IntegrationsAPI Reference

Authentication

OAuth 2.0 client credentials flow for Carrot API access.

Last updated on

Carrot API uses OAuth 2.0 client credentials with bearer tokens. There is no user login step. Integrations authenticate with a clientId and clientSecret.

Authentication flow

  1. Receive clientId and clientSecret from the Carrot API team.
  2. Request an access token from the auth endpoint using Basic Authentication.
  3. Use the returned bearer token in the Authorization header on API requests.
curl --request POST \
  --url https://auth.api.carrot.eco/oauth2/token \
  --header 'Authorization: Basic <clientId:clientSecret in base64>' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'scope=api.carrot.eco/main-scope'

Token lifecycle

  • access_token maximum duration is currently 1 hour.
  • expires_in is returned by the token endpoint response and must be treated as API-provided runtime data (not hard-coded in your integration).
  • Refresh tokens are not used in this flow.
  • Request a new token before expiry to avoid request failures.

Token response format

Typical successful response:

{
  "access_token": "<jwt-or-opaque-token>",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "api.carrot.eco/main-scope"
}

Applying bearer tokens

Send your token on each request:

Authorization: Bearer <access_token>

Environment behavior

Environment is controlled by credentials, not by URL.

  • Test credentials operate only on test data.
  • Production credentials operate only on production data.
  • A test token cannot modify production documents, and the reverse is also true.

See Environments for operational guidance.

Common auth errors

  • 401 — the token could not be parsed: no Authorization header, or a bearer value that is not a decodable JWT. The body is {"message":"Unauthorized"}, with no code field.
  • 403 (edge authorizer) — the token parsed but was rejected: expired, invalid signature, non-Bearer scheme, scope not allowed, or issuer mismatch. The body is {"message":"<reason>"}, for example {"message":"Authorization token expired"}. There is no errors[] envelope.
  • 403 (RESTRICTED_RESOURCE_ERROR) — a valid token without permission for the target resource, including a test credential touching production data or the reverse. The body is the standard errors[] envelope described in Errors.

Refresh on 403, not 401

An expired token never produces a 401 — it is rejected at the edge as a 403, so token-refresh logic keyed on 401 will never fire. Refresh only when the gateway body identifies expiry ({"message":"Authorization token expired"}). The other 403 causes — bad signature, wrong scope or issuer, RESTRICTED_RESOURCE_ERROR — are not fixed by a new token, and retrying them after a refresh only loops.


Environments · Quick Start · Error Handling

On this page