Skip to main content

Authentication

An API key is a pair: a ClientID, which is not confidential, and a secret, which is. You never send the secret with ordinary requests. You exchange the pair for an access token and send the token instead.

Exchange the key for a token​

Send the ClientID and secret as HTTP Basic credentials to POST /v1/token:

curl -X POST https://server.api.throughline.dk/v1/token \
-u "$THROUGHLINE_CLIENT_ID:$THROUGHLINE_CLIENT_SECRET"
{ "accessToken": "eyJhbGciOi…", "tokenType": "Bearer", "expiresIn": 900 }

expiresIn is in seconds: a token lasts 15 minutes. A wrong ClientID or secret answers 401 with the code invalid_client, and so does a key that has been revoked.

Use the token​

Send the token as a bearer token on every other route:

curl https://server.api.throughline.dk/v1/contacts/user-42 \
-H "Authorization: Bearer $THROUGHLINE_TOKEN"

A missing, malformed or expired token answers 401 with the code unauthenticated. Exchange the key again and repeat the request once. There is no refresh token; the exchange is the refresh.

Exchange once and reuse the token for its 15 minutes, rather than exchanging before every call. The exchange checks the secret against a slow hash on purpose, so it is the most expensive call you can make.

The client does all of this for you: it exchanges on the first call, shares one exchange between concurrent calls, and on a 401 exchanges again and replays the request.

const throughline = new ThroughlineClient({
clientId: process.env.THROUGHLINE_CLIENT_ID!,
secret: process.env.THROUGHLINE_CLIENT_SECRET!,
});

Keep the secret on your server​

The secret grants whatever Scopes the key holds, over every Contact in your Tenant. Keep it in your secret store and out of anything a browser downloads. For code that runs in a browser, use a publishable key instead; it can only record Events and carries no secret.

We store only a hash of the secret, so we cannot show it again. If you lose it, create a new key and revoke the old one.