Errors and limits
The one error shape, every error code, the request id, request limits per plan, limits on searches and counts, daily limits, pages and safe retries.
One error shape
Every error answer looks the same. Read error.code to decide what to do and show error.message to people. The message is one plain sentence.
{
"error": {
"code": "insufficient_credits",
"message": "Revealing these people costs 1 credit each and the account has none left. Buy credits or upgrade.",
"details": { "needed": 25, "balance": 0 }
},
"request_id": "req_8f2c1d9e0b7a4c3e9f1a2b3c4d5e6f70",
"detail": "..."
}detail holds the older form of the error for clients written before this shape. New code should read error.
Error codes
| Code | Status | What it means and what to do |
|---|---|---|
invalid_request | 400 | The request is missing something or a value is wrong. The message says what to fix. |
launch_blocked | 400 | The campaign cannot launch yet. details.blockers lists what is missing. |
unauthorized | 401 | No API key, or the key is wrong or revoked. |
api_key_required | 401 | This route needs an API key or a connector sign-in, not a browser session. |
plan_required | 402 | The account's plan does not include this. The message names the plan that does. |
insufficient_credits | 402 | Not enough credits for this call. details says how many are needed. Nothing was charged. |
scope_missing | 403 | The key lacks a scope this call needs. Create a key with that scope. |
permission_missing | 403 | Your role in the workspace does not allow this action. |
forbidden | 403 | This action is not allowed for this account. |
not_found | 404 | No such item in your workspace. Items of other workspaces answer the same way. |
route_not_found | 404 | No such endpoint. Check the path against the reference. |
method_not_allowed | 405 | The path exists but not with this HTTP method. details.allowed lists the methods. |
conflict | 409 | The item is in a state that does not allow this, for example deleting a running campaign. |
idempotency_conflict | 409 | This Idempotency-Key was already used with a different body. |
idempotency_in_progress | 409 | A request with this Idempotency-Key is still running. Wait and retry. |
gone | 410 | The item expired, for example an export file older than its keep time. |
quote_expired | 410 | The quote is too old. Get a new quote and confirm again. |
validation_error | 422 | A field has the wrong type or is missing. details.fields lists each problem. |
access_key_activation_required | 428 | This invited access key is not active yet. Confirm the email in details.claim_url first. |
rate_limited | 429 | Too many requests this minute. Wait Retry-After seconds. |
daily_limit_reached | 429 | The key's daily limit for this kind of call is used up. It resets at midnight UTC. |
internal_error | 500 | Something failed on our side. Retry; quote the request id if it keeps failing. |
unavailable | 503 | A part of the service is busy or paused. Retry in a minute. |
confirmation_required | 400 | A purchase or an order needs confirmed=true, sent only after the person who pays said yes. |
invalid_webhook_url | 400 | The webhook address must be a public https:// address. |
phones_not_in_plan | 402 | Phone numbers come with the Pro plan. Nothing was charged. |
card_not_charged | 402 | The saved card was not charged. Nothing was bought; pay through a payment link instead. |
owner_only | 403 | Only the workspace owner can do this, for example order or cancel mailboxes. |
quote_not_found | 404 | The quote does not exist or belongs to someone else. Get a new quote. |
charge_in_progress | 409 | This quote is being charged right now. Check the purchase in a moment. |
not_enough_names | 409 | Not enough free domain names were found. Send some domains yourself. |
not_paid | 409 | The order is not paid yet, so there is nothing to cancel. |
reason_required | 422 | Cancelling mailboxes needs a reason from the listed choices. |
not_connected | 409 | That tool is not connected yet. Connect it in Settings, Connected tools first. |
unsupported_tool | 409 | This connected tool cannot receive people directly. Send it an export from the Exports page instead. |
tool_key_rejected | 409 | The connected tool did not accept the saved key. Connect it again in Settings, Connected tools. |
price_mismatch | 409 | The price you showed the person is not the quoted price. Show the quoted price and ask again. |
quote_other_session | 409 | The quote was made with another key or connection. Ask for a new quote here and confirm again. |
export_failed | 409 | The export did not finish, so there is nothing to send. Run the export again. |
sign_in_failed | 422 | The mail server did not accept the sign-in, so the mailbox was not connected. details.test says for sending and for reading replies what went wrong. |
Some operations add a code of their own, such as confirmation_required or quote_not_found. Each operation lists its codes in the reference. Treat a code you do not know by its HTTP status.
The request id
Every answer carries an X-Request-Id header, and every error repeats it as request_id. Send your own id in the X-Request-Id header (8 to 64 letters, digits, dots, dashes or underscores) to find a call in your own logs. Quote the id when you ask for help.
Requests per minute
Each key may send this many requests a minute, and up to the second number in any 10 seconds.
| Plan | Requests a minute | In 10 seconds |
|---|---|---|
| 7-day trial or pay as you go, API key or CLI | 30 | 15 |
| 7-day trial or pay as you go, AI assistant | 60 | 20 |
| Starter | 60 | 15 |
| Pro | 240 | 60 |
| Scale | 600 | 150 |
| Hyperscale | 1,200 | 300 |
Every answer to a key call carries X-RateLimit-Limit (requests a minute), X-RateLimit-Remaining (requests left this minute) and X-RateLimit-Reset (seconds until the minute starts again). Above either limit you get 429 rate_limited with a Retry-After header. Wait that many seconds, then try again.
Searches and counts
Searches, counts and previews are free. They are limited per account, across all its keys and the connector, so a second key does not add more.
| Plan | A minute | Counts a day | Preview rows a day |
|---|---|---|---|
| 7-day trial or pay as you go, API key or CLI | 10 | 500 | 500 |
| 7-day trial or pay as you go, AI assistant | 20 | 1,000 | 1,000 |
| Starter | 30 | no limit | no limit |
| Pro | 60 | no limit | no limit |
| Scale | 90 | no limit | no limit |
| Hyperscale | 120 | no limit | no limit |
During the trial, searches and counts also carry X-RateLimit-Daily-Limit and X-RateLimit-Daily-Remaining. A preview holds up to 10 people a call.
Daily limits per key
During the trial and on pay as you go each key also has daily limits. On a plan only the email finder has one; credits bound the rest. Daily limits reset at midnight UTC. GET /api/v1/account shows what is left today.
| What | Per day | Per call |
|---|---|---|
| Revealed people | 100 (no limit on a plan) | 25 |
| Export rows | 50,000 (no limit on a plan) | 50,000 per file, 500,000 per batch |
| Email finder lookups | 2,000 | 30 a minute, lists up to 10,000 rows |
Above a daily limit you get 429 daily_limit_reached. For more people than the daily reveal limit, save a list, export it or add it to a campaign; those paths are made for thousands of people.
Pages
Every list takes limit and cursor. The answer keeps its own key (for example campaigns or people) and adds total, limit, offset, next_cursor and has_more. Pass next_cursor as cursor to get the next page; it is null on the last page. offset works too, if you prefer counting rows yourself.
curl "https://app.argorant.com/api/v1/campaigns?limit=25" -H "Authorization: Bearer $ARGORANT_API_KEY"
curl "https://app.argorant.com/api/v1/campaigns?limit=25&cursor=bzoyNQ" -H "Authorization: Bearer $ARGORANT_API_KEY"When total_is_estimate is true, total is the least there is, for example when a list reached its largest size.
Safe retries
Send an Idempotency-Key header with any write: creating, changing, deleting, answering, forwarding and anything that spends credits or money. Use a new random value for each new action and the same value when you retry it.
- The same key and the same body within 24 hours return the first answer, with the header
Idempotent-Replayed: true. Nothing is done twice. - The same key with a different body answers
409 idempotency_conflict. - While the first request is still running, a retry answers
409 idempotency_in_progress. Wait a moment and try again. - Errors are not stored, so you can fix the problem and retry with the same key.
curl -X POST "https://app.argorant.com/api/v1/exports" \
-H "Authorization: Bearer $ARGORANT_API_KEY" \
-H "Idempotency-Key: export-cfo-germany-2026-10-07" \
-H "Content-Type: application/json" \
-d '{"filters":{"title":"CFO","country":"Germany"},"limit":500}'Campaigns that cannot launch
POST /api/v1/campaigns/{id}/launch answers launch_blocked while something is missing, for example an email, a mailbox with room left today, or people. details.blockers lists each one in plain words. GET /api/v1/campaigns/{id} shows the same list as launch_blockers, so you can fix them before you try.