UnifAPI Docs

Errors

Every error UnifAPI returns, what it means, and how to recover.

Errors always come back in the same envelope, regardless of which upstream provider was called:

{
  "error": {
    "type": "rate_limited",
    "message": "Workspace rate limit exceeded.",
    "request_id": "tikhub-5471f8cf-a381-4204-a280-b73df8c93167"
  }
}
  • error.type is from a closed vocabulary (see table below) — stable, machine-readable, safe to switch on.
  • error.message is for humans and may change without notice.
  • error.request_id is the upstream-prefixed trace id. Include it in support requests.
  • error.issues is present only when type = validation_error — it's the raw Zod issue list.

The HTTP status mirrors the type — clients can pick whichever signal they prefer.

Reference

StatustypeWhen it happensRecovery
400validation_errorRequest failed gateway-side validation (bad query, missing body field).Inspect error.issues. Fix the request.
400invalid_idThe provided id was syntactically valid but the upstream rejected its format.Use a real id.
401unauthorizedAuthorization header missing, malformed, or rejected by the upstream.Rotate or recreate the key.
404not_foundThe resource (video, user, room, ...) does not exist, is deleted, or is private.Confirm the id; some resources are private and 404 by design.
429rate_limitedWorkspace or upstream rate limit exceeded.Honor Retry-After. See Rate limits.
500internal_errorUnifAPI itself failed (uncaught exception).Safe to retry. Report request_id if it persists.
500response_shape_errorUpstream returned a payload that no longer matches our schema (upstream drift).Report request_id — drift is a bug.
502upstream_errorUpstream returned an error UnifAPI cannot recover from.Inspect error.message.
503upstream_unavailableUpstream timed out or is unreachable.Retry with exponential backoff.

The full vocabulary is captured in ADR 0003 — Error model.

Anatomy of a validation error

For validation_error, the issues array carries the raw Zod issue list so a caller can map errors back to fields:

{
  "error": {
    "type": "validation_error",
    "message": "Request validation failed.",
    "issues": [
      {
        "code": "too_big",
        "maximum": 50,
        "type": "number",
        "inclusive": true,
        "path": ["limit"],
        "message": "Number must be less than or equal to 50"
      }
    ]
  }
}

Always log request_id

Every error response carries request_id (when the failure originated from or transited an upstream call). Log it. Support requests without a request_id take days; with one, minutes.

On this page