OAuth 2.0 authentication for the Tink API.
Token lifetimes
Per the Tink docs:
- Client access token (client_credentials grant): expires in 1800 seconds (30 minutes)
- User access token (authorization_code grant): expires in 7200 seconds (2 hours)
Neither token type includes a refresh_token by default. Re-authenticate using the same grant flow to obtain a new token.
Authentication methods
Tink supports two OAuth client authentication methods:
- Client credentials (
client_id+client_secret) — standard, used by this SDK - Mutual TLS (mTLS) — for interoperability. Configure via
Tink.HTTP.MutualTLS.
Flows
1. Client credentials (server-to-server)
{:ok, app_client} = Tink.Auth.client_credentials(scope: "authorization:grant user:create")2. Full user token flow
# Step 1 — app client
{:ok, app_client} = Tink.Auth.client_credentials(scope: "authorization:grant")
# Step 2 — create authorization grant
{:ok, %{"code" => code}} = Tink.Auth.create_authorization(app_client,
user_id: tink_user_id,
scope: "accounts:read,transactions:read,balances:read"
)
# Step 3 — build Tink Link URL and redirect user
url = Tink.Link.build_url(:transactions, %{
client_id: Tink.Config.client_id(),
authorization_code: code,
redirect_uri: "https://yourapp.com/callback",
market: "GB"
})
# Step 4 — exchange redirect code for user token
{:ok, user_client} = Tink.Auth.user_client(redirect_code)3. Inspect a token
{:ok, info} = Tink.Auth.inspect_token(client)4. Proactive refresh check
if Tink.AuthToken.should_refresh?(client) do
{:ok, client} = Tink.Auth.client_credentials(scope: client.scope)
end
Summary
Functions
Obtain an application-level access token via client credentials grant.
Create an authorization grant code for a permanent Tink user.
Create a delegated authorization grant. Requires authorization:grant scope.
Inspect the current token's scopes and validity.
Refresh an access token using a refresh_token.
Revoke all tokens for the current user. Requires authorization:revoke scope.
Exchange a Tink Link redirect code or auth grant code for a user access token.
Functions
@spec client_credentials(keyword()) :: {:ok, Tink.Client.t()} | {:error, Tink.Error.t()}
Obtain an application-level access token via client credentials grant.
Token expires in 1800 seconds (30 min) per Tink docs.
Options
:scope— space-separated scopes (required):client_id— override configclient_id:client_secret— override configclient_secret
@spec create_authorization( Tink.Client.t(), keyword() ) :: {:ok, map()} | {:error, Tink.Error.t()}
Create an authorization grant code for a permanent Tink user.
Requires authorization:grant scope on the client.
Per the Tink docs, this endpoint expects application/x-www-form-urlencoded
parameters using snake_case keys (NOT a JSON body):
curl -X POST https://api.tink.com/api/v1/oauth/authorization-grant \
-H 'Authorization: Bearer ' \
-d 'user_id=CREATED_USER_ID' \
-d 'scope=accounts:read,transactions:read'Options
:user_id— Tink internal user ID:external_user_id— your system's user ID (alternative to:user_id):scope— comma-separated required scopes:id_hint— optional display hint for the user
@spec delegate_authorization( Tink.Client.t(), keyword() ) :: {:ok, map()} | {:error, Tink.Error.t()}
Create a delegated authorization grant. Requires authorization:grant scope.
Like create_authorization/2, this endpoint expects form-urlencoded
snake_case parameters. It additionally requires :actor_client_id — the
client_id of the application that will act on behalf of the user (this
is typically the same as your own client_id unless you are delegating to
a partner app):
curl -X POST https://api.tink.com/api/v1/oauth/authorization-grant/delegate \
-H 'Authorization: Bearer ' \
-d 'external_user_id=' \
-d 'actor_client_id=df05e4b379934cd09963197cc855bfe9' \
-d 'id_hint={End user name/username}' \
-d 'scope=authorization:read,authorization:grant,credentials:refresh,...'Options
:user_id— Tink internal user ID:external_user_id— your system's user ID (alternative to:user_id):actor_client_id—client_idof the delegated/acting application (required):client_id— override configclient_id(your own application'sclient_id):scope— comma-separated required scopes:id_hint— optional display hint for the user
@spec inspect_token(Tink.Client.t()) :: {:ok, map()} | {:error, Tink.Error.t()}
Inspect the current token's scopes and validity.
@spec refresh(Tink.Client.t(), String.t(), keyword()) :: {:ok, Tink.Client.t()} | {:error, Tink.Error.t()}
Refresh an access token using a refresh_token.
Note: Tink does not typically issue refresh_tokens for client_credentials or standard authorization_code flows. This is provided for integrations where a refresh_token is returned (e.g. certain mTLS flows).
@spec revoke_all(Tink.Client.t()) :: {:ok, map()} | {:error, Tink.Error.t()}
Revoke all tokens for the current user. Requires authorization:revoke scope.
@spec user_client( String.t(), keyword() ) :: {:ok, Tink.Client.t()} | {:error, Tink.Error.t()}
Exchange a Tink Link redirect code or auth grant code for a user access token.
Token expires in 7200 seconds (2 hours) per Tink docs.