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/v1

API 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

1

Install the SDK

Install the Python SDK (also available for TypeScript/Node.js):

pip install veratum-sdk
2

Initialize 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" )
3

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..."}] )
4

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_here

Key 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:

  1. Receives your API key in the Authorization header
  2. Computes SHA-256(api_key)
  3. Compares against stored hash in the database
  4. 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: 45

Exceeding 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

GET /health No Auth

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/health
from 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.

POST /receipts API Key Required

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)
POST /receipts API Key Required

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

POST /keys/validate API Key Required

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.

POST /timestamps API Key Required

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.

POST /anchor Admin Key Required

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).

POST /reviews API Key Required

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']}")
GET /reviews API Key Required

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']}")
POST /reviews/{id}/decision API Key Required

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.

POST /customers Admin Key Required

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
email 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']}")
GET /customers/{id} Admin Key Required

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" }
POST /customers/{id}/keys Admin Key Required

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

POST /contact No Auth

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
email 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

  1. Compute Receipt Hash: Calculate SHA-256(receipt_data)
  2. Verify Chain Link: Check that current receipt's entry_hash matches computed hash
  3. Check Previous Link: Verify that the current receipt's prev_hash matches the previous receipt's entry_hash
  4. 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.

1

Receipt Layer

SHA-256 hash chains create immutable records of every AI decision with full metadata preservation.

2

Timestamp Layer (RFC 3161)

Cryptographic timestamps provide legal proof of when decisions were made, certified by a Time Stamp Authority (TSA).

3

W3C Verifiable Credentials

Portable, digitally signed credentials that prove decision authenticity without requiring a central authority. Compatible with decentralized identity systems.

4

Blockchain Anchoring (XRPL)

Merkle roots of decision batches are anchored to the XRP Ledger for decentralized, immutable, and tamper-evident record-keeping.

5

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

  1. Always include the request_id when reporting issues
  2. Implement exponential backoff for 429 (rate limit) responses
  3. Log error responses with full context for debugging
  4. For 500 errors, retry with a slight delay (e.g., 1-5 seconds)
  5. 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" }