CLI#

Arguments#

python -m ramose -s <spec.hf|spec.yaml> [options]

Argument

Description

-s, --spec

RAMOSE spec file(s). Required. Accepts .hf, .yaml, and .yml; accepts multiple files.

-c, --call

API call URL, e.g. /v1/metadata/doi:10.1162/qss_a_00292.

-m, --method

HTTP method for the call. Default: get.

-f, --format

Response format: application/json (default) or text/csv.

-d, --doc

Generate HTML documentation. Ignores -m, -c, -f.

--openapi

Export OpenAPI 3.2 YAML specification.

--api-base

Select which API base to export when multiple specs are loaded.

-o, --output

Write response to file instead of stdout.

-w, --webserver

Start Flask server at host:port.

-css, --css

Custom CSS file path for documentation styling.

--debug

Enable Flask debug mode (auto-reload, interactive debugger).

--cache-dir

Directory for result caching. Default: .cache.

--no-cache

Disable result caching entirely.

--cache-ttl

Cache TTL in seconds. Default: 86400 (1 day).

--retry-attempts

Total SPARQL read attempts, including the first one. Applies to standard SPARQL and SPARQL Anything reads. Default: 3; use 1 to disable retries.

--retry-wait

Seconds to wait before the first SPARQL read retry. Applies to standard SPARQL and SPARQL Anything reads. Default: 0.5.

--retry-backoff

Multiplier applied between SPARQL read retry waits. Applies to standard SPARQL and SPARQL Anything reads. Default: 2.0.

--auth-db

Directory for the bearer token store. Default: .auth.

--token-create

Create a bearer token with the given label, print it once, and exit.

--token-ttl

Token lifetime in seconds for --token-create. Default: no expiry.

--token-list

List stored tokens (labels, timestamps, revoked flag) and exit.

--token-revoke

Revoke the given token and exit.

--backend-auth

Per-endpoint backend credential as endpoint_url=header (e.g. https://host/sparql=Bearer <token>). Repeatable. Merged with RAMOSE_BACKEND_AUTH.

Local mode#

Query an endpoint and print the result:

python -m ramose -s meta_v1.hf -c '/v1/metadata/doi:10.1162/qss_a_00292'
# Response HTTP code: 200
# Body:
[{"id": "doi:10.1162/qss_a_00292 omid:br/062104388184", "title": "OpenCitations Meta", ...}]
# Content-type: application/json

Request CSV instead:

python -m ramose -s meta_v1.hf -f text/csv -c '/v1/metadata/doi:10.1162/qss_a_00292'

Save to file:

python -m ramose -s meta_v1.hf -c '/v1/metadata/doi:10.1162/qss_a_00292' -o result.json

Generate HTML documentation:

python -m ramose -s meta_v1.hf -d -o docs.html

Export OpenAPI spec:

python -m ramose -s meta_v1.hf --openapi -o openapi.yaml

Web server#

Start a Flask development server:

python -m ramose -s meta_v1.hf -w 127.0.0.1:8080

This serves:

  • Dashboard at the root (/)

  • API documentation at the API base path (e.g., /v1)

  • API endpoints at their configured paths

  • OpenAPI spec at <api_base>/openapi.yaml (e.g., /v1/openapi.yaml)

Query via curl:

curl -H "Accept: text/csv" "http://localhost:8080/v1/metadata/doi:10.1162/qss_a_00292"

Load multiple APIs at once:

python -m ramose -s meta_v1.hf index_v2.yaml -w 127.0.0.1:8080

Apply custom CSS to the documentation:

python -m ramose -s meta_v1.hf -w 127.0.0.1:8080 -css style.css

Caching#

RAMOSE caches processed query results in a local SQLite-backed store. Subsequent requests for the same query hit the cache instead of re-querying the SPARQL endpoint.

By default, the cache lives in .cache/ in the working directory with a 1-day TTL. Override with:

python -m ramose -s meta_v1.hf -w 127.0.0.1:8080 --cache-dir /tmp/ramose-cache --cache-ttl 3600

To disable caching:

python -m ramose -s meta_v1.hf -w 127.0.0.1:8080 --no-cache

Per-operation cache control is available via #cache_duration and #cache_disable in the spec file.

SPARQL read retries#

RAMOSE retries failed SPARQL read requests before returning an error. Retries apply to standard queries, HTTP SPARQL steps in multi-source queries, and SPARQL Anything read steps. Write operations are not retried.

python -m ramose -s meta_v1.hf -w 127.0.0.1:8080 --retry-attempts 4 --retry-wait 1 --retry-backoff 2

The retry policy covers network errors, timeouts, and backend status codes 408 Request Timeout, 429 Too Many Requests, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout. Status codes such as 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, and 422 Unprocessable Content return without retrying. For SPARQL Anything, RAMOSE classifies failures from Java exception messages because PySPARQL-Anything does not expose HTTP status codes. Per-operation overrides are available through #retry_attempts, #retry_wait, and #retry_backoff in the spec file.

Authentication#

Operations marked #auth required in the spec file need a bearer token. Tokens are kept in a local SQLite store (default .auth/, configurable with --auth-db); RAMOSE stores only their SHA-256 hash, never the token itself. Write operations (POST/PUT/DELETE) should always be protected this way.

Create a token (printed once):

python -m ramose --token-create my-client

Optionally give it a lifetime in seconds:

python -m ramose --token-create my-client --token-ttl 3600

List or revoke tokens:

python -m ramose --token-list
python -m ramose --token-revoke <token>

Call a protected operation by sending the token in the Authorization header:

curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
  -d '{"resource": "https://w3id.org/oc/meta/br/062104388184", "title": "OpenCitations Meta", "identifier": "https://w3id.org/oc/meta/id/062106312420", "scheme": "http://purl.org/spar/datacite/doi", "value": "10.1162/qss_a_00292"}' \
  "http://localhost:8080/bibliography/v1/resources"

Requests with a missing, invalid, or revoked token receive HTTP 401. Operations without #auth stay open.

Backend authentication#

The bearer token above protects the client→RAMOSE boundary. It is unrelated to any credential the SPARQL backend itself requires on the RAMOSE→backend boundary.

QLever, for example, can require an access token for SPARQL Updates. Apache Jena Fuseki and Ontotext GraphDB expose several schemes: HTTP Basic and bearer tokens, plus GraphDB’s own GDB token.

Configure RAMOSE with its own backend credentials, keyed by endpoint URL. The credential applies to both reads and writes.

Each entry is endpoint_url=header, where the header is the full Authorization value RAMOSE sends. RAMOSE does not interpret the scheme, so the value matches whatever the backend expects (Bearer <token>, Basic <base64(user:pass)>, GDB <token>, and so on):

export RAMOSE_BACKEND_AUTH='https://localhost:7019/sparql=Bearer <qlever-access-token>'
python -m ramose -s write_api.hf -w 127.0.0.1:8080

Set several backends with newline-separated entries in the environment variable, or with a repeatable --backend-auth flag:

python -m ramose -s apis.hf -w 127.0.0.1:8080 \
  --backend-auth 'https://qlever.example/sparql=Bearer <token>' \
  --backend-auth 'https://fuseki.example/ds/update=Basic <base64>'