---
title: "Transfer limits"
description: "Read a sender's transfer caps and what is left to send, and know when a transfer will pause."
---
If your business has a limits policy, each sender has caps in USD: per transfer, daily, weekly, monthly and annual. Gravv does not refuse a transfer over a cap. It returns the transfer as `paused`, and you handle it as described in [Paused transfers](/platform/transfers/paused-transfers). Read the caps before a large payout to know whether it will pause.

**Example.** Maria has a weekly cap of 2,500.00 USD and has sent 2,200.00 USD this week, so 300.00 USD is left. You send 1,500.00 USD. The transfer pauses with `breached_window` `weekly` and `remaining_usd` `300.00`. If `requirements` offers it, you can resume it with stronger sender verification. You can also send 300.00 USD instead, or let it expire. If it expires, Gravv refunds the fee.

## Read a customer's limits

Send [`GET /v1/customers/{customer_id}/limits`](/api-reference/limits/get-v1-customers-customer-id-limits).

```bash title="Get customer limits request"
curl --request GET \
     --url https://api.gravv.xyz/v1/customers/7c9e6679-7425-40de-944b-e07fc1f90ae7/limits \
     --header 'Api-Key: <API_KEY>'
```

```json title="Get customer limits response"
{
  "data": {
    "subject_type": "customer",
    "subject_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "tier_code": "basic",
    "tier_assignment": "kyc",
    "caps_basis": "tier",
    "mode": "enforce",
    "blocked": false,
    "usage_available": true,
    "as_of": "2026-10-13T09:15:22Z",
    "windows": {
      "per_transfer": { "cap_usd": "2000.00", "used_usd": null, "remaining_usd": null },
      "daily": { "cap_usd": null, "used_usd": "0.00", "remaining_usd": null },
      "weekly": { "cap_usd": "2500.00", "used_usd": "2200.00", "remaining_usd": "300.00" },
      "monthly": { "cap_usd": "10000.00", "used_usd": "6400.00", "remaining_usd": "3600.00" },
      "annual": { "cap_usd": "100000.00", "used_usd": "18000.00", "remaining_usd": "82000.00", "requires_approval": false }
    },
    "next_tier": null,
    "candidate_tiers": null
  },
  "error": null
}
```

How to read the response:

- The smallest `remaining_usd` is the most this sender can send now (here 300.00, weekly).
- `cap_usd` `null` means that window has no cap.
- Amounts are USD. Gravv converts a transfer in another currency to USD first, and some policies count the fee too.
- Weeks are ISO weeks, Monday to Sunday, in UTC.
- `mode` says what the policy does: `off` (no limits), `shadow` (Gravv measures usage but nothing pauses) or `enforce` (transfers over a cap pause).
- `blocked: true` means the sender cannot send at all. Their transfers return 422 `ERROR_CODE_SUBJECT_BLOCKED`.
- `next_tier` shows the caps the sender would get at the next verification level, when there is one.

A 404 `not found: no limits policy applies` means your business has no limits policy, not "unlimited by tier". A 404 `not found: subject` means the customer is not one of yours.

## Read a remitter's limits

If you send on behalf of end senders and identify them with `remitter_verification.remitter_id`, Gravv counts their usage per remitter. Read it with [`GET /v1/limits/remitters/{remitter_id}`](/api-reference/limits/get-v1-limits-remitters-remitter-id). The response has the same shape, with `subject_type` `remitter`.

```bash title="Get remitter limits request"
curl --request GET \
     --url https://api.gravv.xyz/v1/limits/remitters/rem-maria-lopez-01 \
     --header 'Api-Key: <API_KEY>'
```

## When a transfer is over a cap

The API returns the transfer as `paused`, with `pause_reason` set to the window (`per_transfer`, `daily`, `weekly`, `monthly`, `annual` or `annual_requires_approval`), plus `breached_window`, `remaining_usd`, `requirements` and `expires_at`. You can:

- Resume it with what `requirements` asks for, such as a `remitter_verification` at a higher level.
- Contact support if the requirement is `admin_review`. Only Gravv can release it.
- Let it expire. Send at most `remaining_usd` now and the rest later.

| Response | Why | Fix |
| :-- | :-- | :-- |
| 422 `transfers are not permitted for this sender` (`ERROR_CODE_SUBJECT_BLOCKED`) | The sender is blocked | Contact support. Do not retry |
| 503 `transfer limits are temporarily unavailable, please retry` (`ERROR_CODE_LIMITS_UNAVAILABLE`) | Gravv cannot check limits right now | Retry with backoff |
| 409 `client_reference has already been used for a different transfer …` (`ERROR_CODE_DUPLICATE_TRANSACTION`) | Under an enforced policy, you reused a `client_reference` with a different body | Use a new `client_reference` for each payout |
| 409 `a transfer with this client_reference is still being processed; retry shortly` (`ERROR_CODE_TRANSFER_IN_PROGRESS`, `Retry-After: 1`) | You retried while the first request was still running | Wait a second and retry |
| 400 `subject_id "x" is not a customer id` | The id is not a UUID | Send the customer id |

## Testing in sandbox

In sandbox, a new customer's policy is in `shadow` mode, so nothing pauses for a limit. `used_usd` stays `0.00`, because sandbox transfers do not count toward usage. Ask support to set a test policy if you need to test a limit pause.

Related recipe: [Stay within transfer limits and answer a pause](/recipes/bank-payouts/stay-within-transfer-limits).
