Errors#
Every error response carries a stable, machine-readable error code and a
human-readable message:
{ "status": "error", "error": "invalid_api_key", "message": "Invalid API key." }
Match on error, not on the message text — messages may be reworded, codes won't.
Current error codes#
These are the codes reachable through the endpoints that exist today:
error |
Status | Likely cause | Fix |
|---|---|---|---|
invalid_api_version |
400 | Unsupported X-Api-Version (below minimum, above latest, or malformed CalVer) |
Send a valid YYYY.M.MICRO version in [minimum, latest], or omit the header to use latest (see Authentication) |
bad_request |
400 | A request is structurally valid but uses a disallowed current path, such as direct OAuth-token upload | Follow the provider's documented endpoint path; Basecamp OAuth tokens must be installed through OAuth |
missing_parameter |
400 | Authenticating with a user token but organization_id is absent |
Add ?organization_id=<id> (see Authentication) |
oauth_not_supported |
400 | OAuth was requested for a provider that does not implement OAuth install | Use the provider's documented credential method |
invalid_oauth_state |
400 | OAuth callback state is malformed, expired, tampered, or for a different provider | Restart the provider OAuth authorization flow |
oauth_authorization_failed |
400 | The OAuth provider redirected back with an authorization error | Retry authorization or check provider consent/client settings |
oauth_token_exchange_failed |
400 | The generic OAuth callback is missing or has invalid code/structural parameters | Retry authorization; confirm the callback shape, redirect URI, and OAuth client settings |
oauth_exchange_failed |
400 | Provider-specific OAuth exchange, installation binding, or stored bundle parsing failed | Restart authorization; verify the OAuth app redirect URI and provider installation |
invalid_api_key |
401 | Missing or unrecognized Bearer credential (service key or user token) | Check Authorization: Bearer <...>; for a user token confirm it is valid |
oauth_token_refresh_failed |
401 | Stored OAuth token is expired/revoked or cannot be refreshed | Re-authorize the provider for that organization |
insufficient_permissions |
403 | Valid user token, but the user is not a member of the requested organization | Use an organization_id the user belongs to |
unknown_provider |
404 | The provider name in the URL isn't a registered provider | Check the spelling against GET /api/v1/providers |
credential_not_found |
404 | Sync or credential verification was requested before an organization stored/installed provider credentials | Store an API credential or complete OAuth install for that provider |
projection_errors_remain |
409 | Confirm was requested while one or more imported task entries still have blocking projection errors | Resolve user mappings or edit the affected task entries, then confirm again |
oauth_not_configured |
503 | Provider OAuth app settings are missing or unusable in the service environment | Configure the provider OAuth env vars and restart the service |
capability_not_supported |
400 | The provider exists but does not support the requested capability or OAuth flow | Check the provider's declared capabilities and docs page |
oauth_provider_not_configured |
503 | Provider OAuth app environment variables are missing or incomplete | Configure the provider OAuth client id, secret, redirect URI, and scopes |
service_unavailable |
503 | A dependency (Mongo, Redis, or the TeamBoost platform API) is temporarily unreachable | Retry with backoff; check /health/ready |
More codes arrive with features
The error envelope already reserves codes for capabilities that aren't built
yet — for example webhook signature failures (invalid_signature) and job
state errors (invalid_job_state). They become reachable as those features
ship; see the Roadmap.