API Documentation

Truestamp provides REST and GraphQL APIs for programmatic access to our cryptographic timestamping services.

Prefer a command line?

Using your API key, the Truestamp CLI handles creating, downloading, and verifying proofs without writing any API code.

Explore the CLI

Working with an AI agent?

Connect Claude Code, Claude Desktop, or another MCP client to Truestamp and work in your own chat session.

Connect an agent

Choose Your API

Select an API style to see tailored examples throughout this page.

REST API

Full-service JSON:API compliant interface for CRUD operations, relationships, and filtering.

GraphQL API

Full-service API with flexible queries, introspection, partial responses, and nested relationships.

Feature REST GraphQL
Endpoint /api/json/items /gql
Content-Type application/vnd.api+json application/json
Request format JSON:API envelope GraphQL mutation
Response format JSON:API envelope GraphQL response
Best for Full-service CRUD, relationships, filtering Full-service flexible queries, partial responses

Getting Started

1. Generate API Key

All API endpoints require authentication. First, create an account or sign in. Then visit your API keys page to generate an API key. Choose an appropriate expiration time and store the key securely.

Security: Never expose API keys in client-side code or public repositories.

2. Authentication

Include your API key in the request headers:

curl -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Accept: application/vnd.api+json" \
     https://www.truestamp.com/api/json/items

3. Multi-Tenant Operations

Truestamp supports multi-tenant operations. You can specify a tenant (team) using headers or query parameters:

# Using tenant header
curl -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Accept: application/vnd.api+json" \
     -H "tenant: TEAM_ID" \
     https://www.truestamp.com/api/json/items

        
# Using query parameter
curl -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Accept: application/vnd.api+json" \
     "https://www.truestamp.com/api/json/items?tenant=TEAM_ID"

Automatic Tenant Fallback

If no tenant is specified, operations automatically use your personal team. You must have access to any team you specify in requests.

4. Rate Limiting

All API requests are rate limited. Limits are determined by your account's subscription plan and its entitlements.

Plan Items / Month Teams Members / Team
Free 50 1 1
Starter 750 5 5
Pro 10,000 20 50
Enterprise 100,000 100 500

When a rate limit is exceeded, the API returns a 429 Too Many Requests response. Contact support if you need higher limits.

Core Operations

Timestamping Items

Create cryptographic timestamps for your data:

# Create a new Item via REST API
curl -X POST \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Accept: application/vnd.api+json" \
     -H "Content-Type: application/vnd.api+json" \
     -H "tenant: TEAM_ID" \
     -d '{
       "data": {
         "attributes": {
           "claims": {
             "name": "document.pdf",
             "description": "Important document to timestamp",
             "hash": "98a9396c68596891dabb177924e5604438ae394f42aa651574a653e221f81955",
             "hash_type": "sha256"
           }
         }
       }
     }' \
     https://www.truestamp.com/api/json/items

Generating and Verifying Proofs

Generate a proof for any committed subject. You must declare the subject type; there is no auto-detection. Pass the whole proof object back to verify it, exactly as produced.

# Generate a proof for a committed Item
curl -X POST \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Accept: application/vnd.api+json" \
     -H "Content-Type: application/vnd.api+json" \
     -d '{
       "data": {
         "id": "01JQ8ZK3M4N5P6Q7R8S9T0V1W2",
         "type": "item",
         "witnesses": ["block", "entropy_nist"]
       }
     }' \
     https://www.truestamp.com/api/json/proof/generate

        
# Verify it, passing the proof back unchanged
curl -X POST \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Accept: application/vnd.api+json" \
     -H "Content-Type: application/vnd.api+json" \
     -d '{
       "data": {
         "proof": { ...the result object from generate... },
         "skip_external": false
       }
     }' \
     https://www.truestamp.com/api/json/proof/verify

Choosing witnesses

A witness is a public record that existed before the submission and that the item's fingerprint commits to. Witnesses open the submitted-after edge of the submission window, and an item commits to one hash per witness when it is submitted. The optional witnesses argument chooses which of those witnesses' underlying detail rides in the bundle.

  • Omit the argument to carry every witness, so a downloaded proof stands alone. This is the default.
  • Pass an empty array to carry none. The compact bundle still proves the data and the submitted-before edge, but the submitted-after edge is not established from the bundle by itself.
  • Pass a subset of the names below to choose.
Witness What a confirmed witness establishes
block The head block existed before the submission, and the containing block's position in the ledger follows it.
entropy_stellar The item was submitted after the Stellar ledger's close time.
entropy_nist The item was submitted after the NIST beacon pulse's publication time.
entropy_bitcoin The item was submitted after the Bitcoin block header time, read conservatively: a header time may run up to two hours ahead of real time.
signing_key_event The key that signed the proof was introduced by a key event recorded in the ledger and committed to a public blockchain.

An unrecognized name is rejected. Asking for a witness the subject never captured simply omits it. For block, beacon and entropy subjects only signing_key_event applies; the other names are ignored.

What a proof bundle carries

Nothing in a bundle is opaque: every hash a verifier meets is recomputed from bytes the bundle carries, which is why the metadata maps ride along and neither a metadata hash nor a block hash does.

"version": 1,
"type": "item",
"generated_at": "2026-09-02T18:04:11Z",
"public_key": "<base64 Ed25519 public key>",
"signature": "<base64 Ed25519 signature>",
"subject": {
  "id": "01JQ8ZK3M4N5P6Q7R8S9T0V1W2",
  "claims": { "name": "document.pdf", "hash": "98a939...", "hash_type": "sha256" },
  "metadata": { "witnesses": { "block": "4ce272...", "entropy_nist": "7c19e4..." } },
  "signing_key_id": "1a2b3c4d",
  "witnesses": {
    "block": { "id": "...", "previous_block_hash": "...", "merkle_root": "...",
               "metadata": {}, "signing_key_id": "1a2b3c4d" },
    "entropy_nist": { "pulse": { ...the captured payload... } }
  }
},
"inclusion_proof": "<base64url compact Merkle proof>",
"block": { "id": "...", "previous_block_hash": "...", "merkle_root": "...",
           "metadata": {}, "signing_key_id": "1a2b3c4d" },
"block_path": [ ...block maps, oldest first... ],
"commitments": [
  { "chain": "stellar", "epoch_merkle_root": "...", "epoch_proof": "...",
    "transaction_hash": "...", "network": "public", "ledger": 56789012,
    "timestamp": "2026-09-02T18:05:00Z" }
],
"signing_key_event": { "block": { ... }, "commitments": [ ... ] }

      
  • subject and inclusion_proof are absent for block and beacon proofs. An entropy subject carries subject.entropy where an item carries subject.claims.
  • block_path appears only when the item's head block is not the containing block's direct predecessor. Entries are ordered oldest first, each one's previous_block_hash naming the hash of the one before it.
  • commitments is always present and non-empty. epoch_merkle_root is the value written on chain on both Stellar and Bitcoin: one key, with no per-chain spelling to dispatch on. Stellar adds ledger; Bitcoin adds block_height, txoutproof, raw_transaction and block_merkle_root.
  • Version 1 is the first published format. Pass a proof to a verifier exactly as produced: never reorder, truncate, or reformat it.

Response Formats

Our REST API follows the JSON:API specification for consistent, standardized responses:

"data": {
  "attributes": {
    "state": "created",
    "signature": "5mqfG/XJ8cB3Aopn...E5D68KB9YVDA==",
    "metadata": {
      "witnesses": {
        "block": "4ce272402f4e3e372148c495712ae37e1568d314bce1c38a3ac758c77720c3c8",
        "entropy_stellar": "b0f4a1c8d92e37561ac0d3f8e27b45901cd6e83a4f21b70d9e5c8a3612fd47be",
        "entropy_nist": "7c19e4b6208af35d1e97c02b4a8df631059e2c7d84b0136fae92c5807d3b41a6",
        "entropy_bitcoin": "35d8c7092f1ba46e83c05d719ae2f6408b3d1c9075e4a2fb861d09c34e7b52af"
      }
    },
    "tags": [],
    "visibility": "private",
    "merkle_proof": null,
    "display_name": "document.pdf",
    "team_id": "019c2a4b-e079-79d8-b305-44144ac61cca",
    "item_hash": "6aacebc6571e4aa68a3b85cd4d73442e97d5ea4de1590d52f4be1d45a04f266b",
    "display_description": "Important document to timestamp",
    "claims": {
      "name": "document.pdf",
      "description": "Important document to timestamp",
      "hash": "98a9396c68596891dabb177924e5604438ae394f42aa651574a653e221f81955",
      "hash_type": "sha256"
    },
    "claims_hash": "d1c3628c7050d075806a815b042775490df73ea54c1b6a0660344e5c20a3dfda",
    "metadata_hash": "4f8508a334dcd379043c61bb3268446d99094aec9559d7e04df374355d439712"
  },
  "id": "019c5d69-240f-71c4-be75-40684764518f",
  "type": "item",
  "relationships": {
    "block": {},
    "team": {},
    "creator": {}
  }
}

Documentation & Resources

Interactive Tools

Learn More

Error Handling

Status Code Description Common Causes
401 Unauthorized Missing or invalid API key
403 Forbidden Insufficient permissions for tenant/resource
400 Bad Request Invalid request format or missing required fields
422 Unprocessable Entity Validation errors in request data
429 Too Many Requests Rate limit exceeded

Support and Resources

Need Help?

Get support for API integration questions and technical issues.

Get Support