Error Codes
This document specifies how the API reports failure: the error body every endpoint returns, the HTTP status codes in use, the error code values an integrator must handle, and the retry discipline that applies to each class.
The error body
Every failed request returns a non-2xx status and this JSON body: the same shape on every endpoint
{
"error": {
"code": "validation_failed",
"message": "Field 'price' must be a decimal string with at most two decimal places."
}
}
codeis the stable, machine-readable value. Switch oncode, never onmessagetext.messageis human-readable, safe to log and to show to an operator, and may be reworded over time without notice. It names the field or condition at fault where the fault is in the request.- Validation failures may add a
fieldsobject naming each offending field and its fault. Clients shall tolerate additional fields in the error object. - A response that is not JSON, or a connection failure, is a transport problem, not an API error: handle it under the retry rules below, not by parsing.
Success responses never contain an error object; failure responses contain nothing else.
HTTP status codes
| Status | Meaning on this API |
|---|---|
200 | Success |
201 | Created |
400 | Malformed request: the body is not valid JSON, or a query parameter cannot be read |
401 | Missing or invalid API key |
403 | Authenticated, but the account's tier or standing does not permit this action |
404 | No resource with that identifier exists in your account |
409 | Conflict: the resource's current state forbids the action, or a uniqueness rule was hit |
422 | Well-formed request that fails validation or a business rule |
429 | Rate limit exceeded: see Rate Limit Headers |
500 | An unexpected failure on the Platform's side |
503 | The API is temporarily unavailable, for example during announced maintenance |
A 404 is also the answer for an identifier that belongs to another account: the API does not confirm that another account's resource exists.
Error codes
Authentication and access
| Code | Status | Meaning |
|---|---|---|
missing_key | 401 | No Authorization header was sent |
invalid_key | 401 | The key is unknown, revoked, or malformed |
tier_forbidden | 403 | The key's tier does not permit this endpoint or action |
account_suspended | 403 | The account's API access is suspended |
not_a_party | 403 | Your account is not a party to the record requested |
not_brand_owner | 403 | Your account does not own the brand record |
location_forbidden | 403 | The franchise location belongs to a different account |
Request shape and validation
| Code | Status | Meaning |
|---|---|---|
malformed_json | 400 | The request body is not valid JSON |
validation_failed | 422 | A field is missing, malformed, or not an allowed value; message names the field |
invalid_filter | 422 | A list filter value cannot be applied |
invalid_period | 422 | A date range is reversed or malformed |
period_too_long | 422 | A reporting range exceeds the maximum span |
invalid_barcode | 422 | A barcode is not a valid GTIN |
evidence_required | 422 | A submission that requires an evidence document arrived without one |
consent_required | 422 | A submission that requires recorded consent arrived without it |
State and conflicts
| Code | Status | Meaning |
|---|---|---|
not_found | 404 | The resource does not exist in your account |
duplicate_sku | 409 | The seller_sku is already in use in your account |
already_shipped | 409 | The order has shipped and cannot be cancelled |
invalid_state | 409 | The action is not available in the resource's current status |
schedule_conflict | 409 | A scheduled price change overlaps an existing schedule |
location_inactive | 409 | The stocking location no longer accepts changes |
appeal_exists | 409 | An appeal has already been filed for this violation |
idempotency_conflict | 409 | The idempotency key was already used with a different request body |
Resource rules
| Code | Status | Meaning |
|---|---|---|
insufficient_unreserved_stock | 422 | A stock change would take on-hand stock below the reserved quantity |
quantity_exceeds_order | 422 | Shipped quantities would exceed the order |
invalid_tracking_number | 422 | The tracking number does not match the carrier's format |
amount_exceeds_balance | 422 | A refund amount exceeds the payment's unrefunded balance |
compare_at_below_price | 422 | A reference price is below the selling price |
vcpr_not_current | 422 | A prescription action was attempted without a current VCPR |
Platform
| Code | Status | Meaning |
|---|---|---|
rate_limited | 429 | Too many requests; wait for the interval in the rate-limit headers |
internal_error | 500 | An unexpected failure; safe to retry a read, and a write carrying an idempotency key |
temporarily_unavailable | 503 | Temporary unavailability; retry after a delay |
Endpoint references add endpoint-specific codes in their own error tables (for example Catalog Endpoints and Pricing Endpoints); the codes above are the shared set, and a code keeps the same meaning wherever it appears.
Retry discipline
- Retry with backoff:
429(after the wait stated in Rate Limit Headers),500, and503. Use increasing delays: for example 1, 4, and 16 seconds: and stop after a small number of attempts. - Never retry unchanged:
400,401,403,404,409,422. The request or the resource state is the problem; repetition changes nothing and repeated authentication failures may be treated as misuse. - On
409for a create: the resource may already exist (a prior attempt succeeded). Re-read it before deciding to resend, and send writes with anIdempotency-Keyheader so retries are applied once (Idempotency Keys). - Log the
code, the status, and the request path for every failure you surface to an operator. Do not log your API key.
If a 500 persists for a request that should succeed, contact support@aapawz.com with the time (UTC), the path, the status, and the code: never with your key.