API Reference
All endpoints are JSON over HTTP.
Authentication
All authenticated requests require an API key in the x-api-key header.
x-api-key: your-api-key
API keys are issued during onboarding. Visit pricing to subscribe, or contact hello@chainoffact.com.
Rate Limits
Default rate limits apply per API key.
- POST /api/witness: 60 requests per minute
- GET /api/facts/*: 60 requests per minute
- POST /api/verify/*: 60 requests per minute
- POST /api/bundles/facts: 10 requests per minute
Higher limits available on request for production deployments.
Error Codes
Bad Request
Invalid request body or missing required fields.
Unauthorized
Missing or invalid API key.
Conflict
Duplicate witness artifact. This witnessHash has already been recorded.
Too Many Requests
Rate limit exceeded. Wait and retry.
Internal Server Error
Unexpected error. Contact support if persistent.
POST /api/witness
Ingests a verified witness artifact into the fact ledger. Requires API key.
Request
{
"witnessVersion": "string",
"intentHash": "sha256 hex (64 chars)",
"verdictHash": "sha256 hex (optional)",
"commitHash": "sha256 hex",
"executionTarget": "string (optional)",
"executionResultHash": "sha256 hex",
"witnessHash": "sha256 hex",
"timestamp": "ISO-8601 datetime",
"executionReceipt": {
"engineId": "string (optional)",
"enginePublicKey": "string (optional)",
"signature": "string (optional)",
"status": "string (optional)"
}
}
Response (201)
{
"factHash": "sha256",
"factObservedAt": "ISO-8601",
"ledgerRoot": "sha256",
"factCount": number
}
The witness artifact is immutable once recorded. Each produces exactly one canonical fact.
GET /api/facts/:factHash
Retrieves a canonical fact by its hash. Requires API key.
Response
- Canonical fact object if found
{ "state": "UNKNOWN" }if not found
POST /api/verify/fact
Verifies the integrity of a single fact by hash. Public endpoint.
Request
{
"factHash": "sha256 hex (64 chars)"
}
Response
{
"state": "MATCH | MISMATCH | UNKNOWN"
}
POST /api/verify/fact-chain
Verifies the integrity of the full fact ledger. Public endpoint.
Response
{
"state": "MATCH | MISMATCH | ABSTAIN | UNKNOWN",
"fact_count": number
}
GET /api/ledger/root
Returns the current ledger root. Public endpoint.
Response
{
"ledgerRoot": "sha256",
"factCount": number,
"headFactHash": "sha256",
"computedAt": "ISO-8601"
}
POST /api/bundles/facts
Generates a sealed fact evidence bundle. Requires API key.
Public Disclosure Warning
This endpoint may generate a publicly accessible, immutable verification artifact.
Once created:
- The artifact cannot be modified or revoked
- The artifact may be accessed by third parties
- The artifact may be retained indefinitely
ChainOfFact does not evaluate whether publication is appropriate, safe, lawful, or advisable.
You are responsible for determining whether public disclosure is intended.
Response
{
"bundle_id": "uuid",
"created_utc": "ISO-8601",
"chain_state": "MATCH | MISMATCH | ABSTAIN | UNKNOWN",
"download_path": "string"
}
GET /api/bundles/download/:filename
Downloads a fact evidence bundle ZIP. Requires API key.
GET /api/health
Health and ledger status. Public endpoint.
Response
{
"ok": true,
"fact_ledger_head": "sha256 | null",
"fact_count": number,
"mode": "append-only"
}
Examples
Ingest a Witness Artifact (curl)
curl -X POST https://api.chainoffact.com/api/witness \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"witnessVersion": "chainoffact.witness.v1",
"intentHash": "a1b2c3...64 hex chars",
"commitHash": "d4e5f6...64 hex chars",
"executionResultHash": "789abc...64 hex chars",
"witnessHash": "def012...64 hex chars",
"timestamp": "2026-01-29T18:42:00Z"
}'
Ingest a Witness Artifact (Python)
import requests
response = requests.post(
"https://api.chainoffact.com/api/witness",
headers={
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
json={
"witnessVersion": "chainoffact.witness.v1",
"intentHash": "a1b2c3...64 hex chars",
"commitHash": "d4e5f6...64 hex chars",
"executionResultHash": "789abc...64 hex chars",
"witnessHash": "def012...64 hex chars",
"timestamp": "2026-01-29T18:42:00Z"
}
)
result = response.json()
print(f"Fact Hash: {result['factHash']}")
print(f"Ledger Root: {result['ledgerRoot']}")
Verify Fact Chain (curl)
curl -X POST https://api.chainoffact.com/api/verify/fact-chain \
-H "Content-Type: application/json"
Verify Fact Chain (Python)
import requests
response = requests.post(
"https://api.chainoffact.com/api/verify/fact-chain"
)
result = response.json()
print(f"State: {result['state']}")
print(f"Fact count: {result['fact_count']}")
Generate Fact Bundle (curl)
curl -X POST https://api.chainoffact.com/api/bundles/facts \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json"
Generate Fact Bundle (Python)
import requests
response = requests.post(
"https://api.chainoffact.com/api/bundles/facts",
headers={"x-api-key": "YOUR_API_KEY"}
)
result = response.json()
print(f"Bundle ID: {result['bundle_id']}")
print(f"Download: {result['download_path']}")
Direct Answer
ChainOfFact is accessible via a REST API for submitting witness artifacts, retrieving canonical facts, and verifying the complete ledger integrity.
Authentication
All write and read endpoints require an API key via the x-api-key header. API keys use the cof_ prefix and are provisioned via self-serve Stripe checkout. Keys are shown once at creation.
Fact Ingestion
POST /api/witness accepts a verified OpenWitness artifact. The system verifies the witness hash, checks Ed25519 receipt signature if present, and appends the canonical fact to the ledger.
Verification Endpoints
POST /api/verify/fact verifies a single fact hash. POST /api/verify/fact-chain verifies the entire ledger. Both return one of four proof states: MATCH, MISMATCH, ABSTAIN, or UNKNOWN.