Sciscape API
Sciscape implements the SCI protocol 0.1 index interface plus a read-only catalog. Use the sci CLI for publishing, submission, and verification. Policy: /api/policy.
Shared behavior
- All public API responses, including errors and preflight responses, send
Access-Control-Allow-Origin: *and exposeContent-Range,Range-Unit,Retry-After, andLocation. - Errors use
{"error":{"code":"policy_refused","message":"…","retryable":false}}, except catalog routes, which keep PostgREST’s native error contract. - Status codes: 400 malformed request; 403 policy refusal (including
not_baseline); 404 absent record or proof; 409 conflicting state; 413 request or sidecar limit; 422 failed protocol, signature, or content check; 429 rate limit or busy verifier (withRetry-After); 503 temporary failure. - Identifiers are bare 64-character lowercase hex digests; keys are canonical JWK
xvalues; accounts are{"type","id"}objects. - Custom writes follow SCI protocol §7 JSON rules and reject unknown fields and duplicate multipart parts.
Routes
GET /.well-known/sci/index.json
Index descriptor (SCI protocol §8.1) with Sciscape extensions.
Fields from api_schema onward are Sciscape extensions. Templates use the protocol’s {id} expansion.
GET /api/policy
Admission policy, quotas, source restrictions, proof limits, and timestamp trust policy (HTML).
GET /api/protocol
SCI protocol used by this Sciscape release.
Rendered HTML of the protocol bundled at the same commit as Sciscape’s vendored SCI library, with a link to that revision on GitHub. The document updates when the library pin changes.
GET /api/publications/{id}/sources
Publication lookup (SCI protocol §8.1.1), including registered publications outside the catalog.
GET https://sciscape.io/api/publications/<id>/sources
200 {"descriptors":["https://archive.example/.well-known/sci/archive.json"]}
{"descriptors":[]} means no known permitted source (unknown, blocked, or no working location). 400 invalid_id for malformed IDs; 503 if the database is unavailable.
GET /api/keys/{x}/revocation/{file}
Revocation lookup (SCI protocol §8.1.2). Not affected by moderation blocks.
file is revocation.json (served as application/json), revocation.json.sig, or revocation.json.sig.tsr (application/octet-stream). 404 proves nothing about revocation.
GET /api/publications/{id}/timestamps
Retained timestamp proofs (SCI protocol §8.1.3) as one timestamp file, application/octet-stream.
404 when no proof is retained or the publication is not a public catalog entry. Verify proofs under SCI protocol §6.8.
POST /api/submit/publication
Publication submission (SCI protocol §8.1.4). No account login.
POST https://sciscape.io/api/submit/publication
Content-Type: application/json
{"id":"<id>","descriptors":["https://raw.githubusercontent.com/OWNER/REPO/main/sci/archive.json"],
"account":{"type":"domain","id":"lab.example"}}
Success: 201 (new catalog admission) or 200 with id, status (accepted or locations_recorded), publication_url, accepted_at (null outside the catalog), and for locations_recorded a reason (no_qualifying_association, revoked_key) and message.
Errors: 403 policy_refused (with reason), 403 not_baseline, 409, 413, 422 (failed checks; unsupported_schema distinct), 429 with Retry-After (rate limit or busy verifier), 503 (retryable).
POST /api/submit/key_revocation
Key revocation (multipart parts revocation.json, revocation.json.sig, optional revocation.json.sig.tsr).
Verified under SCI protocol §6.7, including for unknown or blocked keys. 200 with x and status: "revoked"; repeats return the same state. Timestamp results are reported separately.
POST /api/submit/timestamp
Timestamp proof submission (multipart parts id and manifest.json.sig.tsr) for admitted publications.
200 with id, retained_count, and per-value results; 404 if the publication is not admitted.
POST /api/submit/report
Mirror-failure or content report (JSON).
{"id":"<id>","kind":"mirror_failure","descriptor":"https://archive.example/.well-known/sci/archive.json","reason":"fetch_failed"}
{"id":"<id>","kind":"content","reason":"Free-text reason, at most 2,000 characters"}
202 with report_id. Mirror reasons match ^[a-z][a-z0-9_]{0,63}$ and the descriptor must be registered for the ID.
GET /api/catalog/{publications|citations|citation_counts|totals}
Read-only PostgREST views of schema sciscape_catalog_v1 (GET, HEAD, and CORS preflight only).
The gateway forces Accept-Profile: sciscape_catalog_v1 and needs no key. PostgREST query syntax, Content-Range, and native errors are preserved; other methods return 405.
GET /api/catalog/publications?id=eq.<id>&select=id,title,abstract,public_key
GET /api/catalog/publications?search_text=plfts(simple).neural%20decoding&order=accepted_at.desc,id.desc&limit=20
GET /api/catalog/publications?admission_accounts=cs.[{"type":"domain","id":"lab.example"}]&order=accepted_at.desc,id.desc&limit=20
GET /api/catalog/publications?categories=cs.[{"scheme":"arxiv","code":"cs.LG"}]&limit=20
GET /api/catalog/publications?public_key->>x=eq.<x>&limit=20
GET /api/catalog/publications?or=(accepted_at.lt.<time>,and(accepted_at.eq.<time>,id.lt.<id>))&order=accepted_at.desc,id.desc&limit=20
GET /api/catalog/citations?source_id=eq.<id>&order=position.asc&limit=100
GET /api/catalog/citations?target_key=eq.sci:sha256:<id>&order=source_id.asc,position.asc&limit=100
GET /api/catalog/citation_counts?target_key=eq.sci:sha256:<id>
GET /api/catalog/totals
publications fields: id, public_key, title, abstract, categories, keywords, display, accepted_at, admission_accounts, current_accounts, publisher_names, association_checked_at, revoked, descriptors, source_status, search_text, citing_publications, citing_publications_24h, citing_publications_48h, citing_publications_7d. Sort by citations with order=citing_publications.desc,accepted_at.desc,id.desc. citations: source_id, position, target, relations, reason, target_key. citation_counts: target_key, count, refreshed_at. totals: publications, citations, updated_at.
GET /p/{id} · /p/{prefix} · /reader?sha={id}[&archive={url}…]
Publication pages, prefix resolution, and the browser reader.
/p/{id}: 200 catalog page, 302 to the reader for registered publications outside the catalog, 404 unknown, 410 blocked, 503 unavailable. /p/{prefix} takes 12–63 lowercase hex characters. /reader accepts only sha and repeated HTTPS archive parameters.