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

# Spend control

> Per-transaction-type velocity caps on partner cards

Spend control lets you declare velocity caps on each card without tracking the cardholder's accrued spend yourself. You set the caps; the issuer enforces them at authorization time.

Each card has two transaction-type buckets:

* `sales` — purchase (point-of-sale) transactions
* `cash` — cash withdrawal (ATM) transactions

Each bucket accepts up to six independent caps. Omit a key to leave that bucket uncapped on that horizon.

| Cap key | Meaning |
| - | - |
| `perTransaction` | Maximum amount per single transaction |
| `daily` | Maximum total amount per calendar day |
| `monthly` | Maximum total amount per calendar month |
| `allTime` | Maximum total amount over the card's lifetime |

## Set spend control

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://api.contro.me/v1/partner/cards/card_def456/limits \
    -H "x-contro-api-key: $CONTRO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "spendControl": {
        "sales": { "perTransaction": 200, "daily": 1000, "allTime": 50000 },
        "cash": { "allTime": 0 }
      }
    }'
  ```

  ```typescript SDK (Node) theme={null}
  await contro.cards.updateLimits("card_def456", {
    spendControl: {
      sales: { perTransaction: 200, daily: 1000, allTime: 50000 },
      cash: { allTime: 0 },
    },
  });
  ```
</CodeGroup>

The example above caps in-store purchases at `$200` per transaction, `$1,000` per day, and `$50,000` over the card's lifetime — and disables cash withdrawals entirely by setting an `allTime` cap of `0`.

## Read spend control

`GET /partner/cards/{id}` returns the active caps under `spendControl`. Where the card program supports it, accrued spend is reported under `spendControl.spent`:

```json theme={null}
{
  "id": "card_def456",
  "spendControl": {
    "sales": { "daily": 1000, "allTime": 50000 },
    "cash": { "allTime": 0 },
    "spent": {
      "sales": { "daily": 142.5, "allTime": 8420.10 }
    }
  }
}
```

## Common patterns

**Cash-disabled card.** Set `cash.allTime: 0` to block ATM withdrawals while leaving purchases uncapped.

```json theme={null}
{ "spendControl": { "cash": { "allTime": 0 } } }
```

**Lifetime budget card.** Cap total purchases over the card's lifetime — useful for one-shot expense cards or per-vendor budgets.

```json theme={null}
{ "spendControl": { "sales": { "allTime": 1500 } } }
```

**Daily allowance.** Cap purchases per calendar day with a per-transaction ceiling for fraud control.

```json theme={null}
{
  "spendControl": {
    "sales": { "perTransaction": 100, "daily": 200 }
  }
}
```

## Card program capabilities

Not every card program supports every cap horizon. Caps a program cannot enforce are rejected at request time with a `400` and the message `Card program "<name>" does not support <capKey> spend-control cap.` Ask your Contro admin which caps the programs assigned to your account support.

## Migrating from `{ limit }`

The legacy body `{ "limit": 5000 }` is still accepted on `PATCH /partner/cards/{id}/limits` and is mapped to:

```json theme={null}
{
  "spendControl": {
    "sales": { "allTime": 5000 },
    "cash":  { "allTime": 5000 }
  }
}
```

Send `null` to clear the cap. The legacy `limit` field will be removed in a future release — switch to `spendControl` to take advantage of per-transaction-type caps and finer-grained horizons.
