Skip to content

Errors and rate limits

When to use this guide: Use this reference when an OutboundSync API request fails, returns 401, 403, or 429, 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.

{
"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.

StatusMeaningCommon causeWhat to do
200SuccessThe key is valid and has at least one API-enabled connection.Continue using the response.
401UnauthorizedMissing, malformed, revoked, rotated, or invalid API key.Confirm the Authorization: Bearer osapi_... header and rotate the key if needed.
403ForbiddenValid key, but API access, scopes, connection scope, or Webhooks block the route.See 403 forbidden below.
409ConflictSync retry is not eligible, missing context, or the CRM is not HubSpot/Salesforce.See POST /api/v1/syncs/:id/retry.
429Too many requestsThe IP or account exceeded the current fixed-window limit.Respect the Retry-After header before retrying.
500Server errorUnexpected server-side failure.Retry later; contact support if it repeats.

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"

A key can be valid but still forbidden. Treat the message as the stable signal:

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.

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.

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.

/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.

Authenticated /api/v1/* routes (including webhooks and events) apply two fixed-window limits:

LayerLimitWindowWhen it applies
IP address120 requests60 secondsBefore API key validation
Account owner120 requests60 secondsAfter 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: 37
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();
}
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.