X-API-Key, like any key (Authentication), or exchange it for a short-lived bearer token with the standard OAuth 2.0 client-credentials grant, so an OAuth client library can authenticate without TetraFi-specific code.
The API may change until launch. Every change is listed in the Changelog.
Create a service account
- In the app, open Identity & access, then Service accounts.
- Select Create service account, give it a Name and choose its Role. Description and Expires are optional.
- Copy the account’s user ID: it is the
client_idof the token request. - Open the account, then API keys, and select New key. In Create service-account key, give it a Key name and select Create key.
- Copy the key. It is shown once and is the
client_secretof the token request. Store it in your secret manager, never in source code or a tracked file.
Its sponsor
Every service account has a sponsor: the member who is accountable for it, by default the one who created it. The account can never do more than its sponsor can do now: its permissions are its role intersected with the sponsor’s current permissions, checked on every request. If the sponsor’s own permissions shrink, the account’s shrink with them. When the sponsor stops being a current, unsuspended member of the workspace, the account’s keys can no longer trade from organisation wallets: those orders, and later steps of a trade already placed, are refused with409 SERVICE_ACCOUNT_SPONSOR_NOT_CURRENT. Give the account a current member as sponsor to resume.
Exchange the key for a token
Send a form-encodedPOST /api/v1/oauth/token (RFC 6749, section 4.4):
You can send
client_id and client_secret in an HTTP Basic Authorization header instead of the form. The answer is the standard token response:
There is no refresh token: when a token is about to expire, exchange the key again. Keep tokens in memory only; the key is the credential to protect. The script
samples/http/oauth.sh runs every step on this page:
Output on test networks
Check what the token can do
GET /api/v1/me with the token answers for the key it was exchanged from, the same way it answers that key sent as X-API-Key (Send the key):
organisationWallets is the key’s organisation-wallet trading. Its blockedBy, when present, is the code an organisation-wallet order would be refused with now (Check what a key can trade from).
Output on test networks
/me reads them live, so call it again instead of trusting the token answer’s scope for the token’s whole life.
Send the token
Send the token asAuthorization: Bearer <access_token> on every request, in place of X-API-Key. It works in the service account’s workspace only.
Output on test networks
When the exchange is refused
A refused exchange answers the RFC 6749 error body,{"error", "error_description", "error_uri"}, not the JSON error body of other API refusals:
invalid_client, 401. Theclient_idorclient_secretis wrong, or the key is not an active key of an active service account. The answer carries aWWW-Authenticate: Basicchallenge. Check both values, and create a new key if this one was revoked or has expired.invalid_grant, 400.grant_typeis missing, or the form cannot be read. Send the three fields, form-encoded.unsupported_grant_type, 400.grant_typeis notclient_credentials.unauthorized_client, 400. The key may not be exchanged: it requires request signing or holds venue trading, anderror_uriends with#SIGNED_KEY_NOT_EXCHANGEABLE. Use another key of the account, or send this one as a signedX-API-Key(Sign requests).temporarily_unavailable, 503. TetraFi could not read the account’s current authority. Retry shortly.
Output on test networks
expires_in has passed is refused with 401 and the challenge WWW-Authenticate: Bearer error="invalid_token" (RFC 6750): exchange the key for a new one. A refused API key carries no challenge.