Skip to main content
POST
/
auth
/
token
To access the platform, you must first have an access token. Through this URL, you can obtain one — but be careful! The access token expires after 1 hour. After this period, you will need to re-authenticate.
curl --request POST \
  --url https://api.cartevo.co/api/v1/auth/token \
  --header 'Content-Type: application/json' \
  --data '
{
  "client_id": "<string>",
  "client_key": "<string>"
}
'
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJlY2E1ZTk4Mi0wMGI1LTRhYTItYjcwOS03ZDVjZDY3M2U5NWMiLCJjb21wYW55SWQiOiJlY2E1ZTk4Mi0wMGI1LTRhYTItYjcwOS03ZDVjZDY3M2U5NWMiLCJjbGllbnRJZCI6ImNsaWVudF91dGtxNnV5MnB0IiwiaWF0IjoxNzYyMTY4MDIzLCJleHAiOjE3NjIxNzE2MjN9.hloSSSPJ2WFa31s41BL1nqhemuwHCJKC_wcwVupsBlU",
  "token_type": "Bearer",
  "expires_in": 3600
}

Overview

POST /auth/token exchanges your business credentials (client_id and client_key) for a short-lived Bearer access token. Every other Cartevo endpoint requires this token in the Authorization header. There is no refresh-token endpoint — when a token expires, call this endpoint again.

When to use it

  • Once at the start of any worker, cron job, or HTTP request that needs to call Cartevo.
  • Whenever a previous token is about to expire (recommended: refresh ~5 minutes before expires_in runs out).
  • After a 401 Unauthorized response from any other endpoint — refresh and retry once.

Prerequisites

  • An active Cartevo company account.
  • A client_id / client_key pair, available from the dashboard at Settings → API Keys.

Request

Headers

NameRequiredDescription
Content-TypeYesMust be application/json.
No Authorization header is required for this endpoint.

Body

FieldTypeRequiredDescription
client_idstringYesYour business client identifier (begins with client_).
client_keystringYesYour business client secret. Treat as a password — never commit or share.
{
  "client_id": "client_abcdef123456",
  "client_key": "key_xyz9876543210"
}

Response

200 — Success

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI...",
  "token_type": "Bearer",
  "expires_in": 3600
}
FieldTypeDescription
access_tokenstringThe JWT to send in the Authorization: Bearer <token> header on every other request.
token_typestringAlways "Bearer".
expires_inintegerToken lifetime in seconds. Treat this value as authoritative — do not hard-code an expiry length.
Note: This endpoint returns the raw response shown above — it is not wrapped in the standard { success, statusCode, message, data } envelope used elsewhere. See API Conventions → Response envelope.

Error responses

StatusTriggerRecommended action
400client_id or client_key missing or empty.Fix the request body.
401client_id does not exist, client_key is wrong, or the account is disabled.Verify credentials in the dashboard. Do not retry without changing credentials.
429Rate limit exceeded (default 10 req / 60 s per IP).Back off, then retry. Cache the access token aggressively rather than minting a new one each call.
{
  "message": "Invalid client credentials",
  "error": "Unauthorized",
  "statusCode": 401
}

Token scope and lifetime

  • Scope: Each token is bound to one company in one mode (preproduction or production). It cannot operate on another company’s data, and it cannot cross modes.
  • Lifetime: Determined by the deployment configuration. Treat expires_in as the only authoritative value. The current production default is short-lived (typically 1 hour); preproduction may differ.
  • Revocation: There is no per-token revocation endpoint. Rotating the underlying client_key immediately invalidates all tokens minted from it.

Code examples

cURL
curl -X POST https://api.cartevo.co/api/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "client_abcdef123456",
    "client_key": "key_xyz9876543210"
  }'
Node.js (axios)
import axios from "axios";

const { data } = await axios.post(
  "https://api.cartevo.co/api/v1/auth/token",
  {
    client_id: process.env.CARTEVO_CLIENT_ID,
    client_key: process.env.CARTEVO_CLIENT_KEY,
  }
);

const accessToken = data.access_token;
const expiresAt = Date.now() + data.expires_in * 1000;
Python (requests)
import os, requests

resp = requests.post(
    "https://api.cartevo.co/api/v1/auth/token",
    json={
        "client_id": os.environ["CARTEVO_CLIENT_ID"],
        "client_key": os.environ["CARTEVO_CLIENT_KEY"],
    },
    timeout=10,
)
resp.raise_for_status()
token = resp.json()["access_token"]
PHP (Guzzle)
$client = new GuzzleHttp\Client();
$response = $client->post("https://api.cartevo.co/api/v1/auth/token", [
    "json" => [
        "client_id" => getenv("CARTEVO_CLIENT_ID"),
        "client_key" => getenv("CARTEVO_CLIENT_KEY"),
    ],
]);
$data = json_decode($response->getBody(), true);
$accessToken = $data["access_token"];

Best practices

  • Cache the token in your server for expires_in - 300 seconds and reuse it across requests — do not mint a new token per call.
  • Refresh preemptively. Schedule a refresh ~5 minutes before expiry so in-flight requests never hit a 401.
  • Never expose client_key or the access_token to browsers, mobile apps, or any client-side code. Always proxy through your server.
  • Rotate client_key immediately if you suspect compromise. Existing tokens minted from it remain valid until expiry — there is no per-token revocation.
  • Use separate credentials per environment (preproduction vs. production) so a leaked test key cannot touch live money.

Webhooks fired

None. This endpoint is purely synchronous.

Body

application/json
client_id
string
required
client_key
string
required

Response

Authentication successful

access_token
string
required

JWT access token for API authentication

Example:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJlY2E1ZTk4Mi0wMGI1LTRhYTItYjcwOS03ZDVjZDY3M2U5NWMiLCJjb21wYW55SWQiOiJlY2E1ZTk4Mi0wMGI1LTRhYTItYjcwOS03ZDVjZDY3M2U5NWMiLCJjbGllbnRJZCI6ImNsaWVudF91dGtxNnV5MnB0IiwiaWF0IjoxNzYyMTY4MDIzLCJleHAiOjE3NjIxNzE2MjN9.hloSSSPJ2WFa31s41BL1nqhemuwHCJKC_wcwVupsBlU"

token_type
string
required

Type of token

Example:

"Bearer"

expires_in
integer
required

Token expiration time in seconds

Example:

3600