Limits, budgets, and usage
Distinguish request rate, monthly quota, hard budget, credits, and Usage API counters.
Five controls can affect whether work starts:
| Control | Purpose | Failure and recovery |
|---|---|---|
| Request rate | Limits request pace for a project key. | rate_limit_exceeded; retry after Retry-After. |
| Usage quota | Limits metered requests, tokens, or cost at organization, project, API-key, and optional capability scope for a UTC calendar month. | quota_exceeded; use error.details.resets_at, wait for reset, or ask an administrator to change the quota. |
| Hard cost budget | Stops new capability work after an organization or project monthly cost ceiling is reached. | budget_exceeded; use error.details, wait for reset, or ask an administrator to change the budget. |
| Usage-tier cost cap | Stops new capability work at the organization's tier-based monthly spend ceiling. | budget_exceeded with error.details.scope: usage_tier; wait for reset or a tier change. |
| Prepaid credits | Requires a positive spendable balance when billing is enabled; no future job price is estimated or reserved. | insufficient_credits; add credits or let auto-recharge complete. |
Only the rate-limit case is a transient automatic retry. See Errors.
All quota and budget periods begin at 00:00:00 UTC on the first day of a calendar month and reset at the next month's boundary. An error's structured details reports the applicable scope, limit, current value, remaining value, and resets_at. Do not automatically retry either code merely because its HTTP status is 429: an administrator may change a control before reset, but only rate_limit_exceeded is transient by itself.
What each counter records#
One newly accepted Playbooks job or Audience cycle adds exactly 1 to Usage requests. Idempotent replay returns the original job without adding another request. Rejected job creation, campaign setup, reads, polling, candidate retrieval, and Usage calls add 0 to this monthly counter. They can still consume the API-key request-rate window.
When a job finishes, its capability execution adds attributed tokens and downstream cost_usd; it does not add a second request. A request quota checks whether the next new job would exceed its limit. Token and cost quotas stop new jobs once recorded usage has reached the limit. Work already accepted continues even if a later completion crosses a token, cost, or budget threshold.
Budgets use the append-only downstream cost ledger, independently of Usage quotas. A soft budget records alerts but does not reject work. A hard budget rejects new work at or above its monthly ceiling. Prepaid billing is separate: any positive spendable balance permits work to start, with no admission estimate or price reserve. At completion, actual downstream cost with the organization's billing markup is charged. If that actual price exceeds the remaining balance, the balance is consumed and the job fails without exposing its result; auto-recharge is then triggered. credits.balance_usd is the current ledger balance, not a monthly counter.
Usage records are append-only. The public Usage API returns the authenticated project's current monthly rollup and capability breakdown:
curl --fail-with-body --silent --show-error \
"$BLACKPEARL_API_BASE_URL/v1/usage" \
--header "Authorization: Bearer $BLACKPEARL_API_KEY" | jq .{
"project_id": "proj_example",
"period": "2026-07",
"period_start": "2026-07-01T00:00:00Z",
"period_end": "2026-08-01T00:00:00Z",
"rollup": {
"requests": 12,
"tokens": 45200,
"cost_usd": 1.243
},
"by_capability": [
{
"capability_key": "playbooks",
"requests": 12,
"tokens": 45200,
"cost_usd": 1.243
}
],
"usage_tier": {
"key": "growth",
"name": "Growth",
"rank": 2,
"rate_limit_per_minute": 120,
"monthly_cost_cap_usd": 250.0
},
"rate_limit": {
"limit": 120,
"window_seconds": 60
},
"quotas": [
{
"metric": "requests",
"period": "month",
"scope": "project",
"capability_key": "playbooks",
"limit_value": 1000,
"used": 12,
"remaining": 988,
"resets_at": "2026-08-01T00:00:00Z"
}
],
"budgets": [
{
"period": "month",
"scope": "project",
"capability_key": null,
"limit_usd": 50,
"spend_usd": 1.243,
"remaining_usd": 48.757,
"hard_limit": true,
"resets_at": "2026-08-01T00:00:00Z"
}
],
"credits": {
"billing_enabled": true,
"balance_usd": 98.757,
"topup_increment_usd": 25.0
}
}period_start is inclusive and period_end is exclusive. rollup totals the project, while by_capability reconciles those counters by capability key. usage_tier is nullable and reports the organization's resolved rate and monthly cost cap when tiering applies. quotas includes every organization, project, or API-key quota that can affect this key; budgets includes every organization or project budget that can affect this project. Empty arrays mean no matching control is configured. Compare a completed job's usage with these rollups while allowing for other jobs in the same period.
Usage retrieval is OpenAPI operation usage_v1_usage_get with schema PublicUsageResponse.