Skip to content
VerifAIer
Home / Docs / API / Requests, errors & limits
API · Conventions

Requests, responses, errors & limits

Request/response shapes, the exact error format, status codes, and the truthful story on idempotency, retries, timeouts, pagination and rate limits.

Request format

Requests are JSON with Content-Type: application/json. Bodies are validated by Pydantic models; unknown or wrong-typed fields fail validation with 422. The assessment endpoints share one convention, an evidence object (a serialized EvidenceEnvelope), defaulting to {}:

http

POST /api/v1/trust/assess
{ "evidence": { /* EvidenceEnvelope.to_dict() */ } }

POST /api/v1/compliance/assess
{ "pack_id": "eu_ai_act", "evidence": { /* … */ } }

Query parameters are used for listing endpoints (limit, offset, artifact_type). Path parameters carry resource ids (e.g. /api/v1/registry/agents/{agent_id}).

Response format

Responses are JSON. Each capability returns its full export dict (the object's to_dict()). Responses evolve additively: new fields may appear; existing fields keep their meaning. Listing endpoints wrap results with counts:

json

{ "items": [ /* … */ ], "total": 12, "limit": 50, "offset": 0 }   // /api/vai/*
{ "agents": [ /* … */ ], "count": 3 }                              // /api/v1/registry/agents

Error format

Errors use FastAPI's standard shape. A raised HTTPException serializes to a detail string:

json

{ "detail": "Authentication required" }

Request-validation failures (422) return a structured detail array, one entry per invalid field:

json

{
  "detail": [
    { "loc": ["body", "input"], "msg": "field required", "type": "value_error.missing" }
  ]
}

Status codes

CodeMeaning in VerifAIer
200OK, assessments, audit, listings, control-center overview
201Created, /validate, /pipeline, /dev/audit
204No Content, /api/auth/logout
400Bad request, e.g. unknown artifact_type on /api/vai/artifacts
401Unauthorized, missing/invalid session or API key ("Authentication required" / "Invalid or expired session" / "Invalid credentials")
403Forbidden, API key valid but revoked; org-access denied
404Not found, unknown agent, artifact, validation or run id
422Unprocessable Entity, request-body validation failed (includes unknown pack_id via its Literal)
429Too Many Requests, login rate limit exceeded
502Bad Gateway, /validate / /sentinel/verify when the validation engine raises
503Service Unavailable, e.g. Stripe webhook when the webhook secret is unconfigured
The open governance path never fails on provider trouble. /api/v1/audit/conversation returns 200 with a deterministic mock-backed result even when a provider is down, failure surfaces as data (status:"error", fallback_used:true), not as a 5xx. See failure handling.

Idempotency

There is no Idempotency-Key header. Idempotency instead comes from determinism:

  • The assessment / passport / reputation / signal endpoints are pure functions of their input, the same evidence yields the same content-derived ids (agent_ pass_ rep_ sig_) and the same result. Re-POSTing is safe and side-effect-free.
  • POST /api/v1/registry/observe is idempotent per agent: it upserts a per-agent entry (created_at preserved, updated_at advances, None values never clobber). Re-observing the same agent updates in place rather than duplicating.
  • Only the timestamp (created_at) varies between identical calls; it is deliberately excluded from content-derived id hashes.

Retries

  • Safe to retry: all GETs, and the deterministic POST assessment endpoints (no side effects). registry/observe is safe to retry because it upserts.
  • Rate-limited: POST /api/auth/login: back off on 429 (see below).
  • No server-side provider retry. The Provider Router does not retry a failed call, fallback is driven by availability, and the chain is walked at most once. A client that wants cross-attempt retry must implement it itself (exponential backoff on network errors); the API's own responses are already deterministic and safe to replay.

Timeouts

  • The application does not impose a per-request wall-clock timeout in code. Set request timeouts at your deployment gateway / client.
  • The one upstream call that can block, a live Gemini audit, is bounded inside sentinel/gemini_proxy (stdlib urllib with a timeout) and self-falls-back, so a slow provider cannot hang the evidence path indefinitely.
  • Client guidance: the SDK request builders are transport-agnostic; supply your HTTP client's timeout (the dashboard client uses an AbortController with a default 8s timeout).

Pagination

Pagination is limit/offset where implemented, and is documented per endpoint, it is not uniform, so this table is the source of truth:

EndpointPagination
GET /api/vai/artifacts, /api/vai/receiptslimit (1–200, default 50) + offset (≥0)
GET /validations, /pipeline/runslimit (1–100, default 20) + offset (≥0)
GET /api/v1/registry/agentsnone: returns all entries with a count
GET /api/v1/control-center/overviewnone: full fleet aggregate
Truthful note. The open /api/v1 listing endpoints return complete collections without pagination. For large fleets, aggregate/paginate at your data layer or gateway, cursor pagination is not implemented in the app.

Rate limit posture

  • Implemented: a per-IP login rate limit via an in-process RateLimiter: RATE_LIMIT_LOGIN_RPW attempts (default 20) per RATE_LIMIT_LOGIN_WINDOW seconds (default 900 = 15 min). Exceeding it returns 429 Too many login attempts.
  • Not implemented: there is no general per-endpoint or per-tenant rate limiting on the governance or data APIs.
Deployment-gateway responsibility. Global rate limiting, quotas and per-tenant throttling are expected to live at the reverse proxy / API gateway in front of VerifAIer, not in the app. Document and enforce them there.