Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vane.build/llms.txt

Use this file to discover all available pages before exploring further.

POST /v1/attest

The core endpoint. Appends a signed, indexed record to the authenticated company’s attestation chain. The record’s hash is computed over index | timestamp | canonicalize(payload) and signed with the company’s Ed25519 private key. Requires authentication. Rate limit: 100 requests/minute per API key (see Rate Limits).

Request body

FieldTypeRequiredDescription
agentIdstringYesThe agent taking this action. Does not need to be pre-registered, but pre-registration is recommended for identity coherence.
actionTypestringYesA short descriptor for what the agent did. Freeform — use whatever taxonomy makes sense for your audit needs (e.g., "web-search", "tool-call", "llm-completion").
payloadanyYesArbitrary JSON describing the action. Stored verbatim and included in the hash.
delegationstringNoA delegation JWT from POST /v1/token-exchange or POST /v1/token/exchange. When present, the delegation is verified and bound cryptographically to the record.
companyId is not accepted in the request body. It is derived authoritatively from the API key and embedded in the stored payload automatically. Passing it in the body (as the TypeScript SDK does for legacy reasons) is harmless — the server ignores it and uses the authenticated company.

Response 201AttestationRecord

FieldTypeDescription
indexnumberZero-based position in this company’s chain.
timestampstringISO 8601 timestamp set by the server.
payloadobjectThe stored payload, including server-injected agentId, companyId, and actionType.
delegationDelegationInfoPresent only when a delegation token was supplied.
hashstringSHA-256 hex over `index|timestamp|canonicalize(payload)[canonicalize(delegation)]`.
signaturestringEd25519 over hash, base64url-encoded.
DelegationInfo fields:
FieldTypeDescription
subjectstringsub claim from the delegation token — the entity being acted on behalf of.
delegationChainstring[]The full chain of principals, from subject to acting agent.
actobject | nullRaw act claim for nested delegation.
tokenIdstringjti of the delegation token — ties this record to the exchange event.

Error responses

StatusBodyMeaning
400{ "error": "Missing or invalid fields: agentId, actionType, payload are required" }One or more required fields missing.
400{ "error": "Invalid delegation: ..." }Delegation JWT is malformed, expired, or has an invalid signature.

Example — simple attestation

curl -s -X POST http://localhost:3000/v1/attest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_KEY" \
  -d '{
    "agentId": "researcher-1",
    "actionType": "web-search",
    "payload": {
      "query": "EU AI Act compliance requirements",
      "results": 10,
      "topUrl": "https://example.com/eu-ai-act"
    }
  }'
{
  "index": 0,
  "timestamp": "2026-01-01T12:00:00.000Z",
  "payload": {
    "agentId": "researcher-1",
    "companyId": "acme",
    "actionType": "web-search",
    "payload": {
      "query": "EU AI Act compliance requirements",
      "results": 10,
      "topUrl": "https://example.com/eu-ai-act"
    }
  },
  "hash": "f651a7c3e4b8d2a1c9f0e7b4d3c2a1b0...",
  "signature": "vdv-nC4oR3t8sY2pL6kXqZ1mW9jB0eA..."
}

Example — attested action with delegation

# First get a delegation token
DELEGATION=$(curl -s -X POST http://localhost:3000/v1/token-exchange \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_KEY" \
  -d '{
    "agentId": "researcher-1",
    "actingOn": "acme",
    "scope": "attest:write"
  }' | jq -r '.token')

# Attest with the delegation token bound
curl -s -X POST http://localhost:3000/v1/attest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_KEY" \
  -d "{
    \"agentId\": \"researcher-1\",
    \"actionType\": \"data-export\",
    \"payload\": { \"rows\": 1500, \"destination\": \"s3://acme-reports/\" },
    \"delegation\": \"$DELEGATION\"
  }"
{
  "index": 1,
  "timestamp": "2026-01-01T12:05:00.000Z",
  "payload": {
    "agentId": "researcher-1",
    "companyId": "acme",
    "actionType": "data-export",
    "payload": { "rows": 1500, "destination": "s3://acme-reports/" }
  },
  "delegation": {
    "subject": "spiffe://vane.local/company/acme",
    "delegationChain": [
      "spiffe://vane.local/company/acme",
      "spiffe://vane.local/company/acme/agent/researcher-1"
    ],
    "act": {
      "sub": "spiffe://vane.local/company/acme/agent/researcher-1"
    },
    "tokenId": "cb6a2a5e-21ad-4d2c-80c9-d37516f276ab"
  },
  "hash": "a3f9b2c1d8e5f6a4b7c3d0e9f2a5b8c1...",
  "signature": "Xt8q1R7mNp3kL5jB2cY6wA9oH4vE7uI..."
}