Collect errors
Understand collection errors and retry failed requests.
The collect endpoints on https://cdp.vyg.app (POST /cdp/ingest and POST /cdp/events) use the same error
format as the REST API on api.vyg.app: one error object holding a machine-readable code and a
human-readable message. The codes are the ones listed in Errors.
{
"error": {
"code": "bad_request",
"message": "Body must be a JSON object with an \"events\" array."
}
}Some responses have a {"message": "..."} body and no X-Request-Id:
404{"message":"Not Found"}for a method or path the host does not serve.429{"message":"Too Many Requests"}when the request rate limit is exceeded.500or503with amessagebody when the request cannot be completed.
Check the HTTP status first. Read error.code only when the body has an error object. The message is
for people and can change.
Every response with an error object carries an X-Request-Id header. Send your own
X-Request-Id (up to 128 printable characters) to have it echoed back; browsers may send it and read it
back. Include it when you contact VYG about a failed request.
Some errors carry extra fields next to error, never inside it:
rejected: on a400for events that carry a scope, the offending events and their JSON paths.acceptedandfailed: on a503where only some events were accepted. See Retrying.
| Status | code | When |
|---|---|---|
400 | bad_request | The body is not valid JSON, not an object, or has no events array; a /cdp/events batch has more than 50 events; or a /cdp/events event carries scope, shopDomain or source (with rejected). |
401 | unauthorized | /cdp/events only: a missing or invalid API key. |
403 | insufficient_scope | /cdp/ingest: the origin is not allowed or a payload scope does not match it. /cdp/events: customer data features are not enabled, or no store is connected. |
404 | none | A method other than POST or OPTIONS, or an unknown path. The response contains {"message":"Not Found"}. |
413 | bad_request | The body is over the limit: 64 KB on /cdp/ingest, 256 KB on /cdp/events. |
429 | none | Request rate limit exceeded: {"message":"Too Many Requests"}. |
500 | internal | An unexpected error on VYG's side. |
500 | none | An unexpected error occurred. The response contains a message body. |
503 | unavailable | Events could not be accepted. |
503 | none | The endpoint timed out or could not be reached. The response contains a message body. |
A partial failure on /cdp/events looks like this:
{
"error": {
"code": "unavailable",
"message": "Some events were queued and some were not. Retry only the events listed in \"failed\". The others are already queued, and sending them again would record them twice."
},
"accepted": 1,
"failed": [0]
}Retrying
400,401,403,404,413: do not retry unchanged. Fix the request first.429: retry with exponential backoff and jitter. These responses have noRetry-Afterheader.500,503: retry with exponential backoff. When a/cdp/events503carriesfailed, resend only the events at those indexes in youreventsarray; theacceptedones have already been received. A503with anerrorobject and nofailedmeans no events were accepted, so resend the whole batch. A500or503with only amessagefield does not say which events were accepted, so a resend may record some events twice.
Before 2026-09-28
The collect endpoints used the format {"error": "<code>", "error_description": "..."}, with their own
codes. See the migration guide for the old codes
and what replaced them.