Webhook API
If you prefer to send conversion events from your server rather than the browser, you can POST directly to the Pruuv webhook endpoint. This is useful when you already have lead data in a CRM or backend system and want to forward it to Pruuv without adding JavaScript to your pages.
fbc / fbp (Meta cookies) or ttclid (TikTok click ID) — these can only be read from the browser at the moment of the ad click. For best Meta and TikTok match rates, use the Pixel SDK on your landing pages and include the cookie values in your server-side payload.Authentication
All requests must include a Bearer token in the Authorization header. The token is the Webhook Token shown alongside each funnel stage in Connections > Funnel Webhooks.
Endpoint
POST https://app.pruuv.io/api/webhooks/funnel/{stageId}
Authorization: Bearer YOUR_WEBHOOK_TOKEN
Content-Type: application/jsonExample request
curl -X POST https://app.pruuv.io/api/webhooks/funnel/YOUR_STAGE_ID \
-H "Authorization: Bearer YOUR_WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reference": "CRM-REF-001",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "brand-search",
"gclid": "EAIaIQobCh...",
"revenue_value": 250,
"currency": "GBP"
}'Payload reference
All fields are optional except reference.
| Field | Type | Description |
|---|---|---|
| reference | string | Required. Unique identifier for this contact or conversion. Used for deduplication. |
| item_reference | string | Secondary reference — deal ID, order number, etc. |
| utm_source | string | UTM source parameter |
| utm_medium | string | UTM medium parameter |
| utm_campaign | string | UTM campaign parameter |
| utm_content | string | UTM content parameter (used for ad-level attribution) |
| utm_term | string | UTM term parameter |
| gclid | string | Google click ID |
| wbraid | string | Google web-to-app click ID |
| gbraid | string | Google app-to-web click ID |
| ttclid | string | TikTok click ID |
| msclkid | string | Microsoft/Bing click ID |
| fbc | string | Meta _fbc cookie value |
| fbp | string | Meta _fbp cookie value |
| click_timestamp | ISO datetime | Time of the original ad click (required for Google Conversion Upload API) |
| revenue_value | number | Conversion value |
| currency | string | ISO 4217 currency code (e.g. GBP, USD, EUR) |
| data_timestamp | ISO datetime | Conversion timestamp. Defaults to now if omitted. |
| gender | string | Demographic — for reporting only |
| age_range | string | Demographic — for reporting only |
| location_country | string | Demographic — for reporting only |
| location_region | string | Demographic — for reporting only |
| job_title | string | Demographic — for reporting only |
| company_size | string | Demographic — for reporting only |
| industry | string | Demographic — for reporting only |
Responses
| Status | Body | Meaning |
|---|---|---|
| 200 | { received: true, event_id: "..." } | Event accepted and stored |
| 200 | { received: true, duplicate: true } | Duplicate — same reference at same stage within 60 seconds |
| 400 | { error: "Validation failed", details: {...} } | Invalid payload — check field types |
| 401 | { error: "Unauthorized" } | Missing or incorrect bearer token |
| 404 | { error: "Stage not found" } | stageId does not exist |
| 429 | { error: "Rate limit exceeded" } | More than 1,000 events/hour for this stage |
| 500 | { error: "Internal error" } | Server error — contact support if persistent |
Deduplication
Events with the same reference at the same stage within a 60-second window are deduplicated. Only the first call is recorded; subsequent identical calls within the window return { received: true, duplicate: true } with a 200 status. This makes it safe to retry on network errors.
Rate limits
The webhook accepts a maximum of 1,000 events per hour per funnel stage. Requests beyond this limit receive a 429 response.
Integration paths compared
| Path | Google (gclid) | Meta (fbc/fbp) | TikTok (ttclid) | Effort |
|---|---|---|---|---|
| Pruuv Pixel (recommended) | Auto-captured | Auto-captured | Auto-captured | Paste snippet + call track() |
| Backend webhook | Must capture yourself (hidden field) | Requires JS on landing page | Requires JS on landing page | Self-implement capture + POST |
| CRM pull (coming soon) | Available if CRM stores gclid | Rarely stored in CRMs | Rarely stored in CRMs | CRM config only |