GRANSKA

Get a token

POSThttps://api.granska.cloud/v1/oauth/token

Exchanges a client id and secret for a short-lived bearer token.

No credentialsSpends no quota

The narrative version of this — where a client id and secret come from, how long a token lives, what to do when one expires — is on Authentication. This page is the endpoint itself.

Request body

JSON, three fields, all required. grant_type must be client_credentials; any other value is rejected with 400 UNSUPPORTED_GRANT_TYPE rather than ignored, so a client that sends the wrong grant finds out immediately instead of receiving a token it did not ask for.

The client_secret is sent here and to nowhere else. Every other endpoint takes the resulting access_token as Authorization: Bearer <token>.

ParameterDescription
grant_type
"client_credentials"·body·required
The only grant this gateway supports.
client_id
string·body·required
The identifier issued with the API key.
client_secret
string·body·required
The secret issued with the API key. Sent only to this endpoint, never on other calls.
Request
curl -X POST https://api.granska.cloud/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "cli_9f3a2b7c",
    "client_secret": "sk_live_2c8e41d0a7b6"
  }'
Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

The response

access_token is the bearer token. token_type is always Bearer. expires_in is the remaining lifetime in seconds — read it rather than hardcoding the current value, which is one hour.

There is no refresh token and no revocation endpoint. When a token expires you request another one the same way; requesting a token spends no quota, so a client that fetches one per hour, or simply one on every 401 TOKEN_EXPIRED, is behaving correctly.

Errors

401 UNAUTHORIZED does not distinguish an unknown client id from a wrong secret from a deactivated key. That is deliberate: the alternative lets a caller enumerate valid client ids by watching which ones come back with a different status.

503 SERVICE_UNAVAILABLE is the one failure here worth retrying. It means the credential store was briefly unreachable, not that the credentials are wrong, and the response carries Retry-After.

ErrorWhen
400
BAD_REQUEST
client_id or client_secret is missing.
400
UNSUPPORTED_GRANT_TYPE
grant_type is anything other than client_credentials.
401
UNAUTHORIZED
The client id is unknown, or the secret does not match it.
500
INTERNAL_ERROR
An unexpected server-side failure. Not probable from outside — reaching it means something is wrong.
503
SERVICE_UNAVAILABLE
The credential store is transiently unavailable; a Retry-After header says when to try again. Not probed: it needs an injected infrastructure failure.

Send it without writing a client

If your organisation already has an account, an administrator can exchange a key for a token in the API tester at /admin/api-tester, which is also the fastest way to check that a newly created key works.