Docs

The standard AppError JSON envelope, what each commonly-returned status code means in FastYoke, and three worked examples.

Error envelope

Every FastYoke API error follows the same JSON shape. This page documents the envelope and what each status code means in FastYoke specifically.

The AppError envelope

Every 4xx and 5xx response is a JSON object with at least an error machine code and a message human description, and optionally a details object carrying field-level context:

{
  "error": "validation_failed",
  "message": "field 'body' is required",
  "details": { "field": "body" }
}

The error code is stable and machine-readable; the message is human-readable and may be reworded between releases. Client code should branch on error, not on message.

Status code semantics

StatusMeaning in FastYoke
400Request validation failure — missing fields, malformed JSON, bad enum value.
401Missing or invalid JWT. The auth header was absent, expired, or didn't verify.
403Authenticated, but not authorized for this resource — your JWT is valid but doesn't carry the permission this endpoint requires.
404Not found in the caller's tenant. Could mean the resource genuinely doesn't exist, OR it exists in another tenant that this JWT doesn't see. The platform deliberately collapses both into 404 to avoid leaking cross-tenant existence.
409Write conflict — concurrent FSM transition on the same job, double-seal attempt on an already-sealed envelope, etc. Safe to re-fetch the resource and decide whether to retry.
422Semantically invalid — the request parsed and the caller had permission, but a business rule rejected it. FSM guard returned false; field constraint violated; envelope can't transition from its current state.
429Rate limit hit. See Rate limits for the per-endpoint limits and the Retry-After header.
5xxPlatform error. Safe to retry with exponential backoff.

Worked examples

404 on a wrong-tenant id

curl -i https://app.fastyoke.io/api/v1/tenant/jobs/job_abc123 \
  -H "Authorization: Bearer <jwt for tenant A>"

If job_abc123 belongs to tenant B:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "error": "not_found",
  "message": "job not found"
}

The platform does NOT distinguish "doesn't exist" from "exists in another tenant." This is by design — see Tenant scoping.

422 on a guard-rejected FSM transition

curl -i -X POST https://app.fastyoke.io/api/v1/tenant/jobs/job_xyz/transition \
  -H "Authorization: Bearer <jwt>" \
  -d '{"event_type":"ship"}'
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "error": "guard_rejected",
  "message": "transition guard returned false",
  "details": { "from": "packed", "to": "shipped", "guard": "all_items_scanned" }
}

A 422 means the request was well-formed and authorized but the FSM's guard logic refused the transition.

429 with Retry-After

curl -i -X POST https://app.fastyoke.io/api/v1/public/forms/anonymous \
  -d '{...}'
HTTP/1.1 429 Too Many Requests
Retry-After: 15
Content-Type: application/json

{
  "error": "rate_limited",
  "message": "too many requests"
}

Honor the Retry-After header. See Rate limits for the backoff recommendation.