API
Public API
The production API origin for SDKs and public verification is
https://verify.attesto.eu. Tenant browser workflows live
on https://dashboard.attesto.eu.
Origins
| Origin | Purpose |
|---|---|
https://verify.attesto.eu | Public API, health, signing public key, v1 proof verification, v2 Proofstream verification. |
https://dashboard.attesto.eu | Tenant dashboard, system registration, key reveal-once, exports, webhooks, connectors, billing. |
https://audit.attesto.eu | Auditor-facing portal for invited external auditors. |
Authentication
Server-side event ingest uses a tenant system key in the
Authorization: Bearer header. Public verification routes
validate supplied proof objects and do not require tenant cookies.
curl -X POST https://verify.attesto.eu/v1/sdk/events \
-H "Authorization: Bearer $ATTESTO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $ATTESTO_IDEMPOTENCY_KEY" \
--data-binary @event.json
Idempotency and replay behavior
Write routes accept Idempotency-Key. Repeating the same
key with the same canonical request returns the original result.
Repeating the same key with a different request fails as a conflict.
This protects connector retries and server-side job retries from
creating duplicate evidence.
| Case | Result |
|---|---|
| Same key, same request | Original response is replayed. |
| Same key, changed payload | 409 Conflict. |
| No key on write path | Request is rejected when the route requires dedupe. |
v1 event ingest
Use v1 when you need the stable event audit trail and anchoring path. SDKs set defaults for event type, status, retries, and idempotency.
POST /v1/sdk/eventslogs one event.POST /v1/sdk/events/batchlogs up to 1000 events.GET /v1/events/{eventId}/proofreturns anchored proof material for an event.POST /v1/public/verifyverifies a v1 proof object.
Minimal event body:
{
"type": "ai.decision",
"status": "verified",
"occurred_at": "2026-06-07T12:00:00Z",
"source_ref": "case-2026-0001",
"payload": {
"model": "risk-classifier-v4",
"decision": "manual_review",
"policy_id": "policy-2026-01"
}
}
v2 Proofstream
Proofstream adds append-only streams, signed receipts, windows, checkpoints, witness evidence, anchors, bundles, and offline verification.
POST /v2/streamscreates a stream.POST /v2/streams/{streamId}/eventsappends one event and returns a signed receipt.POST /v2/streams/{streamId}/events/batchappends multiple events with receipt results.GET /v2/receipts/{eventId}returns the stored receipt.GET /v2/windows/{windowId}returns window evidence and inclusion material.GET /v2/checkpoints/{checkpointId}returns checkpoint evidence.GET /v2/checkpoints/{checkpointId}/consistency?from=...returns consistency evidence.POST /v2/audit/packscreates an offline verifier bundle when the range has the required witness and anchor evidence.POST /v2/verifyverifies receipt, stream, checkpoint, consistency, anchor, IVC, or bundle objects.
Create a stream:
curl -X POST https://verify.attesto.eu/v2/streams \
-H "Authorization: Bearer $ATTESTO_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<JSON
{
"system_id": "sys_...",
"use_case": "ai-decision-history",
"policy_id": "policy-2026-01",
"metadata": {
"owner": "risk-platform",
"environment": "production"
}
}
JSON
Append an event:
curl -X POST https://verify.attesto.eu/v2/streams/$STREAM_ID/events \
-H "Authorization: Bearer $ATTESTO_API_KEY" \
-H "Idempotency-Key: $ATTESTO_IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<JSON
{
"source_ref": "case-2026-0001:decision-1",
"event_type": "ai.decision",
"payload": {
"decision": "manual_review",
"score": 91,
"policy_id": "policy-2026-01"
}
}
JSON
Receipt response shape:
{
"stream_event_id": "sev_...",
"stream_id": "str_...",
"seq_no": 1,
"event_hash": "sha256-hex",
"stream_head_hash": "sha256-hex",
"receipt": {
"protocol": "ATTESTO-PROOFSTREAM-001",
"alg": "Ed25519",
"kid": "proofstream-receipt-key",
"signature": "hex-encoded-signature"
}
}
Verification behavior
Verification fails closed on malformed objects, changed payloads, changed sequence numbers, removed or inserted events, stale checkpoints, wrong witness signatures, wrong anchors, and ambiguous fork evidence.
curl -X POST https://verify.attesto.eu/v2/verify \
-H "Content-Type: application/json" \
--data-binary @attesto-bundle.json
Error semantics
| Status | Meaning | Integrator action |
|---|---|---|
400 | Malformed request or unsupported verifier object. | Fix request shape and retry with a new idempotency key if body changes. |
401 | Missing or invalid system key. | Rotate or reconfigure server-side credential. |
403 | Authenticated key lacks access to the tenant, system, or stream. | Check tenant/system assignment. |
404 | Object is not visible to the caller or does not exist. | Confirm IDs and tenant scope. |
409 | Idempotency conflict, sequence conflict, or append conflict. | Do not blindly retry changed bodies; inspect conflict details. |
422 | Request is syntactically valid but violates the route contract. | Fix field values, policy references, or object kind. |
429 | Rate limit. | Back off with jitter and keep idempotency keys stable. |
5xx | Service-side failure. | Retry with the same idempotency key and preserve the original body. |
API keys stay server-side
Attesto system keys are bearer credentials. Use them only from trusted server-side processes, connector edges, or secret-managed job runners.
