Publisher API

Integrate TrustAnchor into your publishing workflow. Anchor photos, videos, and documents at the moment of publication — giving your audience a permanent way to verify authenticity.

Getting Started

  1. Create an account (or log in)
  2. Go to Settings and create an API key
  3. Store the key securely — it is only shown once
  4. Use the key to authenticate API requests

Authentication

Pass your API key via the X-API-Key header:

X-API-Key: ta_sk_your_api_key_here

Alternatively, use Authorization: Bearer ta_sk_.... Keys start with ta_sk_ to distinguish them from session tokens.

Base URL

https://api.trustanchor.io

Endpoints

POST /v1/anchor

Upload and anchor a file. Computes SHA-256 hash, pins to IPFS, builds BCMR metadata, and returns a verification short code.

Content-Type: multipart/form-data
Permission: anchor

fileRequired. The file to anchor.
captionOptional. Description (max 500 chars).
Example Response (201)
{
  "anchor_id": 142,
  "short_code": "Ab3xYz",
  "file_hash": "e3b0c44298fc1c149afbf4c8996fb924...",
  "file_name": "press-release.jpg",
  "file_type": "image/jpeg",
  "file_size": 245760,
  "ipfs_cid": "QmYwAPJzv5CZsnA625s3Xf2nem...",
  "ipfs_url": "https://gateway.pinata.cloud/ipfs/QmYw...",
  "bcmr_cid": "QmRbcH8gTk2n4fVp...",
  "status": "uploaded",
  "verify_url": "https://trustanchor.io/verify?code=Ab3xYz",
  "c2pa": false
}
GET /v1/verify/{hash}

Check if a file hash, token category ID, or short code is anchored. API key optional.

Example Response (200)
{
  "found": true,
  "anchors": [
    {
      "id": 142,
      "file_hash_sha256": "e3b0c44298fc1c149afbf4c8...",
      "file_name": "press-release.jpg",
      "short_code": "Ab3xYz",
      "status": "uploaded",
      "created_at": "2026-06-06 14:30:00",
      "handle": "reuters"
    }
  ]
}
GET /v1/anchor/{id}

Get details of a specific anchor. Scoped to your own anchors only.

Permission: anchor

POST /v1/webhook

Register a webhook URL to receive notifications when anchors are created or confirmed on-chain.

Permission: webhook

urlRequired. HTTPS URL to receive POST callbacks.
eventsOptional. Array: ["anchor.created", "anchor.confirmed"]
GET /v1/webhooks

List all your registered webhooks.

DELETE /v1/webhook/{id}

Delete a webhook.

Rate Limits

Each API key has default limits of 30 requests/minute and 1,000 requests/day. Rate limit info is returned in response headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987

When limits are exceeded, the API returns 429 Too Many Requests with a Retry-After header.

Webhook Signatures

Webhook payloads are signed with HMAC-SHA256 using the secret returned when you create the webhook. Verify the signature to ensure the payload is authentic:

X-TrustAnchor-Signature: sha256=<hmac_hex>
X-TrustAnchor-Event: anchor.created
Content-Type: application/json

Events: anchor.created, anchor.confirmed, anchor.failed, or * for all. Webhooks are disabled after 10 consecutive delivery failures.

Quick Start Examples

cURL

# Anchor a file
curl -X POST https://api.trustanchor.io/v1/anchor \
  -H "X-API-Key: ta_sk_your_key_here" \
  -F "file=@photo.jpg" \
  -F "caption=Breaking news photo from city hall"

# Verify a hash
curl https://api.trustanchor.io/v1/verify/e3b0c44298fc1c149afbf4c8996fb924... \
  -H "X-API-Key: ta_sk_your_key_here"

Python

import requests

API_KEY = "ta_sk_your_key_here"
BASE = "https://api.trustanchor.io"

# Anchor a file
with open("photo.jpg", "rb") as f:
    r = requests.post(f"{BASE}/v1/anchor",
        headers={"X-API-Key": API_KEY},
        files={"file": f},
        data={"caption": "Press photo"})
    print(r.json()["verify_url"])

# Verify a hash
r = requests.get(f"{BASE}/v1/verify/{file_hash}",
    headers={"X-API-Key": API_KEY})
print(r.json()["found"])

Node.js

const fs = require('fs');

const API_KEY = 'ta_sk_your_key_here';
const BASE = 'https://api.trustanchor.io';

// Anchor a file
const form = new FormData();
form.append('file', fs.createReadStream('photo.jpg'));
form.append('caption', 'Press photo');

const res = await fetch(`${BASE}/v1/anchor`, {
  method: 'POST',
  headers: { 'X-API-Key': API_KEY },
  body: form,
});
const data = await res.json();
console.log(data.verify_url);

Error Responses

All errors return JSON with an error field:

{ "error": "Monthly anchor limit reached (7). Upgrade your plan for more." }
400Bad request (invalid input)
401Missing or invalid API key
403API key lacks required permission
409File already anchored
413File exceeds plan size limit
422Validation error
429Rate limit exceeded

Plan Limits

API anchoring counts against your plan's monthly verification limit and file size cap.

PlanAnchors/monthMax file size
Free710 MB
Basic5050 MB
Pro200100 MB
Enterprise400+200 MB

Need higher limits? Contact us about Enterprise plans.