Veratum API Documentation
Welcome to the Veratum API documentation. Veratum provides a comprehensive platform for AI decision transparency, auditability, and compliance through cryptographic receipts and decentralized anchoring.
What is Veratum?
Veratum is an enterprise platform that creates immutable, auditable records of AI decisions. Every decision is captured in a cryptographic receipt, timestamped via RFC 3161, anchored to the XRP Ledger, and backed by W3C Verifiable Credentials for maximum trustworthiness and regulatory compliance.
Key Features
Cryptographic Receipts
Each AI decision generates a cryptographic receipt with SHA-256 hash chains for complete auditability.
RFC 3161 Timestamps
Timestamps provide cryptographic proof of when decisions were made, compliant with international standards.
XRPL Anchoring
Merkle roots are anchored to the XRP Ledger for decentralized, immutable record-keeping.
W3C VC Standards
Verifiable Credentials provide portable, cryptographically signed proof of decisions.
Human Review Workflow
Built-in review system for mandatory or optional human oversight of AI decisions.
eIDAS Compliant
Meets regulatory requirements for qualified electronic signatures and seals.
Base URL
All API requests use the following base URL:
https://api.veratum.ai/v1API Response Format
All responses are returned as JSON with the following structure:
{
"data": { ... },
"error": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}Quick Start Guide
Get up and running with Veratum in just a few minutes.
Step-by-Step Setup
Install the SDK
Install the Python SDK (also available for TypeScript/Node.js):
pip install veratum-sdkInitialize the Client
Create a Veratum client with your API key:
from veratum import VeratumClient
client = VeratumClient(
api_key="vsk_your_api_key_here",
base_url="https://api.veratum.ai/v1"
)Wrap Your AI Client
Use Veratum to wrap your AI client and capture decisions automatically:
from openai import OpenAI
from veratum import VeratumWrapper
ai_client = OpenAI(api_key="sk_...")
wrapped_client = VeratumWrapper(
ai_client=ai_client,
veratum_client=client,
vertical="recruiting",
decision_type="candidate_screening"
)
# All calls now generate cryptographic receipts
response = wrapped_client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Review this candidate..."}]
)Access Receipts
Retrieve receipts and verification data:
# List all receipts
receipts = client.receipts.list()
# Get a specific receipt
receipt = client.receipts.get(entry_hash="abc123...")
# Verify chain integrity
is_valid = client.verify_chain(receipt)
# Get timestamp proof
timestamp = client.timestamps.create(entry_hash=receipt['entry_hash'])
# Request human review if needed
review = client.reviews.create(
entry_hash=receipt['entry_hash'],
review_type="mandatory",
priority="high"
)Next Steps: Read the Authentication guide to understand API key management, then explore the Receipts endpoint documentation for detailed examples.
Authentication
Veratum uses API keys for authentication. All requests must include a valid API key in the Authorization header.
API Key Format
API keys follow the format: vsk_[base64-encoded-32-bytes]
Keys are 60-70 characters long and start with the vsk_ prefix.
Authentication Methods
Bearer Token (Recommended)
Include your API key as a Bearer token in the Authorization header:
Authorization: Bearer vsk_your_api_key_hereKey Validation
Use the /keys/validate endpoint to verify your API key is active:
curl -X POST https://api.veratum.ai/v1/keys/validate \
-H "Authorization: Bearer vsk_your_api_key_here"Hashing & Security
API keys are stored as SHA-256 hashes. During validation, the server:
- Receives your API key in the Authorization header
- Computes SHA-256(api_key)
- Compares against stored hash in the database
- Returns validation result
Important: Always transmit API keys over HTTPS. Never commit API keys to version control. Rotate keys regularly and use separate keys for development, staging, and production environments.
Customer Plans
API keys are associated with customer plans that determine rate limits and feature availability:
- developer: Development and testing (limited rate limits)
- growth: Small-scale production (standard rate limits)
- business: Medium-scale production (high rate limits)
- enterprise: Large-scale production (custom limits)
- regulated: Regulated industries with compliance requirements (custom limits)
Rate Limiting
Veratum implements rate limiting to ensure fair usage and system stability. Rate limits are applied per API key and reset every 60 seconds.
Rate Limits by Endpoint
| Endpoint | Requests per Minute | Notes |
|---|---|---|
| /receipts | 120 | Upload receipts and list existing receipts |
| /customers | 30 | Customer management (admin only) |
| /keys/validate | 60 | Validate API keys |
| /contact | 10 | Contact form submissions |
| default | 60 | All other endpoints |
Rate Limit Headers
All responses include rate limit information in headers:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640100060
Retry-After: 45Exceeding Rate Limits
When you exceed the rate limit, the API returns a 429 (Too Many Requests) response:
{
"error": "Rate limit exceeded. Try again in 60 seconds.",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}Best Practice: Implement exponential backoff in your client code to handle rate limit responses gracefully. When you receive a 429 response, wait for the duration specified in the Retry-After header before retrying.
Health Check
Check the health and status of the Veratum API. This endpoint requires no authentication and is useful for monitoring and load balancing.
Response
{
"status": "healthy",
"version": "1.0.0",
"timestamp": "2024-04-02T14:30:00Z",
"uptime_seconds": 3600
}Examples
curl -X GET https://api.veratum.ai/v1/healthfrom veratum import VeratumClient
client = VeratumClient(base_url="https://api.veratum.ai/v1")
health = client.health.check()
print(health)Receipts
Receipts are cryptographic records of AI decisions. Each receipt contains decision metadata, hashes of prompts/responses, and chain integrity information.
Submit a receipt for an AI decision. Receipts can contain the full decision data including prompts, responses, tokens, AI scores, and human review information.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| receipt | object | Required | Full receipt object with all required fields |
| entry_hash | string | Optional | 64-character hex string (computed from receipt if not provided) |
Response
{
"success": true,
"entry_hash": "abc123def456...",
"storage_url": "s3://veratum-receipts/receipts/cust_xxx/abc123def456.json",
"timestamp": "2024-04-02T14:30:00Z"
}Examples
curl -X POST https://api.veratum.ai/v1/receipts \
-H "Authorization: Bearer vsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"receipt": {
"schema_version": "1.0",
"entry_hash": "abc123...",
"prev_hash": "def456...",
"sequence_no": 1,
"timestamp": "2024-04-02T14:30:00Z",
"model": "gpt-4",
"provider": "openai",
"sdk_version": "1.0.0",
"prompt_hash": "hash1...",
"response_hash": "hash2...",
"tokens_in": 150,
"tokens_out": 250,
"decision_type": "candidate_screening",
"vertical": "recruiting"
}
}'from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
receipt = {
"schema_version": "1.0",
"entry_hash": "abc123...",
"prev_hash": "def456...",
"sequence_no": 1,
"timestamp": "2024-04-02T14:30:00Z",
"model": "gpt-4",
"provider": "openai",
"sdk_version": "1.0.0",
"prompt_hash": "hash1...",
"response_hash": "hash2...",
"tokens_in": 150,
"tokens_out": 250,
"decision_type": "candidate_screening",
"vertical": "recruiting"
}
result = client.receipts.create(receipt=receipt)List all receipts for the authenticated customer. Omit the receipt field and entry_hash to retrieve the list.
Request Body
Send an empty body or minimal metadata to list receipts:
{}Response
{
"receipts": [
{
"schema_version": "1.0",
"entry_hash": "abc123...",
"prev_hash": "def456...",
"sequence_no": 1,
"timestamp": "2024-04-02T14:30:00Z",
...
},
...
]
}Examples
curl -X POST https://api.veratum.ai/v1/receipts \
-H "Authorization: Bearer vsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{}'from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
receipts = client.receipts.list()
for receipt in receipts:
print(f"Entry Hash: {receipt['entry_hash']}")
print(f"Decision: {receipt['decision_type']}")
print(f"Timestamp: {receipt['timestamp']}")Key Validation
Validate an API key and retrieve associated customer information. Useful for verifying key activation and checking plan limits.
Request Body
No body required. Authentication is performed via the Authorization header.
Response
{
"valid": true,
"customer_id": "cust_abc123def456",
"plan": "business"
}Examples
curl -X POST https://api.veratum.ai/v1/keys/validate \
-H "Authorization: Bearer vsk_your_api_key"from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
info = client.keys.validate()
print(f"Valid: {info['valid']}")
print(f"Customer ID: {info['customer_id']}")
print(f"Plan: {info['plan']}")RFC 3161 Timestamps
Generate cryptographic timestamps for receipts using the RFC 3161 standard. Timestamps provide legal proof that a receipt existed at a specific moment in time.
Create an RFC 3161-compatible timestamp token for a receipt entry hash. The timestamp is self-signed by Veratum TSA (Time Stamp Authority) and includes a nonce and serial number for uniqueness.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| entry_hash | string | Required | 64-character hex string from receipt |
Response
{
"timestamp_token": {
"version": 1,
"hash_algorithm": "SHA-256",
"hashed_message": "abc123...",
"timestamp": "2024-04-02T14:30:00Z",
"serial_number": 1712145000000,
"tsa_name": "Veratum TSA v1.0",
"nonce": "randomhexstring"
}
}Examples
curl -X POST https://api.veratum.ai/v1/timestamps \
-H "Authorization: Bearer vsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"entry_hash": "abc123def456..."
}'from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
timestamp = client.timestamps.create(
entry_hash="abc123def456..."
)
print(f"Timestamp: {timestamp['timestamp']}")
print(f"Serial Number: {timestamp['serial_number']}")
print(f"TSA: {timestamp['tsa_name']}")Blockchain Anchoring (XRPL)
Anchor receipt Merkle roots to the XRP Ledger for decentralized, immutable record-keeping. This endpoint is admin-only and requires an admin API key.
Batch multiple receipt hashes and compute a Merkle root, then prepare for anchoring to the XRP Ledger. The Merkle root serves as a cryptographic commitment to all included receipts.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| entry_hashes | array<string> | Required | Array of 64-character hex strings |
Response
{
"anchor_id": "550e8400-e29b-41d4-a716-446655440000",
"merkle_root": "abc123def456...",
"entry_hashes": ["hash1...", "hash2...", ...],
"anchor_time": "2024-04-02T14:30:00Z",
"status": "pending_xrpl",
"proof_map": {
"hash1...": ["left", "right", ...]
}
}Examples
curl -X POST https://api.veratum.ai/v1/anchor \
-H "Authorization: Bearer vsk_admin_key" \
-H "Content-Type: application/json" \
-d '{
"entry_hashes": [
"abc123...",
"def456...",
"ghi789..."
]
}'from veratum import VeratumClient
admin_client = VeratumClient(api_key="vsk_admin_key")
hashes = ["abc123...", "def456...", "ghi789..."]
anchor = admin_client.anchor.create(entry_hashes=hashes)
print(f"Anchor ID: {anchor['anchor_id']}")
print(f"Merkle Root: {anchor['merkle_root']}")
print(f"Status: {anchor['status']}")Human Review Workflow
Request human review of AI decisions. Reviews can be mandatory (must complete before finalizing) or optional (for audit trail).
Create a review request for a receipt. Specify whether the review is mandatory or optional and set priority level.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| entry_hash | string | Required | 64-character hex string from receipt |
| review_type | string | Required | "mandatory" or "optional" |
| priority | string | Optional | "high", "medium" (default), or "low" |
Response
{
"review_id": "rev_abc123def456",
"entry_hash": "abc123...",
"review_type": "mandatory",
"priority": "high",
"status": "pending",
"created_at": "2024-04-02T14:30:00Z"
}Examples
curl -X POST https://api.veratum.ai/v1/reviews \
-H "Authorization: Bearer vsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"entry_hash": "abc123...",
"review_type": "mandatory",
"priority": "high"
}'from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
review = client.reviews.create(
entry_hash="abc123...",
review_type="mandatory",
priority="high"
)
print(f"Review ID: {review['review_id']}")List all pending and completed reviews for the authenticated customer.
Response
{
"reviews": [
{
"review_id": "rev_abc123...",
"entry_hash": "hash1...",
"review_type": "mandatory",
"status": "pending",
"created_at": "2024-04-02T14:30:00Z"
},
...
]
}Examples
curl -X GET https://api.veratum.ai/v1/reviews \
-H "Authorization: Bearer vsk_your_api_key"from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
reviews = client.reviews.list()
for review in reviews:
print(f"Review ID: {review['review_id']}")
print(f"Status: {review['status']}")Submit a decision for a pending review. Only authorized reviewers can submit decisions.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| decision | string | Required | "approved", "rejected", or "escalated" |
| reason | string | Optional | Explanation for the decision |
| override_score | number | Optional | Override the AI score with a reviewer score |
Response
{
"review_id": "rev_abc123...",
"status": "approved",
"decision": "approved",
"reviewer_id": "rev_user_123",
"completed_at": "2024-04-02T14:35:00Z"
}Examples
curl -X POST https://api.veratum.ai/v1/reviews/rev_abc123.../decision \
-H "Authorization: Bearer vsk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"decision": "approved",
"reason": "Decision aligns with company policy",
"override_score": 0.95
}'from veratum import VeratumClient
client = VeratumClient(api_key="vsk_your_api_key")
result = client.reviews.submit_decision(
review_id="rev_abc123...",
decision="approved",
reason="Decision aligns with policy",
override_score=0.95
)Customer Management
All customer management endpoints require admin API key authentication. These endpoints are for account administration only.
Create a new customer account and generate an initial API key. This endpoint is admin-only.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| name | string | Required | Customer contact name |
| string | Required | Customer email address | |
| company | string | Required | Company name |
| plan | string | Optional | Plan tier: "developer", "growth", "business", "enterprise", "regulated" (default: "growth") |
Response
{
"success": true,
"customer_id": "cust_abc123def456",
"api_key": "vsk_xxxxxxxxxxxxxxxx",
"signing_key": "xxxxxxxxxxxxxxxx",
"created_at": "2024-04-02T14:30:00Z"
}Examples
curl -X POST https://api.veratum.ai/v1/customers \
-H "Authorization: Bearer vsk_admin_key" \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"company": "Acme Corp",
"plan": "business"
}'from veratum import VeratumClient
admin_client = VeratumClient(api_key="vsk_admin_key")
customer = admin_client.customers.create(
name="John Doe",
email="john@example.com",
company="Acme Corp",
plan="business"
)
print(f"Customer ID: {customer['customer_id']}")
print(f"API Key: {customer['api_key']}")Retrieve customer information and status.
URL Parameters
| Parameter | Type | Description |
|---|---|---|
| id | string | Customer ID (cust_...) |
Response
{
"customer_id": "cust_abc123def456",
"name": "John Doe",
"email": "john@example.com",
"company": "Acme Corp",
"plan": "business",
"status": "active",
"created_at": "2024-04-02T14:30:00Z"
}Rotate (generate a new) API key for a customer. The old key will be deactivated.
Response
{
"success": true,
"customer_id": "cust_abc123def456",
"api_key": "vsk_new_key_here",
"created_at": "2024-04-02T14:35:00Z"
}Examples
curl -X POST https://api.veratum.ai/v1/customers/cust_abc123.../keys \
-H "Authorization: Bearer vsk_admin_key"from veratum import VeratumClient
admin_client = VeratumClient(api_key="vsk_admin_key")
new_key = admin_client.customers.rotate_key(
customer_id="cust_abc123..."
)
print(f"New API Key: {new_key['api_key']}")Contact Form
Submit a contact form for sales inquiries, support requests, or partnership opportunities. No authentication required.
Request Body
| Field | Type | Status | Description |
|---|---|---|---|
| name | string | Required | Full name |
| company | string | Required | Company name |
| string | Required | Email address | |
| role | string | Required | Job title/role |
| vertical | string | Required | Industry/vertical |
| message | string | Required | Message content |
Response
{
"success": true,
"message": "We'll be in touch within 24 hours.",
"contact_id": "550e8400-e29b-41d4-a716-446655440000"
}Examples
curl -X POST https://api.veratum.ai/v1/contact \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"company": "Tech Corp",
"email": "jane@techcorp.com",
"role": "CTO",
"vertical": "financial-services",
"message": "Interested in learning more about compliance solutions"
}'import requests
response = requests.post(
"https://api.veratum.ai/v1/contact",
json={
"name": "Jane Smith",
"company": "Tech Corp",
"email": "jane@techcorp.com",
"role": "CTO",
"vertical": "financial-services",
"message": "Interested in learning more"
}
)
print(response.json())Receipt Schema
A receipt captures all metadata about an AI decision and includes cryptographic hashes for integrity verification.
Required Fields (22 total)
| Field | Type | Description |
|---|---|---|
| schema_version | string | Receipt schema version (e.g., "1.0") |
| entry_hash | string | SHA-256 hash of the entire receipt (64 hex chars) |
| prev_hash | string | Previous receipt's entry_hash (for chaining) |
| sequence_no | number | Sequential number in the chain (starting at 1) |
| timestamp | string | ISO 8601 timestamp when decision was made |
| model | string | AI model name (e.g., "gpt-4", "claude-3") |
| provider | string | Model provider (e.g., "openai", "anthropic") |
| sdk_version | string | Veratum SDK version used |
| prompt_hash | string | SHA-256 hash of the prompt (64 hex chars) |
| response_hash | string | SHA-256 hash of the response (64 hex chars) |
| tokens_in | number | Number of input tokens consumed |
| tokens_out | number | Number of output tokens generated |
| decision_type | string | Type of decision (e.g., "candidate_screening") |
| vertical | string | Industry vertical (e.g., "recruiting", "finance") |
Optional Fields
| Field | Type | Description |
|---|---|---|
| ai_score | number | AI model's confidence score (0-1) |
| ai_threshold | number | Decision threshold used |
| recruiter_action | string | Action taken by recruiter if applicable |
| human_review_state | string | Status of human review (pending, approved, rejected) |
| reviewer_id | string | ID of human reviewer |
| override_reason | string | Reason if decision was overridden |
| xrpl_tx_hash | string | XRPL transaction hash if anchored |
| signature | string | ECDSA signature of receipt |
| metadata | object | Custom metadata key-value pairs |
Example Receipt
{
"schema_version": "1.0",
"entry_hash": "abc123def456...",
"prev_hash": "789xyz012abc...",
"sequence_no": 42,
"timestamp": "2024-04-02T14:30:00Z",
"model": "gpt-4",
"provider": "openai",
"sdk_version": "1.0.0",
"prompt_hash": "hash1...",
"response_hash": "hash2...",
"tokens_in": 150,
"tokens_out": 250,
"decision_type": "candidate_screening",
"vertical": "recruiting",
"ai_score": 0.87,
"ai_threshold": 0.75,
"human_review_state": "approved",
"reviewer_id": "rev_user_123",
"xrpl_tx_hash": "E1234567890ABCDEF",
"metadata": {
"job_id": "job_123",
"department": "engineering"
}
}Chain Integrity (SHA-256 Hash Chains)
Receipts are linked in a cryptographic chain where each receipt's prev_hash points to the previous receipt's entry_hash. This creates an immutable audit trail.
How it Works
Chain Property: If any receipt in the chain is modified, the hash changes, breaking all subsequent links. This makes tampering immediately obvious.
Verification Process
- Compute Receipt Hash: Calculate SHA-256(receipt_data)
- Verify Chain Link: Check that current receipt's entry_hash matches computed hash
- Check Previous Link: Verify that the current receipt's prev_hash matches the previous receipt's entry_hash
- Repeat: Continue backwards through the chain to the first receipt (which has a null or genesis prev_hash)
Example Chain
Receipt 1:
├─ sequence_no: 1
├─ entry_hash: aaaa...
└─ prev_hash: 0000... (genesis)
Receipt 2:
├─ sequence_no: 2
├─ entry_hash: bbbb...
└─ prev_hash: aaaa... (links to Receipt 1)
Receipt 3:
├─ sequence_no: 3
├─ entry_hash: cccc...
└─ prev_hash: bbbb... (links to Receipt 2)
If Receipt 2 is modified:
├─ entry_hash changes (e.g., bbbb -> bbbb_modified)
└─ Receipt 3's prev_hash no longer matches
└─ Chain is broken! Tampering detected.Verification Code Example
import hashlib
import json
def verify_chain(receipts):
"""Verify integrity of receipt chain."""
for i, receipt in enumerate(receipts):
# Compute expected hash
receipt_copy = receipt.copy()
entry_hash = receipt_copy.pop('entry_hash')
computed = hashlib.sha256(
json.dumps(receipt_copy, sort_keys=True).encode()
).hexdigest()
# Verify chain link
if computed != entry_hash:
return False, f"Receipt {i}: hash mismatch"
# Verify previous link (if not first receipt)
if i > 0 and receipt['prev_hash'] != receipts[i-1]['entry_hash']:
return False, f"Receipt {i}: prev_hash mismatch"
return True, "Chain verified"Five-Layer Proof Stack
Veratum's architecture provides multiple cryptographic layers to ensure AI decisions are trustworthy and auditable across the entire compliance landscape.
Receipt Layer
SHA-256 hash chains create immutable records of every AI decision with full metadata preservation.
Timestamp Layer (RFC 3161)
Cryptographic timestamps provide legal proof of when decisions were made, certified by a Time Stamp Authority (TSA).
W3C Verifiable Credentials
Portable, digitally signed credentials that prove decision authenticity without requiring a central authority. Compatible with decentralized identity systems.
Blockchain Anchoring (XRPL)
Merkle roots of decision batches are anchored to the XRP Ledger for decentralized, immutable, and tamper-evident record-keeping.
eIDAS Compliance
Qualified electronic signatures and seals meet European regulatory requirements for legally binding digital transactions and evidence.
Complementary Technologies
These five layers work together:
- Layer 1 creates an immutable local record
- Layer 2 adds cryptographic time proof
- Layer 3 makes it portable and standardized
- Layer 4 anchors it to a public ledger
- Layer 5 ensures regulatory compliance
Trust Model
The layered approach means even if one layer is compromised, the others provide accountability:
- Receipts alone prove what happened
- Timestamps prove when it happened
- W3C VCs prove who authorized it
- XRPL proves it was publicly committed
- eIDAS compliance satisfies regulators
Error Responses
All error responses follow a consistent format with an error message and request ID for debugging.
Error Response Format
{
"error": "Error message describing what went wrong",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}Common HTTP Status Codes
| Status | Meaning | Example Cause |
|---|---|---|
| 400 | Bad Request | Invalid request body, missing required fields, malformed JSON |
| 401 | Unauthorized | Invalid or missing API key, expired credentials |
| 403 | Forbidden | Insufficient permissions, admin-only endpoint |
| 404 | Not Found | Requested resource doesn't exist, invalid path |
| 409 | Conflict | Resource already exists, duplicate record |
| 413 | Payload Too Large | Request body exceeds 1MB limit |
| 429 | Too Many Requests | Rate limit exceeded, see Retry-After header |
| 500 | Internal Server Error | Unexpected server error, use request_id to debug |
Error Handling Best Practices
- Always include the
request_idwhen reporting issues - Implement exponential backoff for 429 (rate limit) responses
- Log error responses with full context for debugging
- For 500 errors, retry with a slight delay (e.g., 1-5 seconds)
- Validate request format before sending to catch 400 errors early
Example Error Responses
Invalid API Key (401)
{
"error": "Unauthorized",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}Rate Limit Exceeded (429)
{
"error": "Rate limit exceeded. Try again in 60 seconds.",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}Validation Error (400)
{
"error": "Receipt validation failed: Missing field: entry_hash; Invalid field: tokens_in",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}