API Reference

All endpoints are JSON over HTTP.


Authentication

All requests require an API key in the Authorization header.

Authorization: Bearer <your-api-key>

API keys are issued during onboarding. Contact hello@chainoffact.com to request access.


Rate Limits

Default rate limits apply per API key.

  • POST /api/events: 1,000 requests per minute
  • GET /api/events/:id: 500 requests per minute
  • POST /api/verify/*: 100 requests per minute
  • POST /api/bundles/evidence: 10 requests per minute

Higher limits available on request for production deployments.


Error Codes

400

Bad Request

Invalid request body or missing required fields.

401

Unauthorized

Missing or invalid API key.

403

Forbidden

API key does not have permission for this operation.

429

Too Many Requests

Rate limit exceeded. Wait and retry.

500

Internal Server Error

Unexpected error. Contact support if persistent.


POST /api/events

Records a new event.

Request

{
  "event_type": "string",
  "subject": "string (optional)",
  "actor": "string (optional)",
  "inputs_hash": "string (optional)",
  "outputs_hash": "string (optional)",
  "policy_id": "string (optional)",
  "policy_version": "string (optional)",
  "metadata": { "key": "value" }
}

Response

{
  "event_id": "uuid",
  "event_hash": "sha256",
  "timestamp_utc": "ISO-8601"
}

The event is immutable once recorded.


GET /api/events/:event_id

Retrieves a previously recorded event.

Response

  • Event object if found
  • { "state": "UNKNOWN" } if not found

POST /api/verify/event

Verifies the integrity of a single event by ID.

Request

{
  "event_id": "uuid"
}

Response

{
  "state": "MATCH | MISMATCH | UNKNOWN"
}

POST /api/verify/chain

Verifies the integrity of the full ledger.

Response

{
  "state": "MATCH | MISMATCH | ABSTAIN | UNKNOWN",
  "event_count": number
}

POST /api/bundles/evidence

Generates a sealed evidence bundle.

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.

Request

For public disclosure, include an explicit intent flag:

{
  "intent": "public_disclosure"
}

This flag must be explicit and is documented as irreversible.

Response

{
  "bundle_id": "uuid",
  "created_utc": "ISO-8601",
  "chain_state": "MATCH | MISMATCH | ABSTAIN | UNKNOWN",
  "download_path": "string"
}

Public Artifact Metadata

Public artifacts include:

  • publication_timestamp
  • originating_org_id
  • disclosure_intent flag

GET /api/bundles/download/:filename

Downloads an evidence bundle ZIP.


GET /api/health

Health and ledger status.

Response

{
  "ok": true,
  "ledger_head": "sha256 | null",
  "mode": "append-only"
}

Examples

Record an Event (curl)

curl -X POST https://api.chainoffact.com/api/events \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "model_inference",
    "subject": "user-123",
    "actor": "gpt-4-turbo",
    "inputs_hash": "sha256:abc123...",
    "outputs_hash": "sha256:def456...",
    "metadata": {"session_id": "sess-789"}
  }'

Record an Event (Python)

import requests

response = requests.post(
    "https://api.chainoffact.com/api/events",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
    },
    json={
        "event_type": "model_inference",
        "subject": "user-123",
        "actor": "gpt-4-turbo",
        "inputs_hash": "sha256:abc123...",
        "outputs_hash": "sha256:def456...",
        "metadata": {"session_id": "sess-789"}
    }
)

result = response.json()
print(f"Event ID: {result['event_id']}")
print(f"Hash: {result['event_hash']}")

Verify Chain Integrity (curl)

curl -X POST https://api.chainoffact.com/api/verify/chain \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Verify Chain Integrity (Python)

import requests

response = requests.post(
    "https://api.chainoffact.com/api/verify/chain",
    headers={"Authorization": "Bearer YOUR_API_KEY"}
)

result = response.json()
print(f"State: {result['state']}")
print(f"Event count: {result['event_count']}")

Generate Evidence Bundle (curl)

curl -X POST https://api.chainoffact.com/api/bundles/evidence \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Generate Evidence Bundle (Python)

import requests

response = requests.post(
    "https://api.chainoffact.com/api/bundles/evidence",
    headers={"Authorization": "Bearer YOUR_API_KEY"}
)

result = response.json()
print(f"Bundle ID: {result['bundle_id']}")
print(f"Download: {result['download_path']}")