Skip to navigation

Stored credentials

Run the same access again next month without keeping the password
View as Markdown

Tokenization replaces a stored password with a token: an identifier and a key that mean “run that access, through this application, for that customer, for these features” — and nothing else, anywhere else. You keep the key half; the platform keeps the credentials, encrypted under something only your key can derive.

(The token’s first run can also happen in an experience INFONITE hosts — a Financial Rider session, where your customer signs in to their bank in our widget, which is what we call recurring access.)

Tokenization is enabled per application. If yours does not have it, asking for tokenized_access when you start an execution is refused with 403 and detail: insufficient_capabilities@login:tokenized_access — no ticket is ever issued, and no execution is created. The part before the @ is the stable code to branch on; what follows names the capability you are missing. A sandbox run is never refused for it: every application may rehearse anything.

Before production

Recurring access in production needs Tokenized access

Every application can tokenize in sandbox. In production, asking for tokenized_access without the Tokenized access capability is refused with 403 and insufficient_capabilities@login:tokenized_access — no ticket is issued and nothing is created.

And per engine. Not every engine can keep credentials: each one says so in tokenized_access, on List your engines and Show engine details. Banks, telcos and utilities — sources worth reading again — typically can. Asking an engine that cannot is refused before anything is created: 400 with T10N_NOT_AVAILABLE.


How you get a token

1

Ask for a ticket when you start an execution

Send base_configurations.tokenized_access: true to Initiate with parameters. The 202 comes back with a ticket — a single-use, short-lived string that exists only to be exchanged.

2

Exchange it, once

Exchange a ticket takes the execution_id and the ticket, and returns the real thing: a token_id and a token_key, plus the context the token is locked to.

3

Use it instead of credentials

Initiate with a token takes token where the other endpoint takes parameters. Everything else about the execution behaves identically.

What the exchange returns
{
"token": {
"token_id": "6aa3d8b418d1c5dc9a8e3d36",
"token_key": "a3f1…"
},
"context": {
"engine_reference": "DEMOBANKXXXXFIN100ES9999-mobile",
"customer_id": "my-customer-1",
"locking_hash": "v1.36GHPwfDK-UUZGG4fb1jtg",
"features": ["customer_information_read", "accounts_read", "cards_read"]
}
}

Store both halves, and treat token_key like a password. It is the only copy — no screen, no endpoint and no support agent will read it back to you, because nothing on our side holds it. Lose it and the stored credentials can never be opened again, by anyone — until your customer connects the same account again, which renews the token with a new key. Why that is, and why it is deliberate.


What a token is allowed to do

The scope is fixed at the exchange, and no run can widen it.

Locked toMeaning
One applicationYours. A token is meaningless without your application secret alongside it.
One engineThe one that produced it.
One customerThe customer_id of the execution whose ticket you exchanged. Sending a different one changes nothing.
A set of featuresYou may request fewer on a given run. Requesting one that was not in the original scope is refused.

Need a wider scope? Run a parametrized execution with the credentials and the features you want, and exchange its ticket: that renews the token with the new scope. That is deliberate: broadening what stored credentials may reach should require the credentials again.

Validity is 90 days from the exchange, and using the token does not extend it. When the date arrives, the stored credentials are deleted and the token stops existing.

Put the renewal in your calendar, not in your incident log. A quarterly re-run that never re-mints its tokens works perfectly for three months and then fails for everybody at once. Read date_expiration from Check a token, and renew the connection before it lapses — a new execution with the credentials, and its ticket exchanged: the same token_id, a new key and a new date.


One token per connection

A connection is your application, one engine, one customer_id of yours and one account at that source — the account is what locking_hash identifies. A connection has one token for life, and token_id is the field that never changes: it is the identifier to keep your customers’ connections by.

Exchanging a ticket for a connection you already hold a token for does not mint a second token, and does not revoke the one you have: it renews it. Same document, same token_id; what changes is the key, and with it what the token holds.

FieldOn a renewal
token_idKept. The identifier you stored for this connection.
token_keyNew. The previous key stops working the moment the exchange answers.
renewedtrue — false when the exchange created the connection.
context.source_execution_idThe execution whose ticket you just exchanged: the credentials the token holds now.
context.featuresThe scope of that execution: your customer consented again.
date_expiration90 days from this exchange.
status_codeT10N_OK, whatever lock it had.
date_createdKept: when the connection was first created.
Your customer…The exchange returns
connects the same account again — a changed password, a lock, an expiry comingthe same token_id, a new token_key, and renewed: true
connects with a different username at the same sourcea new token_id: another account, another connection
connects the same account under another customer_id of yoursa new token_id: each customer’s connections are kept apart

Keeping the list

Every exchange answer goes into your list by token_id: there is no other field to match on, nothing to deduplicate, and no need to compare locking_hash yourself. Managing your customers’ connections is the practical guide — what to keep per connection, the connect, reconnect and remove flows, what each row shows, and the upsert in code.

Renewing is not revoking. A renewal keeps the connection and changes its key; Revoke a token ends the connection — the credentials are deleted, and if your customer connects that account again later, it is a new connection with a new token_id.


Reading a token’s health

Check a token is the endpoint to call before a batch, and the one that explains a refusal.

StatusWhat it meansWhat to do
T10N_OKReady — the last run authenticated.Use it.
T10N_KOUsable, but the last run did not complete.Use it; if it keeps failing, renew the connection.
T10N_LOGIN_LOCKThe source rejected the stored credentials, or locked the account.Do not retry. Ask your customer to connect the account again: that renews this token.
T10N_SYSTEM_LOCKTemporarily suspended by the platform.Wait; if it persists, contact support.
T10N_REVOKEDRevoked. It will never run again.Delete it. Connecting the account again creates a new connection, with a new token_id.
T10N_BROKENThe stored material can no longer be used.Renew the connection.

A tokenized execution against a locked token answers 423 rather than starting, so a batch fails fast instead of hammering an institution with credentials it has already rejected.

A locked token means a person has to act — retrying makes it worse. Institutions count failed logins, and enough of them locks the account for your customer, not just for you.


Revoking

Revoke a token revokes it immediately and marks the stored credentials 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.

Revoking does not touch executions already run with that token, nor the records they produced: those are removed with Delete an execution.

Your customer’s right to be forgotten is two calls, not a support ticket. Revoke the token, delete the executions. Both are immediate and neither needs us.


locking_hash, and recognising a returning login

Every execution that gets as far as authenticating publishes a locking_hash: a stable fingerprint of the fixed part of the credentials — the username, typically, or whatever the engine’s locking_fields declare. The same access always produces the same value, and the value reveals nothing.

It is what the platform uses to tell one account from another — the fourth part of a connection — without storing what the login is. You do not need to compare it yourself to recognise a returning login: the exchange already does, and answers with the token_id you have. It stays useful before any token exists — an execution’s locking_hash tells you which account it read.