The Tink connector links Formance to Tink's European bank-aggregation platform. It drives the Open Banking PSU flow across Tink's markets: create a Payment Service User, forward them to Tink, hand them a Tink Link session, and sync the resulting accounts, balances, and transactions back through Connectivity. Available from Payments 3.2.0.
Prerequisites#
You need a Tink account and a clientID + clientSecret pair. Tink uses OAuth2 client-credentials; the connector exchanges the credentials for a short-lived bearer token and refreshes automatically.
Covered EU markets: AT, BE, DE, DK, EE, ES, FI, FR, GB, IE, IT, LV, LT, NL, NO, PL, PT, SE. Tink enforces market restriction at the Link session.
Make sure to create an API key dedicated to Formance. Doing so will improve your auditability and security and will allow you to revoke access to Formance at any time if needed.
Installation#
curl -X POST $FORMANCE_API_URL/api/payments/v3/connectors/install/tink \
-H "Content-Type: application/json" \
-d @config.jsonConfiguration fields#
| Field | Type | Required | Default |
|---|---|---|---|
clientID | string | Yes | |
clientSecret | string | Yes | |
endpoint | string | Yes | |
pageSize | integer | No | 25 |
pollingPeriod | string | No | 30m |
endpoint is https://api.tink.com. No separate sandbox endpoint — Tink uses test users on the same host.
Capabilities#
FETCH_ACCOUNTS— depository accounts per PSU connection.FETCH_BALANCES— available + booked balance per account.FETCH_EXTERNAL_ACCOUNTS— counterparty accounts when Tink Payments identifies them.FETCH_PAYMENTS— transactions, paginated viapageToken.CREATE_WEBHOOKS+TRANSLATE_WEBHOOKS— webhooks per PSU user for account-data-refreshed and consent-expiry events.
The connector doesn't initiate transfers or payouts — Tink Payments (the outbound product) isn't wired here.
Account model#
Every Connectivity internal account is one Tink Account (a depository account on a linked connection). The reference is the Tink account ID; name is the account name; defaultAsset is null — Tink's account payload doesn't surface currency at the account level reliably, so balance assets are inferred per-cycle via FETCH_BALANCES. Accounts are PSU-scoped — psuID tracks the PSU and openBankingConnectionID is set when Tink's webhook payload carries the connection ID. EXTERNAL accounts are emitted when Tink Payments identifies them. See Accounts for the cross-connector model.
Linking a user#
Tink's auth ceremony runs through Tink Link:
- Create a PSU —
v3CreatePaymentServiceUserreturns a PSU ID. - Forward to Tink —
v3ForwardPaymentServiceUserToProvidercreates a Tink user and stores theuser_idas PSU metadata. - Create a Link session —
v3CreateLinkForPaymentServiceUserreturns ahttps://link.tink.com/1.0/transactions/...URL +attemptID. - Frontend redirect — the user picks a bank, completes SCA, and lands on your
clientRedirectURLwith an authorization code on the query string. - Refresh-finished webhook — the connector exchanges the code for a
refresh_tokenand binds the connection.
Step-by-step walkthrough on the Open Banking Getting Started guide.
Redirect URL requirements#
- HTTPS in production.
- Registered under your Tink client's allowed redirect URIs.
- Mobile apps follow Tink's Android and iOS optimisation guides for the in-app browser flow.
Asset model#
Multi-currency, formatted to UMN at ISO 4217 precision. Amounts are already in minor units.
Status mapping#
Tink transactions arrive in three lifecycle states:
Tink status | Payment status |
|---|---|
PENDING, UNDEFINED | PENDING |
BOOKED | SUCCEEDED |
| anything else | UNKNOWN |
When a PENDING transaction matures to BOOKED, Tink replaces the provisional ID with a permanent one — the connector swaps the reference and moves the row to SUCCEEDED.
Metadata keys#
Under com.tink.spec/:
- Account:
account_id,name,iban,bic,account_number,holder_name,type(CHECKING/SAVINGS/CREDIT_CARD/ …),flags. - External account:
counterparty_name,counterparty_account_number,counterparty_iban. - Payment:
transaction_id,provider_transaction_id,merchant_category_code,description,payee_message,payer_message,transaction_code.
PSU-level metadata carries user_id — the Tink user the connector created.
Workflow tree#
FetchAccounts (periodic) — per PSU
├── FetchBalances (FromPayload — no extra API call)
└── FetchPayments (periodic) — per PSU/account, pageToken cursor
FetchExternalAccounts (periodic)
CreateWebhooks — provisioned automatically on linkPagination and recovery#
/data/v2/transactions uses pageToken-based pagination. The connector persists the cursor per PSU/account in platform-managed State; restarts resume from the last committed cursor.
Known gaps#
- Tink Payments (outbound initiation) is not wired.
- Identity and Income products aren't surfaced.
- Consent expiry: connections expire after the PSD2 SCA window (~90 days). Tink emits
consent_expired; the connector translates it to aUserConnectionPendingDisconnect→UserConnectionDisconnectedpair. Trigger a fresh link viav3UpdateLinkForPaymentServiceUserto renew.