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.
Problem-details body shape
Section titled “Problem-details body shape”{ "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.
Status code reference
Section titled “Status code reference”| Code | Meaning in Topiic context |
|---|---|
| 200 OK | Request succeeded; body holds the resource or list. |
| 201 Created | Resource created; body holds the new resource. |
| 202 Accepted | Request accepted for processing (e.g. webhook delivery replay queued). |
| 204 No Content | Request succeeded; no body (delete, simple update). |
| 400 Bad Request | Validation failed. Body usually includes an errors map keyed by field name. Fix the request. |
| 401 Unauthorized | Missing, malformed, expired, or invalid bearer credential. Mint or re-mint your API key. |
| 403 Forbidden | Authenticated but not allowed — typically the merchant id on the request doesn’t match your API key’s merchant. |
| 404 Not Found | Resource id doesn’t exist, or belongs to a merchant you can’t see. |
| 409 Conflict | Duplicate (e.g. a nonce already used, a unique-per-merchant email collision). Don’t retry blindly — change inputs. |
| 410 Gone | Resource expired (e.g. signed deep link past exp). Generate a fresh one. |
| 422 Unprocessable Entity | Request was syntactically valid but semantically rejected (e.g. enrolling a member in an inactive plan). |
| 429 Too Many Requests | Rate-limit tripped. Respect Retry-After header. |
| 500 Internal Server Error | Topiic bug. Capture the traceId from the response if present and contact support. Safe to retry idempotent requests. |
| 502 Bad Gateway | Topiic couldn’t reach the upstream payment gateway. Safe to retry with backoff. |
| 503 Service Unavailable | Topiic is degraded. Respect Retry-After; check the status page. |
Idempotency on writes
Section titled “Idempotency on writes”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 samed/salways 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.
Validation errors
Section titled “Validation errors”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.
Authentication errors specifically
Section titled “Authentication errors specifically”A 401 from a REST endpoint usually means one of:
| Cause | Fix |
|---|---|
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. |
Webhook-specific failures
Section titled “Webhook-specific failures”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.