VYG Developer Docs
Webhooks

Webhook Endpoint Reference

URL, headers, body shape, and response semantics for the Custom E-Com webhook endpoint.

VYG exposes a single webhook endpoint for Custom E-Com integrations. Every event you send is a Custom Event — a brand-defined type slug with a JSON Schema and identifier mapping you register up front.

URL

POST https://<your-vyg-webhook-host>/custom/{webhookId}

webhookId is a short, opaque identifier shown on the Settings → Providers → Custom E-Com page after you connect the integration. It remains stable for the lifetime of the integration (it does not change when you regenerate your webhook secret) and is safe to commit to your codebase. Your account contact will give you the exact <your-vyg-webhook-host> for your environment.

Required headers

HeaderRequiredDescription
content-typeMust be application/json.
x-vyg-signatureLowercase hex HMAC-SHA256 of the raw request body, keyed with the brand's webhook secret. See HMAC Verification.
x-vyg-event-idStable, unique id for the event. Same id within 24h is treated as a duplicate and short-circuited.
x-vyg-topicYour registered custom event slug. Must match the type field in the body.

Body shape

The body must be a JSON object with three top-level fields:

type CustomWebhookBody = {
	type: string; // your registered custom event slug
	event_id: string; // matches the x-vyg-event-id header
	data: Record<string, unknown>; // validated against your registered payload schema
};

data must be a JSON object — arrays and scalars are rejected with 400 invalid_payload. The exact required shape comes from the JSON Schema you registered for that type. See Custom Events for the registration model, schema rules, and identifier mapping.

Response semantics

StatusMeaningShould you retry?
200Accepted. Body is {"ok":true,"custom_event_id":"…","flow_event_id":null} or {"deduplicated":true}. flow_event_id is always null: the event is recorded synchronously, but flow triggering runs asynchronously, so no flow id exists when the webhook replies. See Triggering flows.No.
400Missing path parameter, missing signature/body, malformed JSON, body missing type / event_id, or data failed schema validation.No — fix the request and re-send with a new event_id.
401Webhook secret not configured, or HMAC signature did not match.No — verify your signing implementation, then re-send.
404webhookId not found, integration is disabled, or no enabled definition matches the type.No — register or re-enable the definition, then re-send.
422Identifier mapping resolved no external_id, or no email/phone for the contact channel.No — fix the payload or extend the mapping.
500Transient server-side error.Yes, with backoff.

A 404 unknown_event_type response is not stored in the idempotency cache, so you can register the definition and replay the same event_id afterwards.

Idempotency

VYG deduplicates on the (webhookId, x-vyg-event-id) tuple indefinitely: once an event with a given id is accepted, a duplicate request — at any age — short-circuits with 200 OK and body {"deduplicated":true}. No work is repeated.

Replays must always use a new event_id. Reusing an old id (for example from a recovery script run weeks later) is still treated as a duplicate by the database layer and will silently return {"deduplicated":true} — the event is recorded only once.

Body size and timeout

The endpoint is backed by an AWS Lambda function. Stay well within the AWS API Gateway and Lambda payload limits — in practice, well under 6 MB of JSON. Most webhook payloads are a few kilobytes, so this only matters if you're tempted to inline product catalogs or large media references; don't.

On this page