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

# Bank Connections: Inbound Feed API

> Push customer-built bank feeds into DualEntry with the V2 bank-connections API: register accounts, batch-push transactions, and unregister feeds.

Use the Bank Connections inbound API when your systems already talk to the bank and you want DualEntry to receive that feed over `/public/v2/bank-connections/` instead of connecting through a third-party aggregator such as Plaid, Meld, or Salt Edge. After you register a connection and push transactions, the feed appears on the [Bank Connections](/accountants/core-financials/cash-management/bank-connections) screen, where an accountant maps each account to a general ledger (GL) account and reconciles the transactions in [Bank Match](/accountants/core-financials/close-management/bank-match-ai), DualEntry's bank reconciliation workspace.

## What this API is

This path is a **customer-built inbound** bank feed. You **register** a connection and accounts, **push** transactions in batches while the registration is active, and **unregister** when you want DualEntry to stop accepting posts for that connection.

DualEntry does not hold an OAuth session with the bank for this source type. There is no Reconnect flow: if the feed stops, fix your push job and resume posting. On first successful registration, the connection appears on the Bank Connections screen with a generic logo and the `institution_name` you sent, so an accountant can map each of its accounts to a GL account.

## Register a connection and accounts

Create or upsert a customer API bank connection. Optionally include accounts in the same request. Stable customer keys are `connection_source_id` and each account's `account_id`.

```bash theme={null}
curl -X POST https://api.dualentry.com/public/v2/bank-connections/ \
  -H "X-API-KEY: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "connection_source_id": "pub-reg-1",
    "institution_name": "Public API Bank",
    "accounts": [
      {
        "account_id": "acct-pub-1",
        "account_name": "Checking"
      }
    ]
  }'
```

A successful response returns DualEntry `id` values for the connection and accounts. Keep the DualEntry account `id` for the push URL path; keep your `account_id` string for each transaction body.

## Register more accounts

Add or upsert accounts on an existing connection using the DualEntry connection id from registration.

```bash theme={null}
curl -X POST https://api.dualentry.com/public/v2/bank-connections/123/accounts/ \
  -H "X-API-KEY: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "accounts": [
      {
        "account_id": "acct-pub-2",
        "account_name": "Operating"
      }
    ]
  }'
```

## Push transactions

Batch upsert bank-feed rows for one DualEntry financial account. Path parameter is DualEntry's financial account id. Each item must include your customer `account_id` from registration and a unique `external_trx_id`.

```bash theme={null}
curl -X POST https://api.dualentry.com/public/v2/bank-connections/accounts/456/transactions/ \
  -H "X-API-KEY: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "transactions": [
      {
        "external_trx_id": "tx-pub-1",
        "account_id": "acct-pub-1",
        "date": "2026-03-15T12:00:00+00:00",
        "amount": "12.34",
        "description": "Lunch",
        "is_posted": true,
        "counterparty": "Cafe"
      }
    ]
  }'
```

Each item in the `transactions` array accepts these fields:

| Field             | Required | Notes                                                                  |
| ----------------- | -------- | ---------------------------------------------------------------------- |
| `external_trx_id` | Yes      | Idempotency key; stored as `source_id` with `source_type=customer_api` |
| `account_id`      | Yes      | Customer account key from registration; must match the path account    |
| `date`            | Yes      | Pending/transaction date; used when `posted_at` is null                |
| `amount`          | Yes      | Signed decimal; see amount sign below                                  |
| `description`     | Yes      | Empty string allowed                                                   |
| `is_posted`       | Yes      | `true` posted, `false` pending                                         |
| `posted_at`       | No       | Posting date when known                                                |
| `counterparty`    | No       | Payee/merchant; DualEntry maps this into Bank Match payee display      |

## Handle partial batch success

One bad item does not roll back the rest of the batch. The response lists a per-item `status` of `created`, `updated`, or `error`.

```json theme={null}
{
  "success": true,
  "results": [
    {
      "external_trx_id": "ok-1",
      "status": "created",
      "id": 1001,
      "error": null
    },
    {
      "external_trx_id": "",
      "status": "error",
      "id": null,
      "error": {
        "external_trx_id": ["This field may not be blank."]
      }
    },
    {
      "external_trx_id": "ok-2",
      "status": "created",
      "id": 1002,
      "error": null
    }
  ]
}
```

Retry only the failed `external_trx_id` values. Replaying a successful id with the same payload upserts (idempotent update).

## Unregister a connection

Soft-disable a registration so further pushes and account registration are rejected. History is kept. Re-registering with the same `connection_source_id` is supported in the current release.

```bash theme={null}
curl -X DELETE https://api.dualentry.com/public/v2/bank-connections/123/ \
  -H "X-API-KEY: your_api_key_here"
```

There is no Reconnect for `customer_api` feeds. If you stop pushing, DualEntry does not pull from the bank; resume by fixing your integration and posting again (or re-enable the same registration id after unregister).

## Rules and limits

Apply these contract rules when building your integration:

* **Idempotency** - Unique per organization on `external_trx_id` with `source_type=customer_api`.
* **Amount sign** - Positive = debit (money in); negative = credit (money out). Same convention as other DualEntry public bank APIs.
* **Batch size** - At most **250** transactions per push request.
* **Registrations** - Soft limit of **25** active customer API connections per organization (re-enabling an existing `connection_source_id` does not consume a new slot).
* **Start-date exclusion** - Treated like a provider feed: rows dated before the bank-match start date on the mapped GL account (the earliest date DualEntry imports feed activity for that account) are auto-excluded.
* **Backfill** - Historical loads are allowed; chunk them under the batch cap.
* **Limits are tunable** - Batch and registration caps are initial defaults and may change.

## API reference

This guide documents the bank-connections request and response shapes. Browse other V2 resources in the [V2 API reference](/developers/api/resources-v2/invoices/list-invoicev2-records).
