Errors
RogerIQError with stable codes, status, request ID, and validation issues.
Errors
All non-2xx responses throw RogerIQError. Branch on code (machine
readable), not message (human readable).
tsimport { RogerIQ, RogerIQError } from "@rogeriq/sdk";try { await roger.conversations.get("con_missing");} catch (e) { if (e instanceof RogerIQError) { if (e.code === "CONVERSATION_NOT_FOUND") { // handle } console.error(e.code, e.status, e.requestId, e.message); } throw e;}
Fields
| Field | Type | Description |
|---|---|---|
code | string | Stable enum, e.g. CONVERSATION_NOT_FOUND |
status | number | HTTP status code (0 if network error) |
message | string | Human-readable summary |
requestId | string | undefined | Echoes the X-Request-Id header |
issues | { path, message }[] | undefined | Field-level validation errors (400 only) |
retryAfter | number | undefined | Seconds to wait (429 only) |
Common codes
| Code | Status | Meaning |
|---|---|---|
UNAUTHORIZED | 401 | Missing / invalid API key |
FORBIDDEN | 403 | Authenticated but action not allowed |
INSUFFICIENT_SCOPE | 403 | API key has the wrong scope |
API_KEY_ORG_MISMATCH | 403 | API key belongs to a different org than the requested resource |
API_KEY_PROJECT_MISMATCH | 403 | API key's org doesn't own the requested project |
CONVERSATION_NOT_FOUND | 404 | Bad conversation id |
PROJECT_NOT_FOUND | 404 | Bad project id |
CONTACT_NOT_FOUND | 404 | Bad contact id |
RESOURCE_NOT_FOUND | 404 | Generic 404 |
CONFLICT | 409 | Slug collision, idempotency conflict, etc. |
SLUG_CONFLICT | 409 | Specifically for project / form slugs |
BAD_REQUEST | 400 | Generic bad input |
BAD_JSON | 400 | Body wasn't valid JSON |
NO_UPDATES | 400 | PATCH with empty body |
RATE_LIMITED | 429 | Slow down (the SDK auto-retries if retry_after ≤ 30s) |
INTERNAL_ERROR | 500 | Server bug. Include requestId when reporting. |
Validation errors
POST/PATCH bodies that fail Zod validation include a structured issues
array:
json{ "error": "Invalid body", "code": "BAD_REQUEST", "request_id": "req_abc", "issues": [ { "path": "email", "message": "Invalid email" }, { "path": "metadata.plan", "message": "Expected string" } ]}
tstry { await roger.contacts.upsert({ email: "not-an-email" });} catch (e) { if (e instanceof RogerIQError && e.issues) { for (const issue of e.issues) { console.error(`${issue.path}: ${issue.message}`); } }}
Rate limiting
The SDK auto-retries 429 once when retry_after ≤ 30 seconds. For
longer suggested delays the SDK throws so you can decide.
Watch live headroom via the onResponse callback:
tsconst roger = new RogerIQ({ apiKey: process.env.RIQ_API_KEY!, projectId: process.env.RIQ_PROJECT_ID!, onResponse: (meta) => { if (meta.rateLimit && meta.rateLimit.remaining < 10) { console.warn("approaching limit:", meta.rateLimit); } },});
See API rate limits for per-tier limits and the
X-RateLimit-* header reference.