Check what a sender can still send
Read a sender's caps and what is left in each window before a big payout, so a transfer does not pause on payday.
This recipe reads a sender's caps and how much is left in each limit window, so you can check a large payout before you send it. It is for an operations analyst at a US remittance app that verifies its own senders (remitters) and wants no transfers paused on payday.
Status. Available when your business has a limits policy.
Money example
Maria wants to send 1,500 USD today.
- Her limits are 1,000 USD per transfer and 3,000 USD a day, with 0 used today.
- 1,500 USD is over the per-transfer cap, so Gravv would create the transfer
pausedinstead of refusing it. - A higher verification tier lifts the cap. If you verify her to that tier first and then send, the transfer does not pause.
Before you start
- Your business has a limits policy. Without one, both reads return 404 and no Gravv limits apply.
- The sender's id. For your customers, this is the customer id. For senders you verify yourself, it is the
remitter_idyou send inadditional_information.remitter_verification.
Find out what is required
The limits response tells you how Gravv checks the sender and how much they can still send. Read these fields:
| Field | Meaning |
|---|---|
mode |
enforce: a breach pauses the transfer. shadow: Gravv only records a breach. off: no checks |
blocked |
true: Gravv refuses every transfer with 422 ERROR_CODE_SUBJECT_BLOCKED |
windows.<window>.cap_usd, used_usd, remaining_usd |
USD strings for per_transfer, daily, weekly, monthly and annual (the last 12 months) |
cap_usd null |
No cap in that window, but only when caps_basis is tier |
usage_available false |
Gravv could not read usage, so used_usd and remaining_usd are null |
next_tier, candidate_tiers |
The caps a higher tier allows |
Steps
1. Read a remitter's limits
curl --request GET \
--url https://api.gravv.xyz/v1/limits/remitters/rem-20431 \
--header 'Api-Key: <API_KEY>'
const response = await fetch("https://api.gravv.xyz/v1/limits/remitters/rem-20431", {
method: "GET",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
},
});
console.log(response.status, await response.json());
import os
import requests
response = requests.get(
"https://api.gravv.xyz/v1/limits/remitters/rem-20431",
headers={
"Api-Key": os.environ["GRAVV_API_KEY"],
},
)
print(response.status_code, response.json())
{
"data": {
"subject_type": "remitter",
"subject_id": "rem-20431",
"tier_code": "",
"tier_assignment": "per_transfer_attestation",
"caps_basis": "floor",
"mode": "enforce",
"blocked": false,
"usage_available": true,
"as_of": "2026-10-13T09:15:22Z",
"windows": {
"per_transfer": { "cap_usd": "1000.00", "used_usd": null, "remaining_usd": null },
"daily": { "cap_usd": "3000.00", "used_usd": "0.00", "remaining_usd": "3000.00" },
"weekly": { "cap_usd": null, "used_usd": "0.00", "remaining_usd": null },
"monthly": { "cap_usd": "10000.00", "used_usd": "0.00", "remaining_usd": "10000.00" },
"annual": { "cap_usd": "0.00", "used_usd": "0.00", "remaining_usd": "0.00", "requires_approval": true }
},
"next_tier": null,
"candidate_tiers": [
{
"tier_code": "STARTER",
"rank": 0,
"tier_caps": { "per_transfer": "1000", "daily": "3000", "weekly": null, "monthly": "10000", "annual": null, "annual_requires_approval": true },
"caps": { "per_transfer": "1000", "daily": "3000", "weekly": null, "monthly": "10000", "annual": null, "annual_requires_approval": true }
}
]
},
"error": null
}
1,500 is more than the per_transfer cap of 1,000, so the transfer would pause with pause_reason per_transfer. Tier codes such as STARTER come from your business's limits policy. Read them from this response and never hard-code them. Gravv accepts any string as a remitter id. For an id it has never seen, Gravv uses the policy's default tier.
2. Read a customer's limits
The response has the same shape as in step 1, with subject_type set to customer.
curl --request GET \
--url https://api.gravv.xyz/v1/customers/5be6128e-18c2-4797-a142-ea7d17be3111/limits \
--header 'Api-Key: <API_KEY>'
const response = await fetch("https://api.gravv.xyz/v1/customers/5be6128e-18c2-4797-a142-ea7d17be3111/limits", {
method: "GET",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
},
});
console.log(response.status, await response.json());
import os
import requests
response = requests.get(
"https://api.gravv.xyz/v1/customers/5be6128e-18c2-4797-a142-ea7d17be3111/limits",
headers={
"Api-Key": os.environ["GRAVV_API_KEY"],
},
)
print(response.status_code, response.json())
3. Compare before you send
Convert the planned amount to USD and compare it with the smallest remaining_usd and with the per_transfer cap. If a transfer would pause, plan to verify that sender first. Do not split a payment to get under a cap.
If a transfer has already paused, Stay within transfer limits shows how to respond to it.
What can go wrong
| Response | Why | Fix |
|---|---|---|
404 not found: no limits policy applies |
Your business has no limits policy | No Gravv limits apply, so there is nothing to check |
404 not found: subject |
The customer id is not in your business | Fix the id |
400 subject_id "x" is not a customer id |
The id on the customer route is not a UUID | Use the customer's UUID |
404 with the plain-text body 404 page not found |
An empty id, as in /v1/limits/remitters/ |
Add the id |
503 ERROR_CODE_LIMITS_UNAVAILABLE |
Gravv cannot read limits right now | Retry, and wait longer before each new attempt |
| A remitter shows no usage although they sent today | Usage counts only transfers that carried remitter_verification with exactly this remitter_id (case matters) |
Send the same id every time |
An annual cap of "0.00" with requires_approval true |
An annual allowance needs Gravv's approval | Transfers past it pause for review |
Webhooks you will receive
Reading limits sends no webhook. If a transfer later breaches a cap, Gravv sends transfer.requires_information. Its limit_details object holds breached_window, cap_usd, used_usd, remaining_usd and requirements.
Testing in sandbox
Your sandbox business needs a sandbox limits policy, and Gravv sets it up. If the sandbox policy is in shadow mode, both reads return 200, but Gravv only records a breach and never pauses the transfer. To see a pause, ask support to put the policy in enforce mode.