API Errors
Every failure returns the same envelope, whatever went wrong.
{
"error": {
"type": "invalid_request_error",
"code": "parameter_missing",
"message": "Missing required parameter 'name'.",
"param": "name",
"doc_url": "https://argorobots.com/documentation/api/errors#parameter_missing",
"request_id": "req_9f3ed3dc2e61733488a1db04"
}
}
Switch on type for broad handling and code for specific handling. Do not parse message. It is written for a human reading a log and its wording will change; code is the part we keep stable.
param appears whenever a single parameter is to blame. request_id also comes back as a header on every response, successful or not.
Deciding Whether to Retry
- Retry
api_errorandrate_limit_error, with backoff, reusing the sameIdempotency-Key. - Do not retry
authentication_errororinvalid_request_error. Nothing about the request will change. idempotency_key_in_flightis the one exception worth a short retry: the original is still running and the second attempt will replay its result.
authentication_error
The key is missing, wrong, or no longer valid. Always a 401. Do not retry; the same request will fail the same way.
| Code | Status | Cause | What to do |
|---|---|---|---|
missing_api_key |
401 | No key on the request. | Send Authorization: Bearer ab_... or X-Api-Key. |
invalid_api_key |
401 | The key is not one of ours, or does not exist. | Check for a truncated or whitespace-padded copy and paste. Ask the merchant for a fresh key. |
api_key_revoked |
401 | The merchant revoked this key. | Treat as permanent. Prompt your user to reconnect rather than retrying. |
invalid_request_error
Something about the request itself is wrong. The param field names the offending parameter whenever one is to blame.
| Code | Status | Cause | What to do |
|---|---|---|---|
account_inactive |
403 | The Argo Books account behind the key is not active. | The merchant needs to re-enable the API in Settings. |
insufficient_scope |
403 | The key lacks read or write for this call. |
Ask the merchant for a key with the scope you need. |
unknown_route |
404 | No such path. | Check the resource name against the list in Resources. |
resource_missing |
404 | No object with that id on this account. | Confirm the id, and that it belongs to the same merchant as the key. |
method_not_allowed |
405 | Wrong verb for a valid path. | Read the Allow header. Note updates are POST, not PUT or PATCH. |
unknown_api_version |
400 | An Argo-Version we do not recognise. |
Use the version named in the message, or omit the header. |
invalid_json |
400 | The body did not parse. | Check Content-Type matches what you actually sent. |
unknown_parameter |
400 | A field we do not accept. | Usually a typo. The param field is the name we received. |
parameter_missing |
400 | A required field was absent on create. | See the required column in Resources. |
parameter_invalid_empty |
400 | A required field was sent as null or empty. | Required fields can be changed but not cleared. |
parameter_invalid_type |
400 | Wrong JSON type. | Check the type column in Resources. |
parameter_invalid_value |
400 | Right type, unacceptable value. Includes tax_amount exceeding amount. |
The message states the rule. |
parameter_invalid_amount |
400 | A money field was not an integer. | Send minor units. 1999, not 19.99. We reject rather than round. |
parameter_invalid_currency |
400 | Not a three-letter code. | Use ISO 4217. Case does not matter. |
parameter_invalid_country |
400 | Not a two-letter code. | Use ISO 3166-1 alpha-2. |
parameter_invalid_date |
400 | Not a real YYYY-MM-DD date. |
No timestamps, no locale formats. This also catches dates like 2026-02-30. |
parameter_invalid_email |
400 | Not a valid address. | Send null rather than a placeholder if you do not have one. |
parameter_too_long |
400 | Over the field maximum. | See the type column in Resources for the limit. |
parameter_out_of_range |
400 | A numeric parameter outside its bounds, typically limit. |
limit is 1 to 100. Batches take at most 1000 objects. |
parameter_conflict |
400 | Two parameters that cannot be combined. | Pass starting_after or ending_before, not both. |
parameter_invalid_reference |
400 | An id of the wrong type, for example a cat_ where a cus_ belongs. |
Check the expected prefix in Resources. |
reference_not_found |
400 | The referenced object does not exist on this account. | Create it first. References are validated when you send them, not at import. |
parameter_invalid_expand |
400 | Tried to expand something that is not a reference. | Only reference fields and line_items expand, one level deep. |
cursor_not_found |
400 | The pagination cursor names an object we cannot find. | Use an id from the previous page of the same list. |
parameter_invalid_metadata |
400 | Metadata was not a flat object of strings. | Nesting is refused rather than flattened, so what comes back is what went in. |
metadata_too_large |
400 | More than 50 keys. | Metadata is for lookup handles, not payload storage. |
metadata_key_too_long |
400 | A key over 40 characters. | Shorten the key. |
metadata_value_too_long |
400 | A value over 500 characters. | Store the bulk on your side and keep a reference here. |
currency_mismatch |
400 | A refund in a different currency from its revenue. | Match the original. The message names it. |
refund_exceeds_revenue |
400 | Refunds against one sale would exceed what was taken. | The message states how much remains refundable. |
object_not_pending |
409 | The merchant already imported or rejected this object. | It is frozen. Push a correcting object instead of editing. |
object_not_claimable |
409 | A batch named an object that is not pending. The whole batch rolled back. | Re-read pending status and rebuild the batch. |
idempotency_key_required |
400 | A create without an Idempotency-Key. |
Derive one from your own record id so a retry cannot duplicate. |
idempotency_key_too_long |
400 | Over 128 characters. | A UUID or your own id is plenty. |
idempotency_error
The Idempotency-Key conflicts with an earlier request. Keys are remembered for 24 hours.
| Code | Status | Cause | What to do |
|---|---|---|---|
idempotency_key_reused |
409 | Same key, different body. | Almost always a bug: a key was reused for genuinely new data. Use a fresh key. |
idempotency_key_in_flight |
409 | An identical request is still running. | Retry shortly. The retry replays the cached response. |
rate_limit_error
Too many requests on one key.
| Code | Status | Cause | What to do |
|---|---|---|---|
rate_limit_exceeded |
429 | Over 120 requests in a minute. | Wait for Retry-After. Watch X-RateLimit-Remaining and slow down before you hit this. |
api_error
Our fault. Safe to retry with the same Idempotency-Key, which is exactly what the key is for.
| Code | Status | Cause | What to do |
|---|---|---|---|
internal_error |
500 | An unhandled failure on our side. | Retry with backoff. If it persists, send us the request_id. |
field_spec_error |
500 | A validator is missing for a field we advertise. | A bug on our side. Please report it with the request_id. |
unknown_object |
500 | An object type was referenced that we cannot resolve. | A bug on our side. Please report it with the request_id. |