> This page is for Financial Rider Flow.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://infonite.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://infonite.dev/_mcp/server.

# Recurring Access

A Financial Rider session can be used **once** or **for good**. The difference is not a different product — it is whether the session keeps a token of the credentials your customer signed in with.

|                    | One-shot                                                                   | Recurring                                                                                                          |
| :----------------- | :------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- |
| **What happens**   | Your customer connects their banks in the widget, and you read the result. | The same first connection — and from then on, your backend reads those banks again whenever it needs to.           |
| **Who is present** | Your customer, every time.                                                 | Your customer once, at the first connection. Never again, until the access has to be renewed.                      |
| **Which API**      | [Financial Rider](/flows/financial-rider/overview).                        | Financial Rider for the first connection, then [direct executions](/direct-executions/overview) for every refresh. |
| **Turned on with** | Nothing: it is the default.                                                | `tokenized_access: true` at [Create Session](https://infonite.dev/flows/financial-rider/api-reference/financial-rider-api/sessions-management/flows-financial-rider-v-1-session-create).                            |
| **Built for**      | An onboarding, a loan application, a verification.                         | Bank reconciliation, money management, monitoring — anything that needs today's movements tomorrow.                |

---

## How it works

Two phases, on two APIs: the **onboarding** happens once, in the widget, because only your customer can type their credentials; every **refresh** after it is a server-to-server call your backend makes on its own schedule.

```mermaid
flowchart TB
  subgraph ONBOARDING["Once, with your customer — Financial Rider"]
    direction LR
    C["Create Session<br />tokenized_access: true"] -->|"a ticket"| W["Your customer connects<br />their banks in the widget"]
    W --> X["Exchange the ticket<br />once per connection"]
  end

  subgraph REFRESH["Every time, without them — direct executions"]
    direction LR
    T["Initiate with a token"] --> R["Read the results"]
    R --> A["Again, on your<br />own schedule"]
  end

  ONBOARDING -->|"a token per bank"| REFRESH
```

> **Note**
>
> **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](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-exchange), [Initiate with a token](https://infonite.dev/direct-executions/api-reference/direct-executions-api/starting-executions/direct-executions-v-1-init-tokenized), [Check a token](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-status) and [Revoke a token](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-delete). The widget and its API play no part in them: your customer is only needed in the widget, to connect or to reconnect.

#### Create the session with recurring access

[Create Session](https://infonite.dev/flows/financial-rider/api-reference/financial-rider-api/sessions-management/flows-financial-rider-v-1-session-create) with `settings.tokenized_access: true`. The answer carries a **`ticket`** — shown there and nowhere else, so store it with the session.

#### Your customer connects their banks

Exactly as in any session: consent, pick a bank, sign in. Every connection that finishes keeps a token of the credentials it signed in with — at the banks that support it.

#### Exchange the ticket, once per connection

[Get Session Results](https://infonite.dev/flows/financial-rider/api-reference/financial-rider-api/sessions-results/flows-financial-rider-v-1-session-results) lists the `connections` by id. For each one, [Exchange a ticket](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-exchange) with that id as `execution_id` and the session's `ticket`. What comes back is that bank's **`token_id` and `token_key`** — store both halves, and treat the key like a password: it is never shown again. If you already held a token for that same account and customer, it comes back renewed: [your list of connections](#your-list-of-connections) explains it.

#### Refresh from your backend, whenever you need to

[Initiate with a token](https://infonite.dev/direct-executions/api-reference/direct-executions-api/starting-executions/direct-executions-v-1-init-tokenized) runs that bank again with the stored credentials, and its results are read like any [direct execution's](/direct-executions/results) — the financial position or one family at a time. No widget, no customer: a call from your backend, as often as your process needs.

> **Note**
>
> **A token is locked to what the session asked for.** One application, one bank, one `customer_id` and the features the session read. A refresh may ask for fewer features, never for more: widening the scope means a new session — which renews the same token —, because reaching more of somebody's data should require their credentials again.

---

## Your list of connections

What you show your customer — *BBVA, connected; Santander, connected* — is a list of connections, and **`token_id` is the identifier to keep it by**. A connection is one bank account of one of your customers: the same application, the same bank, the same `customer_id` and the same account. It has one token for life.

| Your customer…                                                                                  | [Exchange a ticket](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-exchange) returns                                                      |
| :---------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------- |
| connects a bank for the first time                                                              | a new `token_id`, `renewed: false` — add it to the list                                                   |
| connects **the same account** again — to fix a lock, after a password change, before the expiry | **the same `token_id`**, a new key, `renewed: true` — replace the key you kept; the old one stops working |
| connects the same bank with a **different username**                                            | a new `token_id`: another account, so another entry                                                       |

So a customer who presses *connect* on a bank they already connected does not get a duplicate: the entry you already have is renewed. **`token_id` is the field that never changes**: a renewal revokes nothing — it keeps the token and gives it a new key —, so match on it and nothing else; there is nothing to compare yourself, not `locking_hash`, not the bank's name. [Managing your customers' connections](/guides/credential-tokenization#managing-your-customers-connections) is the practical guide: what to keep per connection, and the connect, reconnect and remove flows of your screen.

---

## What it needs

* **The `login:tokenized_access` capability**, for a production application — see [Capabilities](/console/capabilities). A sandbox session tokenizes without it.
* **A bank whose engine supports it.** Each engine says so in `tokenized_access`, on [List your engines](https://infonite.dev/direct-executions/api-reference/direct-executions-api/engines/direct-executions-v-1-engines-list) — banks typically do, as telcos and utilities do: sources worth reading again. **A session with recurring access offers only the banks that can**, so your customer never connects one you could not refresh. Filters that leave none are refused at [Create Session](https://infonite.dev/flows/financial-rider/api-reference/financial-rider-api/sessions-management/flows-financial-rider-v-1-session-create) with `400 no_engines_available_for_tokenized_access`, and a named bank that cannot with `422 engine_not_available_for_tokenized_access`.
* **Somewhere safe for the token key.** Half of the access is yours, and only yours: we keep the credentials encrypted and a verifier of your key, never the key. [Credential Tokenization](/guides/credential-tokenization) explains the design.

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.

How to request it

---

## When the access has to be renewed

A refresh runs without your customer, so anything only a person can do ends it instead of waiting:

* **A second factor.** If a bank asks for one during a refresh, nobody is there to answer it — a run started with `customer_interaction_available: false` ends instead of pausing. [Challenges & MFA](/direct-executions/challenges) describes the pause and its answers.
* **Credentials that stopped working.** A changed password, or an account the bank locked, leaves the token locked: [Check a token](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-status) says so, and retrying only makes the bank count more failures.
* **Time.** A token expires **90 days after the last exchange**, whether it was used or not.

In every case the answer is the same: **a new Financial Rider session** with `tokenized_access`, where your customer connects that bank again. Exchanging its ticket at [Exchange a ticket](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-exchange) — on the Direct Executions API — **renews the token you already have** — the same `token_id`, a new key, a new expiry — so your list of connections keeps the same entry. Plan the renewal before the expiry date rather than after the first failed refresh — [Stored credentials](/direct-executions/tokenization) has the token's lifecycle, its statuses and how to revoke it.

> **Warning**
>
> **Revoking is your customer's right, and two calls.** When they withdraw their consent or leave your service, [Revoke a token](https://infonite.dev/direct-executions/api-reference/direct-executions-api/tokenization/direct-executions-v-1-token-delete) for every bank, and delete the executions that used it. Both are immediate and neither needs us.

---

**Credential Tokenization.** How the token is built, why neither half opens the credentials alone, and what losing the key means for you.

Credential Tokenization

**Stored credentials.** The refresh side in full: the token's scope, its statuses, its expiry and how to revoke it.

Stored credentials