Errors
Errors
Use the HTTP status, structured code and request id to diagnose an operation.
The error shape
REST failures return {"error":{"type":"invalid_request_error","code":"insufficient_scope","message":"…","request_id":"…"}}. A param field is included when available; it is otherwise omitted. Known failures below 500 use invalid_request_error; server failures use api_error. The response also has X-Request-Id.
Codes
| Status | Code | When |
|---|---|---|
| 400 | idempotency_key_required | Missing or invalid Idempotency-Key: use 1–128 printable non-space ASCII characters. |
| 400 | invalid_cursor | A cursor is malformed or belongs to another request. |
| 400 | invalid_parameter | A required field is missing or malformed. |
| 400 | unsupported_version | Only Swum-Version: 2026-10-25 is accepted. |
| 401 | invalid_api_key | The bearer API key is missing, invalid, revoked or expired. |
| 401 | invalid_token | The key/token is invalid, revoked or expired. |
| 401 | test_key_on_live | A sk_test_ key was sent outside the DEV sandbox API. |
| 403 | action_forbidden | The action is outside the integration allowlist. |
| 403 | api_not_enabled | Plan, feature switch or owner rollout access does not allow this API. |
| 403 | app_key_required | An app subscription route requires a dedicated Zapier, Make or n8n key. |
| 403 | insufficient_scope | The connection lacks the route’s access. |
| 403 | location_forbidden | A write target is outside the permitted locations. |
| 403 | sandbox_required | The owner is not a marked, founder-provisioned DEV sandbox. |
| 403 | school_inactive | The school or owner is no longer active. |
| 403 | team_disabled | The school has not enabled its swim team. |
| 404 | not_found | The school record is unavailable, including location-scoped reads. |
| 404 | route_not_found | No public route exists for this path/method. |
| 409 | duplicate_family | An owner roster contact matches normalized email/phone; an out-of-scope family id is withheld. |
| 409 | idempotency_conflict | The same key was used for a different request. |
| 409 | request_in_progress | The same idempotent operation is still pending or its outcome needs reconciliation. |
| 409 | roster_changed | Selected roster fields changed after the proposal was prepared. |
| 422 | dedupe_review_required | A roster over 5,000 contacts needs its contact index reviewed before API family changes. |
| 422 | failed_precondition | A current domain requirement prevents this action; review the returned message before retrying. |
| 422 | proposal_refused | The existing domain builder refused an unsafe or unsupported change. |
| 429 | daily_write_limit | The connection’s daily area cap is reached. |
| 429 | proposal_limit | The connection has 25 pending approval proposals. |
| 429 | rate_limit_exceeded | Wait the Retry-After interval. |
| 500 | internal_error | Unexpected failure; retain the original key and request id for reconciliation. |
Domain refusals may supply another normalized code. OAuth and JSON-RPC also have their own protocol error handling.
Handle errors
Correct validation and permission errors before retrying. Respect Retry-After on 429. For a lost write response or server error, retain the original idempotency key and reconcile the proposal; a fresh key can create a second operation. For MCP, inspect both JSON-RPC errors and the tools/call result’s isError field.