Skip to content

Errors & status codes

How Topiic signals errors in REST responses and what each status code means in context.

Topiic uses standard HTTP status codes and RFC 7807 problem-details JSON bodies on error responses.

{
"type": "https://tools.ietf.org/html/rfc7807",
"title": "Forbidden",
"status": 403,
"detail": "Caller does not belong to the requested merchant."
}

title is a short human-readable summary, detail is a longer explanation. Some endpoints add extra fields (e.g. validation error lists under errors).

Always log the body — status alone rarely tells you why a call failed.

CodeMeaning in Topiic context
200 OKRequest succeeded; body holds the resource or list.
201 CreatedResource created; body holds the new resource.
202 AcceptedRequest accepted for processing (e.g. webhook delivery replay queued).
204 No ContentRequest succeeded; no body (delete, simple update).
400 Bad RequestValidation failed. Body usually includes an errors map keyed by field name. Fix the request.
401 UnauthorizedMissing, malformed, expired, or invalid bearer credential. Mint or re-mint your API key.
403 ForbiddenAuthenticated but not allowed — typically the merchant id on the request doesn’t match your API key’s merchant.
404 Not FoundResource id doesn’t exist, or belongs to a merchant you can’t see.
409 ConflictDuplicate (e.g. a nonce already used, a unique-per-merchant email collision). Don’t retry blindly — change inputs.
410 GoneResource expired (e.g. signed deep link past exp). Generate a fresh one.
422 Unprocessable EntityRequest was syntactically valid but semantically rejected (e.g. enrolling a member in an inactive plan).
429 Too Many RequestsRate-limit tripped. Respect Retry-After header.
500 Internal Server ErrorTopiic bug. Capture the traceId from the response if present and contact support. Safe to retry idempotent requests.
502 Bad GatewayTopiic couldn’t reach the upstream payment gateway. Safe to retry with backoff.
503 Service UnavailableTopiic is degraded. Respect Retry-After; check the status page.

Most write endpoints don’t yet support an Idempotency-Key header. Until they do:

  • Deep-link resolve is naturally idempotent via the nonce — replaying the same d/s always returns the same outcome.
  • Webhook delivery replay creates a new attempt every time — that’s intentional.
  • Member creation is unique-per-merchant by email — a duplicate returns the existing record on a second call. Direct attempts to insert a duplicate via direct API give a 409 in some edge cases.
  • Other writes — apply your own deduplication on the client side.

400 responses for typed commands include a per-field error map:

{
"status": 400,
"title": "One or more validation errors occurred.",
"errors": {
"email": ["The Email field is not a valid e-mail address."],
"firstName": ["The FirstName field is required."]
}
}

Map these into your form-validation UI rather than displaying the raw text.

A 401 from a REST endpoint usually means one of:

CauseFix
No Authorization header.Add Authorization: Bearer tpk_….
Wrong scheme (Basic, lowercase bearer).Use exact Bearer (capital B).
API key revoked.Mint a new one.
API key past expiresAt.Mint a new one or extend in the portal.

If Topiic’s webhook delivery to your endpoint returns a non-2xx, it’s not an error from your perspective — it’s part of the retry loop. See Retries & replay.