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

# Bank connections and open banking

> What a bank connection is, how it works, its statuses, transactions and analysis, and what the sandbox simulates.

A bank connection lets a customer share the transactions of one bank account with you after they agree. Sahl reads the transactions, groups them into income, housing, debt and other categories, and returns a cash-flow analysis. This is the first thing Sahl does for banks and lenders in Morocco and francophone Africa. Document reading, verification and scoring build on the same case.

<Card title="Upgrade for real bank connections" icon="building-columns" href="https://sahlfinancial.com/use-cases" horizontal>
  Real bank connections come with the Growth plan, switched on for your workspace by Sahl. Until then the sandbox simulates them. See plans and talk to Sales.
</Card>

## What is available today

* **Console, sandbox:** a signed-in member creates a simulated connection and sees fake transactions and an analysis at once. The routes are in the [Console API reference](/console-api/overview).
* **Production:** no bank data provider is wired into the API. Create, refresh, transactions and analysis answer `409` with the code `bank_connect_unavailable`.
* **Partner API with a key:** `/v1/partner/bank-connections`, with the scopes `bank:read` and `bank:write`. Growth plan, switched on per workspace by Sahl. Until Sahl enables your workspace, a call answers `403` `bank_scope_not_allowed`, and once enabled production still answers `409` as above. Same sandbox simulation as the console. To get it enabled, write to [contact@sahlfinancial.com](mailto:contact@sahlfinancial.com).

The banks Sahl lists are on the [Bank coverage](/bank-coverage) page. That page is a list of institutions, not a promise that live data is flowing.

## How a connection works

1. A member of your workspace picks a bank (`bank_code`, `bank_name`) and, if wanted, a case (`case_id`).
2. In a real connection the customer would follow a link, sign in at their own bank and choose what to share. Credentials stay with the bank. The model carries a `link_token` and an `expires_at` for that step.
3. Once the bank confirms, the connection is `connected` and carries the holder name, the last four digits of the account, the transaction count and the averages.
4. You read the transactions and the analysis, and attach the result to a case.

In the sandbox simulation there is no link to follow: the connection is `connected` as soon as it is created, and the figures are generated from its id. They are the same every time for the same connection.

## Statuses

| Status | Meaning |
| - | - |
| `link_created`, `link_sent` | The customer has not finished. Counted as pending in the stats. |
| `connected` | Data is available. Only a connected account can be refreshed (otherwise `400`). |
| `expired` | The link or the consent ran out. |
| `failed` | The connection did not complete. |

`GET /v1/bank-connections/stats` counts them: total, connected, pending, expired, failed. The list takes a `status` filter.

## Transactions and analysis

The transactions list returns each movement with its category, plus the total, the account holder and the bank name. The analysis returns:

| Field | What it holds |
| - | - |
| `income_regularity` | Score, pattern, employer, day of the month, consecutive months and a low, medium or high risk. |
| `risk_flags` | Overdrafts, bounced cheques, gambling transactions, large cash withdrawals, debt payments detected, and the flagged items. |
| `savings_rate`, `estimated_dti` | Savings rate and estimated debt-to-income ratio. |
| `avg_balance`, `avg_end_of_month_balance` | Average balances. |
| `monthly_income`, `monthly_expenses` | Monthly averages. |

In the sandbox these values are invented. Do not read them as a real customer.

## The production rule

The simulation runs only when the request says it is a sandbox request, with the header `X-Sahl-Environment: sandbox` or `environment=sandbox`, and the server has simulation on. Anything else is refused:

```json theme={null}
{ "detail": { "code": "bank_connect_unavailable", "message": "Bank connection is not available yet. No bank data provider is live for this workspace." } }
```

Listing, stats and reading one connection never return `409`.

## Partner API (API key)

Workspaces on the Growth plan that Sahl has enabled can call the same operations with an API key: `POST /v1/partner/bank-connections` (`bank:write`), `GET /v1/partner/bank-connections`, `/stats`, `/{connection_id}`, `/{connection_id}/transactions` and `/{connection_id}/analysis` (`bank:read`), and `POST /v1/partner/bank-connections/{connection_id}/refresh` (`bank:write`). They return the same objects as the console routes, for your workspace only. The production rule above applies unchanged: no live bank data provider, so `409` `bank_connect_unavailable` in production. See the [Partner API reference](/api-reference/introduction).

## Next

* [Bank coverage](/bank-coverage)
* [Bank connection routes: console and partner API](/guides/bank-connections)
* [Console API reference](/console-api/overview)
* [Read documents](/guides/ocr-documents), when the bank is not connectable and you have statements


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.