Errors, rate limits, and retries
Northsun (formerly Mnemix) returns JSON errors with a stable envelope. Production integrations should branch on the HTTP status and error.code, log the trace identifier, and retry only failures that are safe to repeat.
{
"error": {
"code": "validation_error",
"message": "phone_number: Required"
}
}
Status guide
| Status | Typical code | Meaning | What your integration should do |
|---|---|---|---|
400 | bad_request | Invalid JSON or phone number. | Fix the request; do not retry unchanged. |
401 | unauthorized | Missing, malformed, or unknown API key. | Stop and repair secret/configuration. |
404 | not_found | Read-only caller lookup found no caller. | Treat as an empty state or use recall_and_enrich to start the caller lifecycle. |
422 | validation_error | JSON parsed, but a field failed the route schema. | Fix the named field; do not retry unchanged. |
429 | rate_limited | The tenant's request bucket is exhausted. | Wait until reset, add jitter, then retry. |
5xx | internal_error or service_unavailable | Northsun or a required dependency is unavailable. | Retry with capped exponential backoff; preserve the core agent experience when possible. |
Rate-limit headers
Authenticated v1 responses expose:
X-RateLimit-Limit— requests per minute for the authenticated plan.X-RateLimit-Remaining— remaining requests in the current window.X-RateLimit-Reset— the server-provided reset value used by the limiter.X-RateLimit-Mode: degraded— present when the shared Redis limiter is unavailable and a bounded in-isolate fallback is active.
Do not hardcode public plan limits from an old document. Read the response headers because limits are tenant-plan configuration, not a frozen documentation claim.
Retry policy
Use capped exponential backoff with jitter for 429, 503, timeouts, and transient network errors. Do not automatically retry 400, 401, 404, or 422 with an unchanged request.
const retryable = status === 429 || status === 503 || status >= 500;
const delayMs = Math.min(8_000, 500 * 2 ** attempt) + Math.random() * 250;
POST /v1/recall_and_enrich can create a caller on a miss. Reusing the same stable session_id makes application-level correlation easier, but this public route does not currently document an idempotency header contract. Avoid blind concurrent retries and record whether your first attempt may have reached the service.
POST /v1/calls/end returns 204 No Content after the interaction is committed durably — the next recall_and_enrich for that caller sees it immediately, not on a delay. See Hangup, and what happens next. Call it once after hangup; if your webhook platform retries, deduplicate by the platform call identifier before invoking Northsun.
Evidence for support
When reporting a failure, include the endpoint, UTC timestamp, HTTP status, error.code, and X-Trace-Id when present. Never include the API key, complete transcript, or unredacted phone number.
Next steps
- Authentication — verify bearer configuration.
- API reference — validate the request shape.
- Troubleshooting — diagnose common integration symptoms.