Request limits
Parcl applies both an API rate limit and an on-chain request budget. A trading client must handle both.
API rate limit
The APIs use token buckets. The sustained rate is how quickly tokens return; the burst is the most unused capacity the bucket can hold.
| API and request class | Scope | Sustained rate | Burst |
|---|---|---|---|
| REST API, API key or app session | Per user | 100 requests/second | 200 requests |
| REST API, public endpoint | Per client IP | 50 requests/second | 300 requests |
| REST API, sign-in or session write | Per client IP | 20 requests/second | 200 requests |
Validator API, GET | Per client IP | 1,000 requests/second | 2,000 requests |
Validator API, POST | Per client IP | 500 requests/second | 1,000 requests |
Authenticated REST requests also use the applicable client-IP bucket. When a
limit is exceeded, the API returns HTTP 429 with a Retry-After header.
Route retries for one user or IP through one scheduler.
On-chain request budget
Each active margin account starts with 10,000 standard request units. It earns one more unit per $1 of trading volume:
standard_request_cap = 10,000 + floor(lifetime_volume_usd)Each chargeable user action consumes one unit. A batch consumes one unit for each action in the batch. When the standard budget is exhausted, the account can submit one standard action every 10 seconds. Valid cancels and genuine reduce-only orders remain available, but the API rate limits above still apply.
A pending account has a standard request cap of zero until it is activated.
Read current state before sending a burst. The example uses devnet. Mainnet uses https://validator.v4.parcl.co.
curl https://v4-api.dev.parcllabs.com/v1/accounts/12/rate-limit{
"accountId": 12,
"cumulativeVolume": "250000000",
"requestsUsed": "10040",
"requestsCap": "10250",
"safetyRequestsCap": "20000",
"requestsSurplus": "210",
"lastOverBudgetRequestAt": 0,
"standardBudgetExempt": false,
"standardBudgetExemptionReason": null,
"congestion": {
"active": false,
"proposalTxCapacity": 1000,
"snapshotUtcDay": 20691,
"priorDayMakerVolume": "0",
"totalPriorDayMakerVolume": "40744400000",
"pendingStandardUnits": "0",
"quota": "0",
"remaining": "0"
}
}Large counters are decimal strings. Poll this endpoint through one scheduler per account.
safetyRequestsCap is an informational threshold. It does not prevent a valid
cancel or genuine reduce-only action.
During congestion, a standard request can also consume the account's maker-share quota. Cancels and genuine reduce-only orders remain available.
Throttle responses
Transaction throttles return HTTP 429, Retry-After, and machine-readable
fields:
{
"status": "failed",
"hash": "0x...",
"events": [],
"error": "account 12 request budget exhausted; retry after 9321 ms",
"errorCode": "request_budget_exhausted",
"retryAfterMs": 9321
}errorCode | Client action |
|---|---|
request_budget_exhausted | Wait for retryAfterMs and reduce quote churn. |
congestion_quota_exhausted | Wait for retryAfterMs; cancels and reduce-only actions remain available. |
account_pending_activation | Fund the account activation amount before submitting user actions. |
known_signer_not_ready | Wait for retryAfterMs, then refresh account state. |
mempool_admission_throttled | Wait for retryAfterMs, then refresh the rate-limit endpoint. |
Treat an unknown error code as retriable when the HTTP status is 429. Honor
both Retry-After and retryAfterMs.