Errors and rate limits
When to use this guide: Use this reference when an OutboundSync API request fails, returns
401,403, or429, or needs retry logic.
OutboundSync API v1 uses standard HTTP status codes. Error responses include a human-readable message; most also include statusCode and error.
Error response shape
Section titled “Error response shape”{ "statusCode": 401, "message": "Invalid API key", "error": "Unauthorized"}Treat message and the HTTP status code as the stable troubleshooting fields. Some framework-generated responses can vary by status.
Status codes
Section titled “Status codes”| Status | Meaning | Common cause | What to do |
|---|---|---|---|
200 | Success | The key is valid and has at least one API-enabled connection. | Continue using the response. |
401 | Unauthorized | Missing, malformed, revoked, rotated, or invalid API key. | Confirm the Authorization: Bearer osapi_... header and rotate the key if needed. |
403 | Forbidden | Valid key, but API access, scopes, connection scope, or Webhooks block the route. | See 403 forbidden below. |
409 | Conflict | Sync retry is not eligible, missing context, or the CRM is not HubSpot/Salesforce. | See POST /api/v1/syncs/:id/retry. |
429 | Too many requests | The IP or account exceeded the current fixed-window limit. | Respect the Retry-After header before retrying. |
500 | Server error | Unexpected server-side failure. | Retry later; contact support if it repeats. |
401 invalid API key
Section titled “401 invalid API key”OutboundSync returns a uniform 401 for missing, malformed, invalid, revoked, and rotated keys.
{ "statusCode": 401, "message": "Invalid API key", "error": "Unauthorized"}The response includes this header so clients know Bearer authentication is expected:
WWW-Authenticate: Bearer realm="OutboundSync API"403 forbidden
Section titled “403 forbidden”A key can be valid but still forbidden. Treat the message as the stable signal:
API access disabled
Section titled “API access disabled”No accessible CRM connection has API access enabled.
{ "statusCode": 403, "message": "API access is not enabled for this account", "error": "Forbidden"}Enable API access for the CRM connection in the OutboundSync admin app, then retry.
Missing write scope
Section titled “Missing write scope”Mutations on /api/v1/webhooks* and POST /api/v1/syncs/:id/retry require the write scope.
Webhook mutations:
{ "statusCode": 403, "message": "This endpoint requires the 'write' scope", "error": "Forbidden"}Sync retry:
{ "statusCode": 403, "message": "API key requires the \"write\" scope", "error": "Forbidden"}Ask OutboundSync support for a key that includes write. Sync retry allows a connection-scoped key; webhook mutations require an account-wide key. See Creating API keys and POST /api/v1/syncs/:id/retry.
Connection-scoped key on webhooks
Section titled “Connection-scoped key on webhooks”All /api/v1/webhooks* routes (including GETs) require an account-scoped key.
{ "statusCode": 403, "message": "Webhook endpoint management requires an account-scoped API key", "error": "Forbidden"}Create or request an All connections (account-wide) key.
Webhooks not enabled
Section titled “Webhooks not enabled”/api/v1/webhooks* and /api/v1/events* require Webhooks (canUseWebhooks).
{ "statusCode": 403, "message": "Platform webhooks are not enabled for this account", "error": "Forbidden"}The message string above is the live API text (still says “Platform webhooks”). Product docs and the admin UI label this surface Webhooks. Ask an OutboundSync admin to enable Webhooks for the account. Setup guide: Setting up webhooks.
429 rate limit exceeded
Section titled “429 rate limit exceeded”Authenticated /api/v1/* routes (including webhooks and events) apply two fixed-window limits:
| Layer | Limit | Window | When it applies |
|---|---|---|---|
| IP address | 120 requests | 60 seconds | Before API key validation |
| Account owner | 120 requests | 60 seconds | After API key validation |
When a request is rate limited, OutboundSync returns 429 and a Retry-After header with the number of seconds until the current window resets.
Retry-After: 37Retry pattern
Section titled “Retry pattern”async function getOutboundSyncMe(apiKey) { const response = await fetch('https://app.outboundsync.com/api/v1/me', { headers: { Authorization: `Bearer ${apiKey}` }, });
if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') ?? '60'; throw new Error(`OutboundSync rate limit exceeded. Retry after ${retryAfter} seconds.`); }
if (response.status === 401) { throw new Error('OutboundSync API key is missing, invalid, revoked, or rotated.'); }
if (response.status === 403) { const body = await response.json().catch(() => ({})); throw new Error(body.message || 'OutboundSync API request was forbidden.'); }
if (!response.ok) { throw new Error(`OutboundSync API request failed with ${response.status}.`); }
return response.json();}Ask an AI coding assistant
Section titled “Ask an AI coding assistant”Add retry handling for OutboundSync API calls.For 429, read Retry-After and wait that many seconds before retrying once.For 401, tell the user to check the Bearer osapi_ key.For 403, read the message: enable API access, request write scope, use an account-scoped key for /webhooks, or enable Webhooks.