Build with VerityRecord API

Integrate document timestamping, verification, and digital sealing into your applications. Free verification tier available — no API key needed.

See what changed in this documentation →

Two-Tier Access Model

Verification endpoints are always free and open. For full API access, authenticate with an API key or session token.

Free Tier

Verification

Verify documents, retrieve certificates, and check transparency logs. No account required.

Free forever
  • Verify receipt integrity (hash + signature)
  • Download PDF certificates
  • Download stamp images
  • Search by short ID or hash
  • Transparency log & inclusion proofs
  • System health & status
10 req/min 500 req/day IP-based

API Capabilities

✅

Verification API

Verify document integrity, retrieve certificates and stamps. Always free, no API key needed. SHA3-256 + HMAC signatures.

💼

Bag API

Create document bags, add files, seal with cryptographic proof. Merkle tree, TSA timestamps, transparency log.

📄

Upload API

Upload files or raw data for timestamping. Single files, bundles, and async link captures with evidence collection.

🔔

Webhook API

Real-time notifications for receipt creation, bag sealing, and sharing events. Exponential backoff retries.

🔗

Link Capture

Archive web pages with full evidence: HTML, PDF, screenshot, structured data. 25+ platform-specific parsers.

🛡

Transparency Log

Public Merkle tree roots and inclusion proofs for independent verification. Cryptographic audit trail.

Quick Start

Free tier — verify a receipt with zero setup:

# Free tier: Verify a receipt (no API key needed)
curl https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta

# Free tier: Download PDF certificate
curl -o cert.pdf https://verityrecord.com/api/receipt/RECEIPT_ID/certificate.pdf

# Standard tier: Upload a file (API key required)
curl -X POST https://verityrecord.com/api/uploadRaw \
  -H "X-API-Key: vr_your_api_key_here" \
  -H "Content-Type: application/pdf" \
  -H "x-file-name: contract.pdf" \
  --data-binary @contract.pdf
// Free tier: Verify a receipt (no API key needed)
const res = await fetch('https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta');
const data = await res.json();
console.log(data.receipt.signature_valid); // true

// Standard tier: Upload a file
const upload = await fetch('https://verityrecord.com/api/uploadRaw', {
  method: 'POST',
  headers: {
    'X-API-Key': 'vr_your_api_key_here',
    'Content-Type': 'application/pdf',
    'x-file-name': 'contract.pdf'
  },
  body: fileBuffer
});
const receipt = await upload.json();
# Free tier: Verify a receipt (no API key needed)
import requests

res = requests.get('https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta')
data = res.json()
print(data['receipt']['signature_valid'])  # True

# Standard tier: Upload a file
with open('contract.pdf', 'rb') as f:
    res = requests.post(
        'https://verityrecord.com/api/uploadRaw',
        headers={
            'X-API-Key': 'vr_your_api_key_here',
            'Content-Type': 'application/pdf',
            'x-file-name': 'contract.pdf'
        },
        data=f.read()
    )
// Free tier: Verify a receipt
resp, _ := http.Get("https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta")
defer resp.Body.Close()

// Standard tier: Upload a file
file, _ := os.ReadFile("contract.pdf")
req, _ := http.NewRequest("POST",
    "https://verityrecord.com/api/uploadRaw",
    bytes.NewReader(file))
req.Header.Set("X-API-Key", "vr_your_api_key_here")
req.Header.Set("Content-Type", "application/pdf")
req.Header.Set("x-file-name", "contract.pdf")
resp, _ = http.DefaultClient.Do(req)
// Free tier: Verify a receipt
$res = file_get_contents('https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta');
$data = json_decode($res, true);
echo $data['receipt']['signature_valid']; // 1

// Standard tier: Upload a file
$ch = curl_init('https://verityrecord.com/api/uploadRaw');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => file_get_contents('contract.pdf'),
    CURLOPT_HTTPHEADER => [
        'X-API-Key: vr_your_api_key_here',
        'Content-Type: application/pdf',
        'x-file-name: contract.pdf'
    ],
    CURLOPT_RETURNTRANSFER => true
]);
$receipt = json_decode(curl_exec($ch), true);
// Free tier: Verify a receipt
var client = new HttpClient();
var res = await client.GetStringAsync(
    "https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta");

// Standard tier: Upload a file
var content = new ByteArrayContent(File.ReadAllBytes("contract.pdf"));
content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
client.DefaultRequestHeaders.Add("X-API-Key", "vr_your_api_key_here");
client.DefaultRequestHeaders.Add("x-file-name", "contract.pdf");
var resp = await client.PostAsync(
    "https://verityrecord.com/api/uploadRaw", content);
# Free tier: Verify a receipt
require 'net/http'
require 'json'

uri = URI('https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta')
data = JSON.parse(Net::HTTP.get(uri))
puts data['receipt']['signature_valid'] # true

# Standard tier: Upload a file
uri = URI('https://verityrecord.com/api/uploadRaw')
req = Net::HTTP::Post.new(uri)
req['X-API-Key'] = 'vr_your_api_key_here'
req['Content-Type'] = 'application/pdf'
req['x-file-name'] = 'contract.pdf'
req.body = File.read('contract.pdf')
// Free tier: Verify a receipt
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://verityrecord.com/api/receipt/RECEIPT_ID/verify-meta"))
    .build();
HttpResponse<String> res = client.send(req, BodyHandlers.ofString());

// Standard tier: Upload a file
HttpRequest upload = HttpRequest.newBuilder()
    .uri(URI.create("https://verityrecord.com/api/uploadRaw"))
    .header("X-API-Key", "vr_your_api_key_here")
    .header("Content-Type", "application/pdf")
    .header("x-file-name", "contract.pdf")
    .POST(BodyPublishers.ofFile(Path.of("contract.pdf")))
    .build();
Response — GET /api/receipt/:id/verify-meta
{ "ok": true, "receipt": { "receipt_id": "abc123def456", "short_id": "VR-A1B2-C3D4", "status": "sealed", "sealed_at": "2026-02-23T10:30:00.000Z", "file_count": 3, "payload_sha256": "a1b2c3d4...", "merkle_root": "e5f6g7h8...", "signature_valid": true, "certificate_url": "https://verityrecord.com/cert?rid=abc123", "tsa": { "status": "verified" } } }

Endpoint Overview

All endpoints are prefixed with https://verityrecord.com/api/. API versioning: /api/v1/ also supported.

MethodEndpointTierDescription
GET/receipt/:id/verify-metaFreeVerify receipt integrity & seal proof
GET/receipt/:id/certificate.pdfFreeDownload PDF certificate
GET/receipt/:id/stamp.pngFreeDownload stamp image
GET/verifyReceipt/:idFreeVerify receipt signature
POST/verifyFreeVerify with provided fields
GET/receipt/by-short/:shortIdFreeFind receipt by short ID
GET/receipt/by-hash/:hashFreeFind receipt by payload hash
GET/transparency/rootsFreePublic daily Merkle roots
GET/transparency/proof/:idFreeInclusion proof for a receipt
Standard Tier Endpoints
POST/bagsStdCreate a new document bag
GET/bags/:idStdGet bag details
POST/bags/:id/filesStdAdd files to a bag
POST/bags/:id/sealStdSeal a bag (creates receipt)
POST/uploadRawStdUpload & timestamp a single file
POST/captureLinkStdCapture & archive a web page
GET/receipt/:idStdGet full receipt details
POST/webhooksStdRegister a webhook endpoint
POST/keysStdCreate a new API key

Authentication

Two authentication methods are supported. Free tier endpoints require no authentication.

API Key (Server-to-Server)

Send your API key in the X-API-Key header or as a Bearer token. Keys start with vr_.

# Option 1: X-API-Key header curl -H "X-API-Key: vr_your_key_here" https://verityrecord.com/api/bags # Option 2: Bearer token curl -H "Authorization: Bearer vr_your_key_here" https://verityrecord.com/api/bags

Session Token (Web / Mobile)

For browser and mobile apps using VerityRecord authentication. Full access to all endpoints.

const token = await auth.getSessionToken(); const res = await fetch('/api/bags', { headers: { 'Authorization': `Bearer ${token}` } });

Rate Limiting

Free-tier and API-key responses include X-RateLimit-* headers. Exceeding a limit returns 429 Too Many Requests with a scope field (minute or daily); daily windows reset at midnight UTC.

Response Headers

X-RateLimit-Limit: 60 X-RateLimit-Remaining: 58 X-RateLimit-Reset: 1708905600 X-API-Tier: standard

Free Tier

10 requests/minute, 500 requests/day per IP address. No authentication needed.

Standard Tier

60 requests/minute, 5,000 requests/day per API key. Custom limits available.

API Scopes

API keys can be restricted with scopes for least-privilege access.

Available Scopes

upload — File upload
receipt:read — Read receipts
receipt:verify — Verify receipts
receipt:download — Download assets
webhook:send — Manage webhooks

Error Handling

All errors follow a consistent JSON format with an ok: false flag and machine-readable code.

Error Response Format
{ "ok": false, "error": "Human-readable error message.", "code": "ERROR_CODE" }

Common Error Codes

AUTH_REQUIRED 401 — Authentication required API_KEY_REQUIRED 401 — API key required for this endpoint FORBIDDEN 403 — Insufficient permissions INSUFFICIENT_SCOPE 403 — API key lacks required scope NOT_FOUND 404 — Resource not found RATE_LIMIT_EXCEEDED 429 — Too many requests API_QUOTA_EXCEEDED 429 — Monthly usage quota exceeded VALIDATION_* 400 — Invalid request parameters (e.g. VALIDATION_MISSING_FIELD, VALIDATION_INVALID_FORMAT)

OpenAPI Specification

Full machine-readable API specification available for import into Postman, Swagger UI, or code generators.

VerityRecord API — OpenAPI 3.0.3 specification with 100+ operations. The file served at /openapi.yaml is always the current version.

Download openapi.yaml

API Key Management

Create and manage API keys for server-to-server integration. Keys provide Standard tier access with configurable scopes and rate limits.

Create an API Key

Authenticate with your account, then create a key with desired scopes.

curl -X POST https://verityrecord.com/api/keys \ -H "Authorization: Bearer <session_token>" \ -H "Content-Type: application/json" \ -d '{ "name": "My Integration", "scopes": ["upload", "receipt:read", "receipt:verify"] }'

Key Format

API keys start with vr_ followed by 32 random hexadecimal characters. Store securely — the full key is shown only once at creation time.

vr_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6

Key Operations

POST /api/keys Create a new API key GET /api/keys List your API keys DEL /api/keys/:id Revoke an API key

Webhooks

Receive real-time HTTP POST notifications when events occur in your account. Requires Standard tier access.

Supported Events

receipt.created A new receipt has been created receipt.ready Receipt processing is complete receipt.failed Receipt processing failed bag.sealed A bag has been sealed bag.shared A bag has been shared

Register a Webhook

curl -X POST https://verityrecord.com/api/webhooks \ -H "X-API-Key: vr_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-server.com/webhook", "events": ["receipt.ready", "bag.sealed"] }'

Delivery & Retries

Webhooks are delivered via HTTP POST with a JSON body. Failed deliveries are retried with exponential backoff (up to 5 attempts within ~30 minutes). Your endpoint must respond with 2xx within 10 seconds.

Webhook Operations

POST /api/webhooks Register a webhook GET /api/webhooks List your webhooks DEL /api/webhooks/:id Delete a webhook GET /api/webhooks/:id/deliveries View delivery history