Handle GOFA API errors, rate limits, retries, and session charges.
The API uses JSON responses and includes a GOFA-generated x-request-id on
authenticated requests. Keep that ID with your application logs and include it
when contacting GOFA Support; do not send API keys or health data to Support.
Errors from the common API access boundary have this shape:
{
"error": {
"code": "<public-error-code>",
"message": "<human-readable-message>",
"requestId": "<GOFA-generated-request-id>"
}
}The Vital Scan handler's 404, per-session polling 429, and handler-level
500 responses contain error.message and error.requestId; those responses
do not promise an error.code. The common access boundary can reject a
request before the handler runs, with the coded responses listed below.
| Status | Code | Meaning |
|---|---|---|
400 | invalid_request | The JSON body, userId, locale, or returnUrl is invalid. |
400 | return_origin_not_approved | The returnUrl origin is not approved for the workspace. |
401 | invalid_api_key | The bearer key is missing, invalid, expired, or revoked. |
402 | insufficient_credits | No point remains in the current Free allowance for a new session. The response includes remaining, cycleId, and resetsAt. |
403 | product_not_available | Vital Scan is not available for the workspace. |
403 | product_not_entitled | The authenticated key is not entitled to Vital Scan. |
403 | entitlement_inactive | The workspace's commercial entitlement is not active. |
403 | entitlement_expired | The workspace's commercial entitlement has expired. |
403 | free_membership_required | The workspace does not have the required Free membership. |
429 | rate_limit_exceeded | The configured requests-per-minute limit was exceeded. |
503 | entitlement_unavailable | Entitlement data could not be read or validated temporarily. |
503 | rate_limit_unavailable | Request-protection configuration or its distributed check is temporarily unavailable. |
503 | free_membership_unavailable | Free membership data is temporarily unavailable. |
503 | free_allowance_unavailable | Free allowance data is temporarily unavailable. |
503 | vital_scan_creation_unavailable | GOFA could not confirm whether session creation committed. |
503 | commit_outcome_unknown | The session-creation transaction outcome is unknown. |
503 | usage_event_unavailable | Successful commercial usage recording is temporarily unavailable. |
500 | vital_scan_creation_failed | An unexpected error prevented session creation. |
The product_not_available and invalid_request checks are specific to
session creation. The authentication, entitlement, and rate-limit checks apply
to all three public session operations.
400, 401, or 403.402, wait until the allowance resets or ask GOFA to update the
workspace; repeating the request cannot create a session without a point.429, honor Retry-After and use exponential backoff. A GET that polls
the same session too soon returns 429 with the number of seconds to wait.5xx, with
bounded exponential backoff. Honor Retry-After if present and stop at a
deadline rather than polling indefinitely.5xx. In particular, commit_outcome_unknown and
vital_scan_creation_unavailable mean creation could not be confirmed. The
session and charge may already exist even though your backend did not receive
201. A new POST is a new billable operation; neither the same userId nor an
Idempotency-Key header deduplicates it.userId, and GET does not recover the secret hosted URL. Do not send
keys, hosted URLs, or health data to Support.404 if it already succeeded; it
does not refund or create a charge.Authenticated responses may include:
ratelimit-limit — the workspace-configured requests-per-minute limit.ratelimit-remaining — the remaining requests in the current window.ratelimit-reset — the reset time as a Unix timestamp in seconds.Retry-After — how long to wait when a request is rejected for a retryable
limit condition.The exact requests-per-minute value is configured per workspace; do not hardcode a plan value in your client. GET and DELETE are not billable, but they still consume rate-limit capacity. In addition, a given session may be polled no more than once every five seconds.
These are separate limits. For example, five-second polling is 12 requests per minute, so it exceeds a workspace configured for 10 requests per minute even with only one session. Share one request budget across all keys, session polls, creates, and deletes in the workspace. See the bounded, single-session example in Quick Start.
A successful POST /api/v1/vital-scan/sessions response (201 Created)
consumes one available point. GET and DELETE consume no points. A rejected
request does not intentionally create a billable session. Deleting a session,
letting it expire, or a user leaving the hosted flow does not refund the point
used for its creation.