Corteksa
GuidesIntegrations

Troubleshooting

Integrations — Troubleshooting

The most common integration failures, and the one-line fix. For the platform's standard error envelope, see Errors.

401 Unauthorized

The credential is missing, malformed, revoked, or expired. The exact message tells you which:

MessageCauseFix
Missing API key / Missing access tokenNo credential on the requestSend X-Api-Key: crtk_live_… or Authorization: Bearer crtk_live_… / crtk_oauth_…
Invalid or expired API keyUnknown, revoked, or past expires_atThe customer revoked it or it lapsed — reconnect with a fresh key
Invalid or revoked access tokenOAuth token unknown or revokedRe-run the OAuth flow (or refresh)
Access token expiredOAuth access token past its ~1h TTLUse the refresh_token grant to mint a new one
Token is not bound to a workspaceA hyper token with no workspaceThe credential is malformed — re-issue it

Treat a sudden 401 as "disconnected": clear the stored credential and prompt to reconnect. A revoked key or a revoked OAuth grant stops working on the very next call.

403 Forbidden

Authenticated, but the credential lacks the scope for that route. Scopes are route-name strings (read.contacts, create.deals, …).

  • Records: reading needs read.{objectSlug}, writing needs create/update/delete.{objectSlug}. Check the granted scopes in the /me response and confirm the object slug (schemas are customizable).
  • Public webhooks: managing subscriptions requires an API key or OAuth token — a human (JWT) caller is rejected with "Public webhooks must be managed with an API key or an OAuth token". Creating a subscription also needs read.{object_slug} — a webhook can only carry data the key could read.
  • Minting a key with a scope the creator doesn't hold → "You cannot grant scopes you don't hold: …". Grant only scopes the creating admin has (super-admins may grant any).

429 Too Many Requests

"API key rate limit exceeded" — the per-key fixed-window limiter (API_KEY_RATE_LIMIT_PER_MINUTE, default 120/min) tripped. Slow down, batch requests, or raise the limit. It applies to API-key traffic only, never human JWTs. (A Redis blip fails open — the limiter never locks out a valid key.)

OAuth token exchange errors

POST /oauth/token returns raw RFC 6749 JSON with a specific message:

MessageMeaning & fix
code and redirect_uri are required (400)Include both in the authorization_code body
invalid_grant: code is invalid, expired, or already usedCodes are single-use and live 60s — exchange immediately
invalid_grant: redirect_uri mismatchThe exchange redirect_uri must byte-match the one in the authorize request and the registered URI
invalid_grant: client_id mismatchThe client_id differs from the one the code was issued to
invalid_grant: PKCE required for public clientsPublic clients must send code_challenge (authorize) + code_verifier (token)
invalid_grant: PKCE verification failedThe code_verifier doesn't match the code_challenge (S256)
invalid_client: bad client secretConfidential client — wrong/missing client_secret
invalid_clientUnknown/inactive client_id
invalid_grant: refresh token / refresh token expiredRefresh token unknown, already rotated, or past 30d — reconnect. Note: presenting an already-rotated refresh token is treated as a leak and revokes the whole token family
  • 400 on the GET — unknown/inactive client_id, redirect_uri not an exact match of a registered URI, a requested scope the app isn't allowed, PKCE missing for a public client, or response_typecode. Show an error screen; never redirect the browser (the backend withholds redirect_to as an open-redirect defense).
  • 400 on the POST — approving when none of the requested scopes are grantable by this user's permissions ("None of the requested scopes can be granted by your account"). The user needs the underlying object permissions.
  • 401 — the user isn't logged in; send them to login and return to the exact consent URL with all query params preserved.

The call succeeds but returns fewer rows than expected

Scopes are only the coarse endpoint gate. Past it, every record query is re-filtered by the acting admin's live A/G/M/D level — a key that acts as an admin with M (mine) access sees only that admin's records, not the whole object. Raise the admin's access level or have the key act as an admin with broader rights. See Authorization.

Inbound webhooks never arrive

A subscription delivers a signed POST to your target_url (which must be HTTPS). If nothing arrives: confirm the subscription is active, that your endpoint returns 2xx quickly, and that you're verifying X-Corteksa-Signature correctly. Remember an event caused by your own key's write is intentionally never echoed back. See Webhooks.

Next

On this page