Webhook Endpoint Reference
Send a custom event and handle its response.
Send events to your integration's webhook URL. Register each event type before sending it.
URL
POST https://<your-vyg-webhook-host>/custom/{webhookId}webhookId is the last part of the Webhook URL on your data source's page in Settings → Data
sources.
It stays the same when you replace your webhook secret. Ask your VYG account contact
for the webhook host.
Required headers
| Header | Required | Description |
|---|---|---|
content-type | ✓ | Must be application/json. |
x-vyg-signature | ✓ | Lowercase hex HMAC-SHA256 of the raw request body, keyed with the brand's webhook secret. See HMAC Verification. |
x-vyg-event-id | ✓ | Stable, unique id for the event. Reuse it when retrying the same delivery. |
x-vyg-topic | ✓ | Your 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 to define the required fields and identify the customer.
Response semantics
| Status | Meaning | Should you retry? |
|---|---|---|
200 | Accepted. Body is {"ok":true,"custom_event_id":"…","flow_event_id":null} or {"deduplicated":true}. flow_event_id is null; acceptance does not confirm a campaign run or message delivery. See Triggering flows. | No. |
400 | Missing path parameter, empty body, malformed JSON, body missing type / event_id, or data failed schema validation. | Fix the request and resend with the same event_id. |
401 | Webhook secret not configured, or signature is missing or invalid. | No — verify your signing implementation, then re-send. |
404 | webhookId not found, integration is disabled, or no enabled definition matches the type. | No — register or re-enable the definition, then re-send. |
422 | Identifier mapping resolved no external_id, no email/phone for the contact channel, or a contact_channel_conflict (email/phone already owned by another contact). Email alone is accepted; SMS/agent flows still need phone. | No — fix the payload, extend the mapping, or resolve the identity conflict. |
500, 503 | Transient server-side error. | Yes, with backoff. |
A 200 response with {"ok":false,"reason":"dead_letter"} means the event could not
be processed. Stop automatic retries and contact VYG support with the event ID.
After 404 unknown_event_type, register or enable the definition and resend with
the same event_id.
Idempotency
Retry an unchanged delivery with the same event_id. If a payload is rejected, correct
it and resend; a new event_id is not required.
The entity ID selected by external_id_path identifies the saved record within the
event definition. Another delivery for that entity does not create a separate record.
Use a different entity ID only for a genuinely different entity.
Request size
Send one JSON event per request. Include the fields needed by your registered event schema.