Evidence & signatures
Download evidence objects by SHA-256 digest, read execution attestations, and verify signatures.
CiteArk evidence objects and execution attestations are both content-addressed. The digest path parameter of both endpoints is 64 lowercase hex characters (without the sha256: prefix); malformed digests return 400.
Authentication
- Objects and attestations of public repositories are directly accessible without signing in.
- Objects and attestations of private repositories require a browser session or
x-api-keywith read permission; otherwise403.
GET /api/objects/{digest}
Download evidence, or objects whose license permits redistribution, by content digest. Paper PDFs whose license does not allow redistribution can only be downloaded by the owner / organization members; everyone else gets 451 {"error": "the paper license does not allow CiteArk to redistribute it; please visit the original source"}.
Example
curl -OJ https://citeark.co/api/objects/<64-char-hex-digest>Response
200 returns a binary stream with headers:
| Header | Description |
|---|---|
| content-type | The object's original mediaType |
| content-length | Length in bytes |
| content-disposition | attachment, with filename <hex>.pdf or <hex>.bin |
| etag | "<hex>", identical to the digest |
| x-content-sha256 | sha256:<hex>; can be used to verify download integrity |
| x-content-type-options | nosniff |
| cache-control | Public objects: public, max-age=31536000, immutable; private objects: private, no-store |
Conditional requests with If-None-Match are supported: when the ETag matches, returns 304.
Errors
| Code | Meaning |
|---|---|
| 400 | Invalid digest format |
| 403 | No permission to read this object |
| 404 | Object does not exist |
| 451 | Paper license does not allow redistribution |
| 502 | Object integrity check failed |
GET /api/attestations/{digest}
Read the execution attestation of a run by statement digest; the server re-verifies the signature.
Example
curl https://citeark.co/api/attestations/<64-char-hex-digest>Response
200 returns { "attestation": { ... }, "verified": true, "verificationMethod": "…" }:
| Field | Description |
|---|---|
| attestation.statementDigest | Statement digest (sha256: prefixed) |
| attestation.nodeId | Signing node ID |
| attestation.keyId | Signing key ID |
| attestation.algorithm | ed25519 / ecdsa-p256 / pending |
| attestation.signature | Signature value |
| attestation.publicKeyPem | Signing public key (PEM) |
| attestation.statement | The signed statement content |
| attestation.signedAt | Signing time (ISO 8601) |
| attestation.transparencyLog | Transparency Log position: index, entryDigest, previousEntryDigest |
| verified | Result of the server's live signature verification |
| verificationMethod | Always ECDSA P-256 over CiteArk canonical JSON |
{
"attestation": {
"statementDigest": "sha256:…",
"nodeId": "…",
"keyId": "…",
"algorithm": "ecdsa-p256",
"signature": "…",
"publicKeyPem": "…",
"statement": { "…": "…" },
"signedAt": "…",
"transparencyLog": { "index": 12, "entryDigest": "sha256:…", "previousEntryDigest": "sha256:…" }
},
"verified": true,
"verificationMethod": "ECDSA P-256 over CiteArk canonical JSON"
}Caching: public repositories public, max-age=300; private repositories private, no-store.
Errors
| Code | Meaning |
|---|---|
| 400 | Invalid digest format |
| 403 | No permission to read this attestation |
| 404 | Attestation does not exist |
Notes
- Both
x-content-sha256and the ETag come from the digest registered when the server stored the object. After downloading, you can recompute the SHA-256 yourself and compare, confirming that transfer and storage were not tampered with. - The attestation's
verifiedfield is the server's verification result; for independent verification, extractpublicKeyPem,signature, andstatementand verify the signature yourself.
Post-reproduction extensions
GET /api/repository-extensions?repositoryId=... returns extension availability, automatic-trigger preferences and current-input runs. research-visualization subscribes to reproduction completion and evidence updates by default. Its output is a derived presentation, not a scientific Assessment.
Repository managers can use an API key to request generation with POST /api/repository-extensions and { "repositoryId": "...", "extensionId": "research-visualization" }, or change automatic generation with PATCH on the same endpoint and { "repositoryId": "...", "extensionId": "research-visualization", "enabled": false }. Disabling affects future automatic requests, not already queued work. Enabling queues a check of existing completed results; unchanged input reuses the existing run. Historical papers are not bulk-generated on deployment.
GET /api/repository-extensions/runs/{runId}/view renders research visualizations from their verified, immutable manifest using the current presentation layer. x-content-sha256 identifies the returned HTML bytes; x-source-manifest-sha256 identifies the stored source manifest, and x-visualization-presentation identifies the viewer version. Presentation updates do not rerun experiments or overwrite archived outputs. Access still follows repository visibility, with private, no-store caching and a sandboxed document.
The research-reading-v2 version of research-visualization saves five reader destinations (overview, methods, evidence, reuse, further research) in a single generated plan. The agent chooses source-backed narrative blocks and charts; the platform validates references. Previous same-input visualizations remain readable while managers can request the new version through the existing POST endpoint. Reading a saved report never invokes a model.
The saved research manifest is available through GET /api/repository-extensions/runs/{runId}/view?format=json, with the same repository permissions and digest checks as the HTML view. The native Learn tab reads this saved content without starting generation.