Errors & Rate Limits
HTTP status codes the Agoralia API returns, the error body shape, per-plan rate limits and 429 handling, and how idempotency works.
Errors & Rate Limits
This page covers how the REST API signals failures and throttling. For the endpoint list see API Endpoints; for what each scope unlocks see Scopes.
HTTP status codes
| Status | Meaning | When it happens |
|---|---|---|
400 | Bad request | Invalid input — e.g. malformed phone number, no fields to update, unsupported provider, invalid campaign settings. |
401 | Unauthorized | Missing/malformed X-API-Key (must start with ag_), unknown key, or expired key. |
403 | Forbidden | The key is valid but lacks the required scope (Missing scope: <scope>), or the destination number is on the DNC list when placing a call. |
404 | Not found | The resource doesn't exist or isn't in your workspace (agents, campaigns, leads, calls, numbers, DNC entries). |
409 | Conflict | State conflict — e.g. modifying a non-draft/paused campaign, deleting a running campaign, linking an already-linked number, or reusing an Idempotency-Key with a different body. |
422 | Unprocessable entity | Request understood but not actionable — e.g. publishing an inactive agent, placing a call with an unpublished agent, or campaign_not_ready on launch (see below). |
429 | Too many requests | Per-plan rate limit exceeded (per minute or per day). |
502 | Bad gateway | The downstream voice provider failed (e.g. could not publish the agent or place the call). Retry. |
The API never returns a 500 for normal operation; provider failures surface as 502.
Error body shape
Errors return a JSON object with a detail field (FastAPI convention):
{ "detail": "Agent not found" }detail can also be a structured object. The campaign launch pre-flight returns the
fields an automated caller needs to self-correct:
{
"detail": {
"error": "campaign_not_ready",
"message": "Campaign is not ready to launch. Resolve the missing requirements, then retry.",
"missing": [
{ "requirement": "contacts", "message": "...", "action": "..." }
],
"suggestions": ["..."]
}
}Rate limits
The API is available on every plan. Abuse is bounded by per-workspace rate limits that scale with the billing plan, rather than a hard plan gate. Limits apply per minute and per day.
| Plan | Per minute | Per day |
|---|---|---|
| Free / unknown | 30 | 1,000 |
| Starter | 60 | 5,000 |
| Professional | 120 | 20,000 |
| Business | 300 | 100,000 |
| Enterprise | 600 | 500,000 |
When a limit is exceeded the API returns 429 with a detail message:
{ "detail": "API rate limit exceeded (per minute). Slow down and retry shortly." }{ "detail": "API daily rate limit exceeded. Upgrade your plan or retry tomorrow." }Back off and retry. The per-minute window resets within 60 seconds; the per-day window resets every 24 hours.
Idempotency
Write endpoints that create or place something accept an Idempotency-Key header:
POST /agents, POST /campaigns, POST /campaigns/{id}/leads, POST /calls,
POST /phone-numbers/link, and POST /sms.
curl -X POST https://api.agoralia.app/api/v1/agents \
-H "X-API-Key: ag_your_key_here" \
-H "Idempotency-Key: 4f9c-create-sales-agent" \
-H "Content-Type: application/json" \
-d '{ "name": "Sales", "system_prompt": "You are a sales agent." }'- Reuse the same key with the same body to get the same stored response back — the operation runs only once. Safe to retry after a network failure.
- Reuse the same key with a different body and the API returns
409 Idempotency key reused with different request body.
Generate a unique key per logical operation (a UUID works well).