Credential Tokenization
Refreshing somebody’s data every month should not mean keeping their bank password in your database. Tokenization moves that problem off your side without moving it wholly onto ours: the credentials are stored encrypted by the platform, under a key that only exists while you present the token you hold.
Neither half is enough on its own. That is the whole design, and it is worth understanding before you decide whether to use it — because it also decides what happens when something goes wrong.
Tokenization is enabled per application. Ask support to turn it on. It is available for direct executions and for Financial Rider, where it is what recurring access is built on — and this page stays the single explanation of how it works. It is also per engine: only an engine whose tokenized_access is true in List your engines can keep credentials — typically banks, telcos and utilities, sources worth reading again.
The two halves
You ask for a ticket
When you run an access for the first time, you ask for it to be tokenized — one setting, wherever the credentials are first typed: base_configurations.tokenized_access when you start a direct execution, or settings.tokenized_access when you create a Financial Rider session. What comes back is a ticket: single-use, short-lived, and useless for anything except the next step.
How the encryption works
This is the part that makes the split real rather than a promise.
The key you hold is not the encryption key
Your token_key is never used directly to encrypt anything. It is one input to a derivation: HMAC-SHA256 over your key, under a secret that lives only in our runtime environment. The result is the 256-bit key that actually opens the credentials, and it exists only for the moment it is used — it is never written down, on either side.
What that means in practice
This is shared responsibility, in the exact sense of the term. You are not handing us your customers’ credentials to look after; you are keeping the half that makes them readable. It also means the protection is only as good as how you store token_key — the one thing we cannot do for you.
Losing the key is final, and that is deliberate
There is no recovery path, no support ticket and no override. If the token key is lost, the stored credentials become bytes nobody can open — including us.
Final for the key — not for the connection. Losing the key loses the ability to refresh, nothing else: start a new session for the same customer_id, have your customer connect the same account, and exchange its ticket. The answer carries the same token_id with a new key, so the entry you keep for that connection — and everything you hang off it — goes on working. That is the only way back, and it involves your customer, because it involves their password. How to build it.
Design for that before it happens. A token key living in exactly one place, with no backup and no rotation plan, turns a routine database migration into a re-onboarding of every customer. Store it as you store any other secret you cannot recreate.
What a token can do, and for how long
A token is not a general-purpose credential. Its scope is fixed at the exchange, and a run can narrow it but never widen it:
It expires 90 days after the exchange, and using it does not extend that. When the date arrives, the stored credentials are deleted. Track it and renew the connection before it lapses — a quarterly job that never renews works for three months and then fails for everybody at once.
A token can also be locked by the source: if the institution rejects the stored credentials or blocks the account, the token stops running and says so. Retrying does not help and can make it worse — institutions count failed attempts. That is a conversation with your customer, and it ends with them connecting the account again.
One token per connection. A connection is your application, one source, one customer_id and one account at that source. Exchanging a ticket for a connection that already has a token renews it — the same token_id, a new key, the new run’s scope and expiry, renewed: true — instead of minting a second one. A renewal revokes nothing: token_id never changes for the life of a connection. Managing your customers’ connections turns that into a list you can show.
Managing your customers’ connections
A practical guide: what to keep on your side, and how to turn it into the screen your customer uses — BBVA, connected · Santander, needs your attention — with connect, reconnect and remove.
The rule underneath is one sentence: a connection is one row, and token_id is its key. It is the one field that never changes for the life of a connection — not on a refresh, not on a lock, not on a reconnection.
Everything after the first connection is the Direct Executions API, server to server. Exchanging a ticket, refreshing, checking and revoking a token are calls your backend makes with your application secret — Exchange a ticket, Initiate with a token, Check a token and Revoke a token. The widget and its API play no part in them: your customer is only needed to connect, or to reconnect.
What to keep, one row per connection
Never keep the password — you never had it, which is the point — nor the ticket once it is exchanged.
Connect, reconnect, remove
Connect: your customer adds a bank
Start a session for that customer’s customer_id — a Financial Rider session with tokenized_access, or a direct execution that asks for a ticket — and exchange the ticket for each connection at Exchange a ticket. An answer with renewed: false is a new row.
Reconnect: a lock, a changed password, an expiry coming
Exactly the same, with the same customer_id. Your customer signs in to the same account, and Exchange a ticket answers the same token_id, a new key and renewed: true: find the row by token_id, replace its key, and it is connected again. Nothing is revoked: the previous key simply stops working, and the row, its history and anything you hang off it stay.
Remove: your customer disconnects a bank, or leaves
Revoke the token and delete the row — and the executions that used it, when they withdraw their consent. That connection is over: connecting that account again later is a new row, with a new token_id.
A different username is a different account, so it is a new row even at the same bank — your customer may well have two. If a reconnect comes back with a new token_id, they signed in to another account: show it as a new connection, and leave the old one to be reconnected or removed.
What each row shows
The whole rule in code
Every Exchange a ticket answer is an upsert keyed by token_id:
There is nothing to deduplicate and nothing to compare yourself — not locking_hash, not the bank’s name: the exchange has already decided whether this is a connection you have. An exchange that answers 409 overlapped another of the same ticket — a retry: wait for that one, or retry after its Retry-After.
If you lose a key
You lose the refresh of that connection, not the connection. Start a new session for the row’s customer_id and have your customer connect the same account: the exchange answers the row’s own token_id with a new key, and the row works again — keep the new key somewhere you cannot lose it this time. Under a different customer_id, the same account would be another connection, and the old row would stay without a key.
Revoking
Revocation is immediate and irreversible: no execution can use the token afterwards, and the stored credentials are marked for deletion. Call it when a customer withdraws consent, closes their account with you, or asks you to stop — and after any suspicion that your half leaked.
Your customer’s right to be forgotten is two calls, not a support ticket. Revoke the token, delete the executions that used it. Both are immediate, and neither needs us.