This guide specifies how nGrow is expecting your custom built webfunnels to send user events to our webhook.
🔧 General Requirements
Our server will respond with a 2xx HTTP status within 1 second after receiving a webhook request.
If no such response is received, the event is considered undelivered.
Undelivered events should be retried automatically using an exponential backoff strategy:
delay(n) = n⁴ + 15 + rand(0, 29) × (n + 1)
Where:
delay — delay in seconds before the next retry
n — retry attempt number (starting from 1)
rand(0, 29) — a random integer between 0 and 29
🌐 Webhook Endpoint
URL:
Please use webhook url provided to you during nGrow app onboarding on 'Select Funnel Builder' page
https://email-webhooks.ngrow.ai/api/v1/web2wave-webhook/<ngrow_app_id>.
Each webhook request contains a JSON payload depending on the event type.
📥 Supported Event Types
Event Type | Description |
profile.updated | Fired when a user updates their profile. Email is required to be present. |
onboarding.completed | Fired when the user completes onboarding. |
purchase.completed | Fired on initial purchase, upsell, or recurring transaction. |
subscription.renewed | Fired when an existing subscription is renewed. |
📌 Common Required Fields (all events)
{
"type": "string", // Event name
"funnel_id": "string", // The current funnel or paywall id
"project_id": "string", // Any consistent project_id, associated with app
"created_at": 1734392768, // UNIX time in UTC timezone
"profile": {
"id": "string",
"country": "string", // 2-digit ISO code
"city": "string",
"locale": "string", // ISO (e.g. en-us)
"time_zone": "string" // e.g. America/New_York
}
}
🔍 Event-Specific Payloads
1. profile.updated
Triggered when user properties change. Must be fired when the user submits their email.
Required additional field:
"data": {
"email": "[email protected]"
}
Example:
{
"type": "profile.updated",
"created_at": 1734392768,
"funnel_id": "fun_01...",
"project_id": "01HP...",
"profile": {
"id": "pro_01...",
"country": "US",
"city": "New York",
"locale": "en-US",
"time_zone": "America/New_York"
},
"data": {
"email": "[email protected]"
}
}
2. onboarding.completed
Triggered when the user finishes the onboarding funnel.
After the funnel is completed, we expect the onboarding.completed event. In addition to the common fields, it must contain the data.replies attribute — an array of objects describing the user’s answers.
Each object in data.replies includes:
screen.custom_id — optional (screen name or text)
screen.id — screen ID
screen.index — screen position in the funnel
element.custom_id — optional (question name or label)
element.id — question ID
element.type — Options (single/multi choice) or Input (free text)
state.value — answer ID or text. If multiple options selected, values are comma-separated
Example:
{
"type": "onboarding.completed",
"created_at": 1734388235,
"data": {
"replies": [
{
"screen": {
"custom_id": "q_triggers",
"id": "W5mtQrrW",
"index": 22
},
"element": {
"custom_id": "q_triggers",
"id": "W5mtQrrW",
"type": "Options"
},
"state": {
"value": "nrWU6, 2ndrm, gefCv, family-issues, not-enough-me-time-or-self-care"
}
}
]
}
}
3. purchase.completed
Triggered on any type of user purchase.
Required fields in data:
id, created_at, price, currency
vendor_product_id, vendor_profile_id, vendor_transaction_id
Example:
{
"type": "purchase.completed",
"created_at": 1734349469,
"data": {
"id": "tra_...",
"currency": "USD",
"price": 3000,
"vendor_product_id": "prod_...",
"vendor_transaction_id": "in_..."
}
}
4. subscription.renewed
Fired when the subscription is renewed by the payment provider.
Required fields in data:
starts_at, vendor, vendor_subscription_id, vendor_transaction_id
Example:
{
"type": "subscription.renewed",
"created_at": 1734349469,
"data": {
"starts_at": "2024-09-14T13:44:02Z",
"vendor": "stripe",
"vendor_subscription_id": "sub_...",
"vendor_transaction_id": "in_..."
}
}