Skip to main content
The Cula Tracking API uses OAuth2 client credentials for authentication. Each consumer receives a client_id and client_secret, exchanges them for a short-lived access token, and passes that token on every API request alongside an organisation context header.

Obtaining credentials

Credentials are issued by the Cula team. Each credential set represents a single consumer — typically an integration partner or system. Contact your Cula representative to receive your client_id and client_secret.
Credentials are managed by Cula. They cannot be created or rotated via the API.

Getting an access token

Exchange your credentials for an access token by calling the token endpoint with the client_credentials grant type. Authenticate using HTTP Basic auth with your client_id as username and client_secret as password.
curl -X POST https://auth.demo.cula.earth/oauth2/token \
  -u "$CULA_CLIENT_ID:$CULA_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials"
The response contains your access token:
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_in": 300,
  "token_type": "bearer"
}
FieldDescription
access_tokenThe Bearer token to use in API requests
expires_inToken lifetime in seconds
token_typeAlways bearer

Making authenticated requests

Every request requires two headers:
  1. Authorization — the access token as a Bearer token.
  2. Cula-Organisation-Id — the organisation to scope this request to.
curl https://api.demo.cula.earth/tracking/v1/sites \
  -H "Authorization: Bearer $CULA_ACCESS_TOKEN" \
  -H "Cula-Organisation-Id: your-organisation-id"

Access model

Each consumer is authorized to access one or more organisations. How many depends on your role:
  • Tracking data providers (e.g. biochar producers, project operators) typically access their own organisation only. They write process tracking data — sourcing steps, deliveries, emission logs — into their org.
  • Tracking data consumers (e.g. credit marketplaces, registry platforms) typically have read access to multiple organisations whose tracking data they need to query. A marketplace that sells credits on behalf of several producers would use a single consumer with access to each producer’s organisation.
In both cases, the consumer authenticates with one set of credentials. The Cula-Organisation-Id header on each request determines which organisation is being accessed.

Organisation context (Cula-Organisation-Id)

The Cula-Organisation-Id header tells the server which organisation to scope each request to.
  • The header is required on every request. There is no default organisation.
  • Omitting the header returns 400:
{
  "error": {
    "type": "validation_error",
    "code": "missing_header",
    "message": "The Cula-Organisation-Id header is required. Every request must specify the target organisation.",
    "param": "Cula-Organisation-Id",
    "request_id": "req_01abc..."
  }
}
  • Passing an organisation your consumer is not authorized for returns 403:
{
  "error": {
    "type": "auth_error",
    "code": "org_not_authorized",
    "message": "The authenticated consumer is not authorized to access this organisation.",
    "request_id": "req_01abc..."
  }
}

Token lifecycle

Access tokens are short-lived. When a token expires, request a new one from the token endpoint — the client credentials flow does not use refresh tokens. Your application should handle 401 responses by requesting a fresh token and retrying the request.
Do not hardcode or cache tokens beyond their expires_in lifetime.

Credential rotation

Cula can issue a new client_secret for your consumer. The previous secret remains valid until explicitly revoked, allowing zero-downtime rotation:
  1. Request a new secret from your Cula representative.
  2. Update your systems to use the new secret.
  3. Confirm the old secret can be revoked.