Errors
Understand API errors and decide when to retry.
The error envelope
Every error from the REST API (https://api.vyg.app/v1) is a JSON object with one error object holding
a machine-readable code and a human-readable message:
{
"error": {
"code": "insufficient_scope",
"message": "Credential lacks a required scope"
}
}Check the HTTP status and code. The message is for people and can change.
Every response, including errors, carries an X-Request-Id header. Send your own X-Request-Id to have
it echoed back; include it when you contact VYG about a failed request.
The MCP server (/mcp) reports errors differently. See MCP errors.
Codes
| Status | code | When |
|---|---|---|
400 | bad_request | The request is malformed: an invalid id, filter, sort, cursor or body, or an unknown field in a strict body. |
401 | unauthorized | No credential, or an unknown, revoked or expired one. |
401 | legacy_credential_not_supported | A retired vyg_live_ credential. Create a new API key. |
403 | insufficient_scope | The credential is valid but lacks a scope the operation needs, the operation needs a sign-in, or a required feature is unavailable. |
404 | not_found | The requested resource could not be found. |
409 | conflict | The request conflicts with the current state, for example a duplicate name or key, or a stale schema_version. |
409 | limit_reached | A fixed per-brand limit is reached, such as the 25 custom providers a brand can have. Retrying will not help until something is removed. |
429 | rate_limited | Too many requests. VYG's own limits send a Retry-After header; a limit passed on from Shopify or Klaviyo says how long to wait in the message. |
500 | internal | VYG could not complete the request due to an unexpected error. |
503 | unavailable | The service is temporarily unavailable. Retry with backoff. |
The REST reference lists the statuses each operation can return. Validation messages name the field that
failed, for example limit: Number must be less than or equal to 100.
Retrying
400,401,403,404: the request is wrong or not allowed. Change it before sending it again.409: for aschema_versionconflict, read the resource again, re-apply your change and send it. For a duplicate, pick another name or key. Forlimit_reached(for example the per-brand custom provider limit onPOST /v1/providers), remove something before trying again.429: wait the number of seconds in theRetry-Afterheader, or the wait the message gives, then retry. See Rate limits.500,503: retry with exponential backoff and jitter.
Writes are not idempotent. If a write times out, read the resource before retrying so you do not create it twice.
Collect endpoints
The collect host (https://cdp.vyg.app) uses the same error format and codes. A body over the size limit is
413 with bad_request. Some responses (404, 429, 500 or 503) have a {"message": "..."} body instead, so
check the status first. See Collect errors.
MCP errors
The MCP server at https://api.vyg.app/mcp uses a different error format. Errors come in three forms.
Credential errors happen before the request is read. The body is flat, with error and
error_description strings:
{ "error": "unauthorized", "error_description": "Authentication required." }A 401 also carries a WWW-Authenticate header whose resource_metadata points at
https://api.vyg.app/.well-known/oauth-protected-resource. MCP clients use it to start sign-in. Other
credential problems use the same flat shape with the REST status, for example 403 with
insufficient_scope.
Protocol errors are JSON-RPC error objects:
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32603, "message": "Internal error" } }JSON-RPC code | Meaning |
|---|---|
-32700 | The request body is not valid JSON. |
-32000 | Wrong HTTP method (send MCP requests with POST), or, with HTTP 415, an MCP 2026-07-28 request without a JSON Content-Type. |
-32001 | The request timed out. Retry with backoff. |
-32602 | Invalid request parameters. Also returned when the tool name is unknown or not available to your credential. Invalid tool arguments come back as a tool error instead (see below). |
-32020 | MCP 2026-07-28 only, with HTTP 400: the MCP-Protocol-Version, Mcp-Method or Mcp-Name header is missing or does not match the request body. |
-32022 | MCP 2026-07-28 only, with HTTP 400: the requested protocol version is not supported. The error data lists the supported versions; pick one and retry. |
-32603 | An unexpected error on VYG's side. Retry with backoff. |
An MCP 2026-07-28 request without a JSON Content-Type (application/json) is refused with HTTP 415.
Tool errors are normal tool results with isError: true. The text starts with the same code the
REST API uses, for example not_found: Customer not found, so the codes and
retry rules above apply.