Skip to content

REST API Reference

PrimeStamp exposes a FastAPI-based REST API for document stamping, verification, and fingerprinting. Interactive documentation is available at /docs (Swagger UI) and /redoc (ReDoc) when the server is running.

Starting the Server

uvicorn primestamp.api.server:app --reload --host 0.0.0.0 --port 8800

Authentication

Requests are identified by API key or client IP. Include your key in one of these headers:

Header Format
Authorization Bearer ps_live_... or Bearer ps_test_...
X-API-Key ps_live_... or ps_test_...

Unauthenticated requests fall back to IP-based identification and receive the anonymous rate-limit tier. See Rate Limiting for tier details.


Health

GET /health

Returns server health status.

Response (HealthResponse):

{
  "status": "healthy",
  "version": "0.1.0",
  "timestamp": "2026-04-10T12:00:00+00:00"
}

GET /

API root with navigation links.

{
  "name": "PrimeStamp API",
  "version": "0.1.0",
  "docs": "/docs",
  "health": "/health",
  "dashboard": "/dashboard"
}

Stamps

POST /stamps

Create a new document stamp. Upload a file as multipart form data.

Parameters (form/query):

Parameter Type Default Description
file UploadFile required Document to stamp
preset string null casual, standard, archival, or maximum
anchors string null Comma-separated anchor types (e.g. bitcoin,ethereum)
trust_threshold int 5 Minimum trust score required
version string 1.0.0 Document version
generate_fp bool false Generate a Prime-Space fingerprint
identity_id string null Identity for signing

Example (curl):

curl -X POST http://localhost:8800/stamps \
  -F "file=@document.pdf" \
  -F "preset=standard" \
  -F "generate_fp=true"

Response (StampResponse):

{
  "stamp_id": "a1b2c3d4-...",
  "created_at": "2026-04-10T12:00:00+00:00",
  "document_hash": "abc123...",
  "hash_algorithm": "sha3-256",
  "author_public_key": "ed25519:...",
  "is_signed": true,
  "anchors_requested": ["bitcoin", "ethereum"],
  "trust_score": 9,
  "trust_threshold": 5,
  "trust_met": true,
  "has_fingerprint": true,
  "stamp_json": { ... }
}

GET /stamps/{stamp_id}

Retrieve a stamp by its ID.

curl http://localhost:8800/stamps/a1b2c3d4-...

Returns the same StampResponse structure.

POST /stamps/{stamp_id}/verify

Verify a stored stamp, optionally against the original document content.

Parameters:

Parameter Type Description
stamp_id string (path) Stamp ID to verify
file UploadFile (optional) Original document for content hash verification

Response (VerifyResponse):

{
  "is_valid": true,
  "signature_valid": true,
  "content_hash_valid": true,
  "trust_score": 9,
  "trust_threshold": 5,
  "trust_met": true,
  "confirmed_anchors": 2,
  "pending_anchors": 0,
  "details": { ... }
}

POST /verify

Verify a stamp from raw JSON (without needing a stored stamp).

Request body (VerifyRequest):

{
  "stamp_json": { ... }
}

Optionally include a file upload for content hash verification. Response is the same VerifyResponse.


Fingerprints

POST /fingerprint

Generate a Prime-Space fingerprint for a document.

Parameters:

Parameter Type Default Description
file UploadFile required Document to fingerprint
method string hierarchical Decomposition method: hierarchical, flat, content_addressed, semantic

Response (FingerprintResponse):

{
  "standard_hash": "sha3-256:abc123...",
  "merkle_root": "def456...",
  "chunk_count": 12,
  "tree_depth": 4,
  "shadow_scales": [2, 3, 5, 7, 11, 13],
  "entropy": 4.23,
  "decomposition_method": "hierarchical",
  "proofs_available": ["existence", "structure", "similarity"],
  "fingerprint_json": { ... }
}

POST /fingerprint/compare

Compare two fingerprints for structural similarity.

Request body (CompareRequest):

{
  "fingerprint1": { ... },
  "fingerprint2": { ... }
}

Response (CompareResponse):

{
  "similarities": {
    "2": 0.95,
    "3": 0.91,
    "5": 0.88,
    "7": 0.82,
    "11": 0.79,
    "13": 0.76
  },
  "overall_similarity": 0.85,
  "assessment": "Similar - documents share significant structure"
}

Similarity assessments:

Range Assessment
>= 0.9 Very similar -- likely same or nearly identical documents
>= 0.7 Similar -- documents share significant structure
>= 0.5 Somewhat similar -- some structural overlap
< 0.5 Different -- documents have distinct structure

POST /fingerprint/proof

Generate a partial proof from a fingerprint.

Request body (ProofRequest):

{
  "fingerprint_json": { ... },
  "proof_type": "existence",
  "section_index": 3
}

Supported proof types:

Proof Type Required Fields Description
existence section_index Prove a section exists without revealing content
structure scale (default 7) Reveal structure at a shadow resolution
similarity reference_fingerprint Prove similarity to another document

GET /fingerprint/{stamp_id}/shadow/{scale}

Get the shadow transform at a specific prime scale for a stamped document.

curl http://localhost:8800/fingerprint/a1b2c3d4-.../shadow/7
{
  "scale": 7,
  "resolution": "14%",
  "length": 128,
  "hash": "abc123...",
  "values": [42, 17, 89, ...]
}

Identity

POST /identity

Generate a new Ed25519 signing identity.

Response (IdentityResponse):

{
  "public_key": "ed25519:abc123...",
  "created_at": "2026-04-10T12:00:00+00:00"
}

GET /identity/{identity_id}

Retrieve identity information. The identity_id is the first 16 hex characters of the public key.


Configuration

GET /presets

List all available stamp presets.

[
  {
    "name": "casual",
    "description": "...",
    "storage_mode": "local",
    "encryption": "none",
    "anchors": ["rfc3161"],
    "trust_threshold": 2
  },
  ...
]

GET /presets/{name}

Get details for a specific preset (casual, standard, archival, maximum).


Utilities

POST /hash

Hash a document without creating a stamp.

Parameters:

Parameter Type Default Description
file UploadFile required Document to hash
algorithm string sha3-256 sha3-256, sha256, or blake3
{
  "filename": "document.pdf",
  "size_bytes": 102400,
  "algorithm": "sha3-256",
  "hash": "abc123..."
}

Error Responses

All errors return a JSON body with a detail field:

{
  "detail": "Stamp not found"
}
Status Code Meaning
400 Bad request -- invalid parameters or processing error
404 Resource not found
429 Rate limit exceeded (see Rate Limiting)

Verification Portal

PrimeStamp provides a public verification portal where anyone can verify a stamp by visiting its URL. The portal is served at /verify/{stamp_id} and does not require authentication.

Verification URL Format

https://primestamp.io/verify/{stamp_id}

The base URL is configurable via the PRIMESTAMP_BASE_URL environment variable. In self-hosted deployments, set this to your own domain:

export PRIMESTAMP_BASE_URL=https://verify.mycompany.com

GET /verify/{stamp_id}

Renders an HTML page showing the stamp's verification status, document hash, anchor timeline, and trust score. This page is designed for sharing with third parties who need to confirm document authenticity without installing PrimeStamp.

The portal is implemented in primestamp/web/verify_portal.py and can be deployed alongside the API server or as a standalone service.


Vault

The Vault API provides dead man's switch key escrow. Vaults hold encrypted keys that are released when heartbeat deadlines expire or upon manual release.

POST /vault/create

Create a new vault.

Request body (CreateVaultRequest):

{
  "encrypted_key": "<base64-encoded encrypted key>",
  "heartbeat_deadline": 259200,
  "content_uris": ["ipfs://Qm...", "arweave://tx123"],
  "allow_manual_release": true,
  "metadata": {
    "label": "project-keys"
  }
}
Field Type Required Description
encrypted_key string (base64) yes The encrypted key material to escrow
heartbeat_deadline int yes Seconds until release if no heartbeat is received
content_uris string[] no URIs pointing to the encrypted content (IPFS, Arweave, S3, etc.)
allow_manual_release bool no Whether the vault owner can trigger early release (default false)
metadata object no Arbitrary key-value metadata

Response (VaultResponse):

{
  "id": "vault-a1b2c3d4...",
  "state": "active",
  "created_at": "2026-04-10T12:00:00+00:00",
  "deadline": "2026-04-13T12:00:00+00:00",
  "content_uris": ["ipfs://Qm...", "arweave://tx123"],
  "allow_manual_release": true,
  "metadata": {"label": "project-keys"}
}

POST /vault/{id}/heartbeat

Submit a heartbeat to extend the vault deadline. A mandatory fee is required with each heartbeat.

Path parameters:

Parameter Type Description
id string Vault ID

Request body (HeartbeatRequest):

{
  "fee_receipt": "tx_receipt_abc123"
}

Response (HeartbeatReceipt):

{
  "vault_id": "vault-a1b2c3d4...",
  "heartbeat_at": "2026-04-11T12:00:00+00:00",
  "next_deadline": "2026-04-14T12:00:00+00:00",
  "fee_amount": "0.001",
  "fee_currency": "ETH"
}

POST /vault/batch-heartbeat

Submit heartbeats for multiple vaults in a single request.

Request body (BatchHeartbeatRequest):

{
  "vault_ids": ["vault-aaa...", "vault-bbb...", "vault-ccc..."],
  "fee_receipt": "tx_receipt_batch456"
}

Response (BatchHeartbeatResult):

{
  "renewed": 3,
  "failed": 0,
  "results": [
    {"vault_id": "vault-aaa...", "next_deadline": "2026-04-14T12:00:00+00:00"},
    {"vault_id": "vault-bbb...", "next_deadline": "2026-04-14T12:00:00+00:00"},
    {"vault_id": "vault-ccc...", "next_deadline": "2026-04-14T12:00:00+00:00"}
  ],
  "errors": []
}

GET /vault/{id}

Get the current status of a vault.

Path parameters:

Parameter Type Description
id string Vault ID

Response (VaultResponse):

{
  "id": "vault-a1b2c3d4...",
  "state": "active",
  "created_at": "2026-04-10T12:00:00+00:00",
  "deadline": "2026-04-14T12:00:00+00:00",
  "last_heartbeat": "2026-04-11T12:00:00+00:00",
  "heartbeat_count": 2,
  "content_uris": ["ipfs://Qm...", "arweave://tx123"],
  "allow_manual_release": true,
  "metadata": {"label": "project-keys"}
}

Vault states: active, released, burned, expired.

POST /vault/{id}/release

Manually release the vault key. Only available when allow_manual_release was set to true at creation.

Path parameters:

Parameter Type Description
id string Vault ID

Request body (ReleaseRequest):

{
  "reason": "Project handover"
}

Response (ReleaseResult):

{
  "vault_id": "vault-a1b2c3d4...",
  "released": true,
  "released_at": "2026-04-11T15:00:00+00:00",
  "reason": "Project handover"
}

POST /vault/{id}/retrieve

Retrieve the escrowed key from a released or expired vault.

Path parameters:

Parameter Type Description
id string Vault ID

Request body (RetrieveRequest):

{
  "proof_of_identity": "<base64-encoded identity proof>"
}

Response (RetrievedKey):

{
  "vault_id": "vault-a1b2c3d4...",
  "encrypted_key": "<base64-encoded encrypted key>",
  "released_at": "2026-04-11T15:00:00+00:00"
}

GET /vault/list

List vaults belonging to the authenticated user.

Query parameters:

Parameter Type Default Description
state string null Filter by state: active, released, burned, expired
limit int 50 Maximum number of results
offset int 0 Pagination offset

Response (VaultList):

{
  "items": [
    {
      "id": "vault-a1b2c3d4...",
      "state": "active",
      "deadline": "2026-04-14T12:00:00+00:00",
      "heartbeat_count": 2
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

POST /vault/group/create

Create a heartbeat group to manage multiple vaults with a shared schedule.

Request body (HeartbeatGroupRequest):

{
  "name": "production-vaults",
  "vault_ids": ["vault-aaa...", "vault-bbb..."],
  "interval": 172800
}

Response (HeartbeatGroup):

{
  "id": "group-xyz789...",
  "name": "production-vaults",
  "vault_ids": ["vault-aaa...", "vault-bbb..."],
  "interval": 172800,
  "created_at": "2026-04-10T12:00:00+00:00"
}

GET /vault/fees

Get current vault fee schedule.

Response (VaultFees):

{
  "create_fee": "0.005",
  "heartbeat_fee": "0.001",
  "batch_discount": "0.10",
  "currency": "ETH",
  "fee_recipient": "0xabc..."
}

POST /vault/{id}/add-mirror

Add a content URI mirror to an existing vault for redundant storage.

Path parameters:

Parameter Type Description
id string Vault ID

Request body:

{
  "uri": "s3://bucket/backup-key.enc"
}

Response:

{
  "vault_id": "vault-a1b2c3d4...",
  "content_uris": ["ipfs://Qm...", "arweave://tx123", "s3://bucket/backup-key.enc"]
}

Explorer

The Explorer API provides public read-only access to vault and network statistics.

GET /explorer/api/vaults

List publicly visible vaults.

Query parameters:

Parameter Type Default Description
limit int 100 Maximum number of results
offset int 0 Pagination offset
state string null Filter by state

Response:

{
  "items": [
    {
      "id": "vault-a1b2c3d4...",
      "state": "active",
      "created_at": "2026-04-10T12:00:00+00:00",
      "deadline": "2026-04-14T12:00:00+00:00",
      "heartbeat_count": 2
    }
  ],
  "total": 250,
  "limit": 100,
  "offset": 0
}

GET /explorer/api/stats

Get aggregate network statistics.

Response:

{
  "active_vaults": 1523,
  "total_vaults": 4210,
  "total_heartbeats": 89432,
  "total_releases": 312,
  "total_burns": 45,
  "total_fees_collected": "42.5",
  "fee_currency": "ETH"
}

CORS

The server enables CORS for all origins by default. Configure allow_origins in production.