Errors
Every failure from a public SDK namespace surfaces as a TreatinkError, and each one also fires
the instance-level 'error' event.
class TreatinkError extends Error {
code: string; // one of the codes below
status?: number; // HTTP status, when the error came from the wire
param?: string; // offending field, when the API identifies one
requestId?: string; // for support/debugging
}
Fixtures mode produces identical error objects to live mode — a test asserting on a code
passes in both.
API codes
These come from the wire (see the error envelope):
| HTTP | Codes |
|---|---|
| 400 | bad_request, invalid_cursor |
| 401 | invalid_api_key |
| 403 | insufficient_permissions |
| 404 | not_found |
| 409 | upload_quota_exceeded, upload_incomplete, upload_expired, asset_not_final, cutout_label_not_final, idempotency_conflict |
| 413 | upload_too_large |
| 415 | unsupported_media_type |
| 422 | validation_error, upload_validation_failed |
| 503 | service_unavailable |
SDK-local codes
Raised client-side, never from the wire:
| Code | When |
|---|---|
key_scope_violation | a secret (sk_…) or non-publishable key was passed to Treatink.init — thrown synchronously |
unsupported_file_type | client-side pre-upload validation rejected the file |
upload_failed | the browser PUT to the presigned storage URL failed (network/CORS) |
Wire envelope
{ "error": { "type": "invalid_request_error", "code": "upload_too_large",
"message": "…", "param": "size_bytes",
"request_id": "req_fx_000001" } }
type varies by class: 4xx request errors → invalid_request_error; 401 →
authentication_error; 403 → permission_error; 5xx → api_error (e.g. with code
service_unavailable).
Retry guidance
- Idempotent GETs (catalog, templates) are retried by the SDK automatically with exponential backoff and jitter — you don't need to retry reads yourself.
- Writes are never blind-retried. A failed artwork upload surfaces
upload_failedto the UI instead of retrying silently. - Order submission is safe to retry:
submitOrdersends anIdempotency-Key(default =external_order_id), so re-posting the same payload replays the original order. Reusing the same key with a different body returns409 idempotency_conflict.
Testing failures in fixtures mode
tk.fixtures.failNext(op, { status, code }) makes the next matching operation fail with the exact
wire envelope, so you can exercise your error handling deterministically:
tk.fixtures.failNext('products.list', { status: 503, code: 'service_unavailable' });