Skip to main content
The v2 REST API uses a single, predictable error envelope across every endpoint. Whatever the failure — a missing auth token, a Zod validation problem, a 404, a downstream rate limit — the body shape is the same. Build your error-handling once and reuse it everywhere.
This page covers v2 REST endpoints. MCP tool errors follow the ADCP error spec and are returned in structuredContent rather than HTTP status codes.

Error envelope

Every non-success response has data: null and a populated error object:
Successful responses have the inverse shape: { "data": <result>, "error": null }. List endpoints add a meta block (see Pagination).
Throughout the Buyer and Storefront task references, the ## Response examples show the data payload only — the inner result. On the wire it is always wrapped in the envelope above: { "data": <payload>, "error": null }, plus a meta block on list endpoints. Read the result from response.data.

HTTP status codes

Common error codes

Domain-specific codes you may encounter on campaign endpoints:

Validation errors

When request validation fails, code is VALIDATION_ERROR and details.issues enumerates every problem Zod found, with dotted field paths:
When a single-field check fails (e.g. a route guard), field is set instead:
Always render details.issues[].path in your UI — the user usually just needs to know which form field to fix.

Handling errors in client code

Don’t pattern-match on message text — message strings may be reworded for clarity. Always branch on error.code (and on HTTP status as a fallback).

Retrying safely

RATE_LIMITED, INTERNAL_ERROR, and SERVICE_UNAVAILABLE are transient — retry GETs with exponential backoff. For creation/mutation requests after a 5xx, prefer to surface the error rather than auto-retry, since duplicate-create protection isn’t enforced server-side. VALIDATION_ERROR, NOT_FOUND, FORBIDDEN, ACCESS_DENIED, and CONFLICT are terminal — don’t retry until the input or state changes.