Tokens

A credential is not used directly on every call. It is exchanged once for a short-lived access token, which is sent on each request, and a long-lived refresh token, which is used to get the next pair.

Lifetimes

TokenLifetimeWhere it is set
Access token60 minutesapi.tokens.access_minutes
Refresh token30 daysapi.tokens.refresh_days

Sixty minutes is long enough for a request that runs for a few minutes to finish without stopping to renew, and short enough that a token copied out of a log or a proxy is worthless within the hour. A refresh call costs one request at the start of a run; a one-minute token would mean a renewal mid-request for no gain.

The credential’s own expiry date is a different thing: it is when the credential stops working entirely. Neither number is on the credential screen.

Exchange

POST /api/v1/tokens
Content-Type: application/json

{
  "client_id": "…",
  "client_secret": "…"
}

201 Created:

{
  "token_type": "Bearer",
  "access_token": "12|3fA9…",
  "expires_in": 3600,
  "refresh_token": "…",
  "refresh_expires_in": 2592000,
  "abilities": [
    "read",
    "write",
    "organisation:141",
    "scope:transactions.write",
    "scope:reference.read"
  ]
}

abilities is what the credential holds at the moment the token is issued: read and write for the two directions, organisation:{id} for each company it may reach, and scope:{resource}.{action} for each scope it holds. Nothing else. A call that needs an ability the token does not carry is refused with 403 before anything is read or written, so a read-only credential cannot send. The scopes themselves are listed on Endpoints.

Using the access token

GET /api/v1/organisations/141/requests
Authorization: Bearer {access_token}

A call with no header, or with a token whose credential was revoked or has expired, is refused with 401.

Renewing

POST /api/v1/tokens/refresh
Content-Type: application/json

{
  "refresh_token": "…"
}

The answer is the same shape as the exchange and carries a new refresh token.

The refresh token is spent when it is used. Sending the same one twice fails the second time, so a copy taken from the wire is worth at most one attempt — and that attempt is visible at the next exchange with the real one.

Refusals

StatusMessageCause
401The client id and secret do not match.Wrong client id, wrong secret, or a client id that does not exist
401This credential is revoked or has expired.Revoked on the screen, or past its expiry date
401The refresh token is no longer valid.Already used, expired, or never issued
401The account that owns this credential no longer exists.The credential’s creator was removed
429—More than 10 token requests a minute from one caller

A revoked credential also stops tokens already issued from it: the credential is re-read on every call, so revocation does not wait for the access token to expire.