LiveRecoverVYG Developer Docs
Custom Integration

Errors & Retry Semantics

What each response status means and when to retry.

The Custom E-Com webhook endpoint returns a small, well-defined set of HTTP statuses. Use them as the source of truth for whether to retry — do not parse response bodies for retry decisions.

Status codes

200 OK — accepted

Two meaningful body shapes:

BodyMeaning
{"ok":true, ...}Event was verified, validated, and recorded synchronously. If you have an active flow on this event, flow triggering runs asynchronously afterward (the response carries no flow id).
{"deduplicated":true}Same (webhookId, x-vyg-event-id) was already accepted within the last 24h.

Retry? No — your delivery is done.

400 Bad Request — your request is malformed

Returned for any of:

  • Missing webhookId in the URL path.
  • Missing x-vyg-signature header or empty body.
  • Body is not valid JSON.
  • Body is missing the type or event_id field.

Retry? No. Fix the request before re-sending. If you do re-send after fixing, use a new x-vyg-event-id so the original (broken) attempt isn't deduplicated against the fix.

401 Unauthorized — signature problem

Returned when:

  • The brand has no webhook secret configured (rotate it from Settings → Providers → Custom E-Com).
  • The x-vyg-signature does not match the HMAC-SHA256 of the body keyed with the brand's secret.

Retry? No. Verify your signing implementation against the HMAC Verification examples — the same fixture body and secret must produce the documented hex string. The most common cause is signing one representation of the body and sending another (re-stringification, whitespace, trailing newlines from echo).

404 Not Found — integration or event type not found

Returned when the webhookId from the URL path matches no enabled integration, or when no enabled event definition matches the type you sent ({"ok":false,"reason":"unknown_event_type", ...}). This usually means:

  • Wrong id in the URL.
  • The integration was disabled on the LiveRecover side.
  • The type slug is not registered (or its definition is disabled). Send only topics you have registered; an unregistered topic is never recorded and never triggers a flow.

Retry? No. Confirm the id with your account contact, or register / re-enable the event definition, then re-send.

500 Internal Server Error — transient

Anything thrown out of the handler that isn't one of the above.

Retry? Yes — with backoff.

For 5xx only:

  • Jittered exponential backoff.
  • Suggested schedule: 1s → 5s → 30s → 5m → 30m → 1h → ... up to 24h.
  • Always retry with the same x-vyg-event-id. Idempotency is persisted on (webhookId, x-vyg-event-id), so reusing the id is safe at any horizon — a successful original delivery short-circuits with 200 {"deduplicated":true} and the event is recorded only once.
  • Stop retrying once you receive any 2xx (the event is accepted or was already accepted) or a non-5xx error.

Do not retry 4xx. Doing so consumes your sending budget without changing the outcome and can mask real bugs (e.g., a clock-skewed signing machine that produces 401 for every request).

Idempotency window and retries

LiveRecover deduplicates accepted events on (webhookId, x-vyg-event-id) indefinitely — once an event with a given id is accepted, replaying it with the same id always short-circuits to 200 {"deduplicated":true} and the event is never recorded twice, no matter how much time has passed.

What this means for integrators:

  • Reuse the same x-vyg-event-id for every retry of the same delivery — at any horizon, hours or weeks later. The replay is deduped.
  • For a brand-new event, mint a new x-vyg-event-id. Reusing an old id will short-circuit to 200 {"deduplicated":true} and the event will not be recorded a second time.
  • The 24h ceiling on retry budget above is just a sending-cost guideline, not an idempotency window — exceeding it does not risk double-processing.

On this page