Linking Cards to Bank Accounts

Introduction

Linking a card to a connected bank account is what turns on earlier settlement for that card: when a card authorization matches a posted bank transaction on the account, the transaction flips PENDING→SETTLED on the bank's evidence — typically within hours of the swipe rather than days.

Linking cards is optional and independent of the bank connection itself. Bank-only events (fees, transfers, payroll, FX markup) fire on a connected bank account with no card link at all — see Quick Start: Bank Linking. This page is about the second step: attaching cards for earlier settlement.

📘

You may not need to call anything

Card links are detected automatically. Read on for when to link manually — pre-linking before any spend, correcting an assignment, or importing history.

Automatic detection

The first time a card's transactions produce a high-confidence match against a bank account's feed, Astrada links that card to the account — no API call required. This is the common path: connect the bank, let spend flow, and cards attach themselves to the right account as evidence appears.

Two things to know about auto-detected links:

  • They do not backfill history. Only transactions from the moment of linking forward benefit from earlier settlement. To import earlier history, link the card manually with backfill (below).
  • The current set of linked cards is always readable — see Reading the current links.

Manual linking

PATCH /bank-accounts/{id} (scope banking:write) sets the account's card set explicitly. It's the manual override for the automatic detector. Use it to:

  • Pre-link a card before any spend exists, so the very first matching transaction settles early.
  • Correct an assignment, or move a card between accounts.
  • Import history for newly linked cards, via backfill.
PATCH /bank-accounts/a1b2c3d4-e5f6-7890-abcd-ef1234567890 HTTP/1.1
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json

{
  "cardIds": [
    "5dec2c49-0aa5-4683-a317-427eb5d115f3",
    "8abc1d23-4e56-7f89-0abc-def123456789"
  ],
  "backfill": { "startDate": "2026-01-27", "endDate": "2026-04-27" }
}
curl -X PATCH https://api.astrada.co/bank-accounts/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cardIds": [
      "5dec2c49-0aa5-4683-a317-427eb5d115f3",
      "8abc1d23-4e56-7f89-0abc-def123456789"
    ],
    "backfill": { "startDate": "2026-01-27", "endDate": "2026-04-27" }
  }'
{
  "cardIds": [
    "5dec2c49-0aa5-4683-a317-427eb5d115f3",
    "8abc1d23-4e56-7f89-0abc-def123456789"
  ],
  "backfill": { "startDate": "2026-01-27", "endDate": "2026-04-27" }
}
FieldTypeRequiredDescription
cardIdsUUID[]YesThe cards to link. Full replacement — send the complete desired set, not a delta.
backfillobjectNoOpt-in historical import. Runs only for cards being added in this request.
backfill.startDateISO dateNoDefaults to 90 days ago.
backfill.endDateISO dateNoDefaults to today.

Response (200 OK):

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "cardIds": [
    "5dec2c49-0aa5-4683-a317-427eb5d115f3",
    "8abc1d23-4e56-7f89-0abc-def123456789"
  ],
  "state": "active",
  "updatedAt": "2026-04-27T15:00:00Z",
  "backfill": { "transactionsProcessed": 50, "matchesFound": 10 }
}

The backfill block appears only when a backfill was requested.

🚧

cardIds is a full replacement

The endpoint replaces the account's explicit card set with exactly what you send — it is not a delta. To add a card, send the existing cardIds plus the new one; to remove one, send the set without it. Sending cardIds: [] clears explicit links (automatic detection may re-link a card on its next high-confidence match).

Backfill history

When you add cards, pass backfill: { startDate, endDate } to import historical bank transactions for those cards (default: the last 90 days). Earlier settlement then runs against any historical card authorizations still in PENDING, and bank-only events fire retroactively for historical transactions that remain unmatched.

Backfill runs only for the cards added in that request — not cards already linked to the account.

Multi-card linking & constraints

A bank account can carry many cards (1:N); a card links to at most one bank account at a time. Each rule below returns a specific error — handle them in your linking UI:

RuleOn violation
A card links to only one bank account at a time.409 Conflict — the card is already linked to another bank account.
Every card and the bank account must share the same subaccountId.Enforced upstream by card issuance; banking trusts the cardIds you pass.

To move a card from account A to account B: first PATCH A with a cardIds set that omits the card (freeing it), then PATCH B to add it. Linking a card to B while it's still linked to A returns 409 CARD_ALREADY_LINKED.

Reading the current links

  • GET /bank-accounts/{id} (scope banking:read) — the account, including its cardIds.
  • GET /bank-accounts?cardId={cardId} — the account a given card is linked to (empty if none).
  • GET /bank-accounts?subaccountId={subaccountId} — every account for a subaccount, each with its cardIds.

Next steps