> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sumvin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bank linking

> Link a user's bank account through the ramp widget — institution discovery, link initiation, account population, and processor token issuance.

<Snippet file="product-term-disambiguation.mdx" />

Bank linking lets a user connect a bank account to their Sumvin profile through the ramp widget. The link result populates the user's accounts, makes balance and transaction data available, and supports issuing processor tokens for downstream payment use. It is part of **Atomic Money** — Sumvin's payments, ramps, cards, and settlement surface.

<Note>
  Bank linking is in **private preview**.
</Note>

## Why this exists

Sumvin's account model treats a linked bank account as a first-class resource — it can serve as a fiat settlement destination for off-ramp (off-ramp is in private preview), as a balance source for budgets and insights, and as the funding origin for ACH-style payment flows that consume a processor token. Routing those flows through one ramp that Sumvin operates means the partner integrates against `/v0/accounts/*` and `/v0/bank-linking/*` rather than against an external provider directly.

## Provider routing

The bank-linking entitlement on the user gates the `/v0/bank-linking/*` endpoints — institution discovery, processor token issuance, and the connection-lifecycle operations. Without it, those calls return `403 Forbidden` with error code `GATE-403-001`. The `/v0/accounts/link/config` and `/v0/accounts/link` entry points are not entitlement-gated.

```http theme={null}
GET /v0/accounts/link/config
```

Always call this first. The response tells you the link-flow configuration before you initiate.

```json theme={null}
{
  "provider": "meld",
  "requires_institution_selection": true,
  "_links": { ... }
}
```

The ramp flow requires institution selection — your UI must let the user pick from the institution catalog before initiating the link.

## End-to-end flow

<Steps>
  <Step title="Discover institutions">
    Fetch the catalog — filter by region, supported products, or name search. The catalog is cached server-side; it is safe to call on every render of your bank-picker UI.

    [`GET /v0/bank-linking/institutions`](/api-reference/bank-linking/get-institutions)
  </Step>

  <Step title="Initiate the link">
    Pass the chosen `institution_id`. Sumvin returns `202 Accepted` with a `widget_url` and `connect_token`. Embed the widget URL in your client to surface the hosted institution-connect flow to the user.

    [`POST /v0/accounts/link`](/api-reference/accounts/initiate-link)
  </Step>

  <Step title="User completes the connect flow">
    The user authenticates with their bank inside the ramp widget. On success, Sumvin receives a `BANK_LINKING_CONNECTION_COMPLETED` event on its webhook endpoint. This event is informational — account data lands in the next step.
  </Step>

  <Step title="Account data arrives">
    A `BANK_LINKING_ACCOUNTS_UPDATED` event arrives with the populated account list. Sumvin upserts each account against the user, mapping the provider's account types into Sumvin's `account_type` taxonomy. The accounts then surface on the list endpoint.

    [`GET /v0/accounts/`](/api-reference/accounts/list-accounts)
  </Step>

  <Step title="Transactions become available (optional)">
    For institutions and products that support it, a `BANK_LINKING_TRANSACTIONS_AGGREGATED` event (and `..._HISTORICAL_...` for backfill) arrives. Sumvin triggers a background sync to pull and persist transactions against each account.
  </Step>

  <Step title="Issue a processor token (optional)">
    To use the linked account as a payment source for a downstream processor (for example, an ACH payment partner), pass the processor name. Sumvin mints the token and returns it.

    [`POST /v0/bank-linking/accounts/{account_id}/processor-token`](/api-reference/bank-linking/create-bank-processor-token)
  </Step>
</Steps>

## Polling for completion

Bank linking is asynchronous from the partner's perspective — the link response is `202`, not the final account state. After the user closes the widget, poll the accounts list; new accounts appear once the `BANK_LINKING_ACCOUNTS_UPDATED` event is delivered. The `poll` link in the link response points at `/v0/accounts?status=pending_connection` for that purpose.

[`POST /v0/accounts/link`](/api-reference/accounts/initiate-link) — Initiate the link (returns `202`).

[`GET /v0/accounts/`](/api-reference/accounts/list-accounts) — Poll for completion.

Partner-facing webhooks for these events are not yet available; polling is the supported pattern.

## Connection lifecycle

After the initial link, Sumvin tracks the connection's status from the `BANK_LINKING_CONNECTION_STATUS_CHANGE` webhook:

| Provider status      | Sumvin account status |
| -------------------- | --------------------- |
| `ACTIVE`             | `active`              |
| `DEGRADED`           | `active`              |
| `RECONNECT_REQUIRED` | `refresh_required`    |
| `DISCONNECTED`       | `disconnected`        |
| `ERROR`              | `error`               |

If the connection moves to `refresh_required`, the user needs to re-authenticate. Surface the user-facing prompt off the account's `status` field, then call `POST /v0/bank-linking/connections/{connection_id}/repair` to get a fresh `widget_url` and `connect_token` and re-open the connect widget against the existing connection (it returns `201 Created`). Alternatively, `POST /v0/bank-linking/connections/{connection_id}/refresh` triggers a background refresh of the connection and returns `202 Accepted`.

When the user disconnects the account, Sumvin tears down the connection upstream and soft-deletes the corresponding accounts.

[`DELETE /v0/accounts/{account_id}`](/api-reference/accounts/delete-account) — Disconnect a linked account.

## Endpoint surface

| Aspect                  | Endpoint                                                                                                                           |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Link configuration      | [`GET /v0/accounts/link/config`](/api-reference/accounts/get-link-config) — `provider=meld`, `requires_institution_selection=true` |
| Institution discovery   | [`GET /v0/bank-linking/institutions`](/api-reference/bank-linking/get-institutions)                                                |
| Initiate link           | [`POST /v0/accounts/link`](/api-reference/accounts/initiate-link) — returns `202 Accepted` with `widget_url`                       |
| Token exchange          | Implicit via webhook (`BANK_LINKING_ACCOUNTS_UPDATED`)                                                                             |
| Processor token         | [`POST /v0/bank-linking/accounts/{account_id}/processor-token`](/api-reference/bank-linking/create-bank-processor-token)           |
| List connections        | `GET /v0/bank-linking/connections`                                                                                                 |
| Get a connection        | `GET /v0/bank-linking/connections/{connection_id}`                                                                                 |
| Refresh a connection    | `POST /v0/bank-linking/connections/{connection_id}/refresh` — returns `202 Accepted`                                               |
| Repair / re-open widget | `POST /v0/bank-linking/connections/{connection_id}/repair` — returns `201 Created` with a fresh `widget_url`                       |
| Disconnect a connection | `DELETE /v0/bank-linking/connections/{connection_id}` — returns `202 Accepted`                                                     |
| Account management      | `/v0/accounts/*` — list, get, sync, delete                                                                                         |

The `/v0/bank-linking/*` namespace covers ramp-specific operations (institutions, processor tokens, and connection lifecycle). The `/v0/accounts/*` namespace covers ongoing account management.

## Related

* [Atomic Money ramps overview](/products/ramps/overview)
* [Reference](/products/ramps/reference)
* [KYC passthrough](/products/ramps/kyc-passthrough) — why the widget does not re-verify the user
