Errors
Every error response is JSON. Every error response has the same envelope. Stage failures get a 422 with the failing stage named explicitly.
Error envelope
{
"ok": false,
"duration_ms": 12,
"error": "human-readable message",
"error_stage": "DOG"
}
error_stage is populated only for stage-rejection responses (HTTP 422). It's always one of the nine stage codes:
DOG DTL DKEC AER ZKSP PHASE4 LEDGER REGISTRY DLA
Status codes
| Code | When | Caller action |
|---|---|---|
| 400 | Malformed JSON, missing required field, bad hex | Fix the request |
| 401 | Missing or invalid X-Verdifax-Key (only when keys exist) | Provide a valid key |
| 404 | Run id not found, or not visible to the caller's key | Confirm the id and the key |
| 422 | A pipeline stage rejected the run | Read error_stage; fix upstream input |
| 429 | Rate limit exceeded (per-key) | Retry after the Retry-After header |
| 500 | Unhandled internal error | Report to the operator with the request id |
Stage rejection
When a pipeline stage rejects a run, the orchestrator persists the run with status: "stage_error" and returns 422 with the failing stage. The run is still visible in /runs and /runs/{id} for forensic review — failures are auditable, not silent.
curl -s -X POST http://localhost:9090/execute \
-H "Content-Type: application/json" \
-H "X-Verdifax-Key: vfx_..." \
-d '{ "payload_text": "x", "program_id": "not-hex", ... }'
{
"ok": false,
"error": "program_id must be 64-char hex, got 7 chars"
}
