Auvral

Errors

The Auvral error format, every status code the API returns, and what to do about each one.

Every error response has the same shape:

{
  "statusCode": 409,
  "message": "Flow has no published version",
  "code": "FLOW_NOT_PUBLISHED"
}
FieldDescription
statusCodeRepeats the HTTP status code.
messageHuman-readable. Written for a developer reading a log, not a stable machine-readable code. Never branch on this string.
codeA stable machine-readable code for the condition. Present on every error the API returns except the 500. Branch on this.

code is what you write your error handling against; message may be reworded at any time. The field is absent where there is no code to give, so read it as optional.

A code that exists never changes meaning.

Successful responses use the same envelope with data in place of message:

{ "statusCode": 201, "data": { "sessionId": "..." } }

The catalogue of POST /v1/sessions

400 Bad request

The body did not validate. These are bugs in your integration; retrying the same request will not help.

codeCause
MISSING_REQUIRED_FIELDSflowId is missing or empty
INVALID_REFERENCE_IDreferenceId was sent but is not a string, or is empty (or only whitespace, it is trimmed). Omit the field entirely to let Auvral assign one
REFERENCE_ID_TOO_LONGreferenceId is above 128 characters. Shorten it, or hash your identifier
INVALID_METADATAmetadata breaks one of its limits: at most 50 keys, keys of 1 to 40 characters, string values of at most 500 characters, no nesting. The message names the rule that failed
INVALID_EXPIRES_INexpiresIn is not an integer, not positive, or above 86400
INVALID_ALLOWED_ORIGINSAn entry of allowedOrigins is not an http/https origin or "*": a missing scheme, a path, a query, a trailing slash, an uppercase host. It also covers "*" sent alongside a concrete origin, more than 20 entries, and an entry above 255 characters. The message names the offending entry and the canonical form that would have been accepted
INVALID_RETURN_URLreturnUrl is not an absolute http or https URL, or is above 2048 characters. A relative path, a bare host and any other scheme (javascript:, data:) are all refused
INVALID_FLOW_VERSIONflowVersion is neither published nor draft
DRAFT_REQUIRES_SANDBOX_KEYflowVersion: "draft" was sent with a live key. Drafts are testable in sandbox only

401 Unauthorized

{ "statusCode": 401, "message": "Invalid api key", "code": "INVALID_API_KEY" }

Always this exact body, whatever went wrong: missing, malformed, unknown, revoked, or used against the wrong environment. Work down the checklist in Authentication.

403 Forbidden

codeCause
PLAN_EXHAUSTEDYour plan has no live verifications left, or its free window has ended. The message says which of the two it was

Only live keys are refused: sandbox verifications are not counted and never run out, so your integration can keep being tested while the plan is exhausted. Nothing was created, and the same request works once the plan is lifted. Write to sales@auvral.com, or read the plan on the My plan page of the dashboard.

404 Not found

codeCause
FLOW_NOT_FOUNDThe flowId does not exist, or it belongs to a different organization than your API key
FLOW_DRAFT_NOT_FOUNDYou asked for flowVersion: "draft" and the flow has no unpublished changes

The most common cause of FLOW_NOT_FOUND is environment crossover: a sandbox flow id sent with a live key, or the reverse. Flow ids are not shared between environments.

409 Conflict

The flow exists, and it cannot run right now. Both of these are fixed in the dashboard, not in your request.

codeCause
FLOW_NOT_PUBLISHEDThe flow has never been published, so there is no published version to run. Publish it, or ask for flowVersion: "draft" with a sandbox key
FLOW_NOT_ACTIVEThe flow was deactivated. It accepts no new sessions with either key kind until it is reactivated

Sessions you already created are unaffected: each one pins the flow version it opened on, and runs it to the end whatever happens to the flow afterwards.

500 Server error

{ "statusCode": 500, "message": "Failed to create session" }

Something went wrong on Auvral's side, and it carries no code: a server error is not a condition to branch on. Retry with backoff. If it persists, get in touch and include the timestamp and the referenceId you sent.

The catalogue of the reads

Both reads answer one 404 for every reason an id is not yours to see, and they never say which reason it was.

GET /v1/sessions/{sessionId}

codeStatusCause
SESSION_NOT_FOUND404No session with this id belongs to your key: it never existed, it belongs to another organization, it was created in the other environment, or it expired without your user ever starting it
INVALID_API_KEY401Same body as everywhere else

A session that expired after your user started it is not a 404: it answers 200 with the verdict, rebuilt from the verification it produced. Only a session that left nothing behind disappears.

GET /v1/verifications/{id}

codeStatusCause
VERIFICATION_NOT_FOUND404No verification with this id belongs to your key: unknown id, another organization, or the other environment
INVALID_API_KEY401Same body as everywhere else

Environment crossover is the common cause here too: a sandbox verificationId read with a live key is a 404, and the reverse as well.

Retrying

StatusRetry?
400No, fix the request
401No, fix the credential
403No, the plan has to be lifted first
404No, fix the id
409No, fix the flow in the dashboard
500Yes, with exponential backoff

POST /v1/sessions is not idempotent: referenceId names the person, not the call, so it is not an idempotency key, and every successful call creates a new session. A retry after a call that actually succeeded leaves an unused session behind, which is harmless because it expires on its own, but do not retry unless you are confident the first call did not succeed.

Errors that are not API errors

A rejected verification is not an error. verification.failed arrives with a 200 from your endpoint and means the checks did not pass. See Event reference.

SDK errors are separate. onError({ code, message }) reports integration problems in the browser (missing_url, already_open) and never carries a verification outcome. See SDK reference.

An expired URL fails in the browser, not in your API calls: your user sees an expired message and your backend is not notified. Recovery is a new session.

On this page