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
| Token | Lifetime | Where it is set |
|---|---|---|
| Access token | 60 minutes | api.tokens.access_minutes |
| Refresh token | 30 days | api.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.
Refusals
| Status | Message | Cause |
|---|---|---|
| 401 | The client id and secret do not match. | Wrong client id, wrong secret, or a client id that does not exist |
| 401 | This credential is revoked or has expired. | Revoked on the screen, or past its expiry date |
| 401 | The refresh token is no longer valid. | Already used, expired, or never issued |
| 401 | The 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.