Skip to content

Error handling

Status Meaning Retry?
400 Malformed request No — fix the request
401 Token present but invalid No — fix the token
403 No Authorization header, or method not allowed on this path No
404 Unknown form_slug or slug No — check both
406 Cannot satisfy the Accept header No
415 Unsupported media type No — send application/json
422 Validation failed No — fix the payload
429 Throttled Yes — exponential backoff
431 Header fields too large No
461 Insufficient workspace credit No — alert and top up
500 Server error Yes — up to 3× with backoff, then alert

Most errors use one shape:

{
"error": {
"status_code": 401,
"message": "Unauthorized",
"detail": "No permission -- see authorization schemes"
}
}

On 422, error.detail is an object keyed by question_key instead of a string.

Three responses use a different shape:

Where Shape
422 from .../submit/ Flat {"field": ["message"]} — no error wrapper
404 from .../hook-submit/ {"detail": "No AppliedForm matches the given query."}
461 from .../create/ {"detail": "Insufficient Credit", "code": "InsufficientCredit"}

Branch on the HTTP status first, then read whichever shape that status uses.

461 Insufficient Credit
{ "detail": "Insufficient Credit", "code": "InsufficientCredit" }
400 / 401 / 403 -> do not retry; fix the request or the token
404 -> do not retry; check form_slug and slug
422 -> do not retry; fix the payload
429 -> retry with exponential backoff
461 -> do not retry; alert and top up workspace credit
5xx -> retry up to 3x with backoff, then alert
  • API token stored server-side only, never shipped to a client.
  • slug persisted against your own record at create time.
  • slug and form_url treated as secrets — out of logs and analytics.
  • Pre-filled personal data kept to the minimum.
  • Webhook receiver validates the Authorization header.
  • Idempotency keyed on slug + submitted_at, not on nounce.
  • Receiver returns 2xx within 30 seconds.
  • Signed images fetched within 15 minutes and copied to your own storage.
  • Receiver size-tested against a sanctions-match payload.
  • Status values compared case-insensitively, with fallbacks for renamed columns.
  • Every response envelope handled, including the flat 422 and the 461 body.
  • Alerting on 429, 461 and 5xx.
  • Desktop visitors shown a QR code, not a dead redirect.

When contacting UpPass support, include:

form_slug the flow
Application number application.no, e.g. COK00100001
slug the application
event.nounce for a webhook issue
Timestamp (UTC) application.submitted_at