Skip to content

Sending Data via Webhook

This page explains exactly what to send to DURUM.ai for the app to work at its full potential. Whether you use GHL, Typeform, Calendly, Stripe, Zoho, Pipedrive, or a custom tool, the rules are the same.


The 3 Absolutely Essential Things

Without these 3 elements, your event won't be processed correctly.

1. Identify Your Account (client_key)

Every webhook must be associated with your account. There are two ways to do it:

Option A -- In the URL with bid (recommended):

https://app.durum.ai/api/webhook/lead?bid=YOUR_BUSINESS_ID

This is the format the app gives you in Settings -> Integrations. The bid is a unique, unguessable identifier, safer than a readable key. All 7 standard endpoints accept it.

Option B -- In the URL with client_key:

https://app.durum.ai/api/webhook/lead?client_key=YOUR_KEY

Still fully supported, no deprecation.

Option C -- In the JSON payload:

json
{ "client_key": "YOUR_KEY", "email": "..." }

Without client_key

The event is placed in quarantine. It won't be lost, but it will need to be classified manually by the agency. Your KPIs won't be updated in real time.

2. Identify the Contact (Email or Phone)

DURUM.ai needs to identify who the prospect is. Send at minimum one of these fields:

FieldExamplePriority
emailjohn.smith@email.comIdeal -- also used for deduplication and attribution
phone+15145551234Good backup -- E.164 format or 10 digits
nameJohn SmithUseful but insufficient alone

Without Email or Phone

For booking, no-show and sale (generic JSON), the event is rejected (rejected: missing_contact_info response): an appointment or sale that cannot be tied to a contact is useless and would skew your KPIs. For lead and application, the event will still be recorded, but the system won't be able to:

  • Detect duplicates (risk of counting the same lead twice)
  • Link the lead to future actions (booking, sale)
  • Enrich data with contact history

3. Send to the Right Endpoint

Each event type has its own endpoint. This is what determines the type in DURUM.ai.

WhenEndpointWhat Is Created
A prospect shows interest/api/webhook/leadLead
A prospect fills out a detailed form/api/webhook/applicationApplication
An appointment is booked/api/webhook/bookingBooking
A prospect doesn't show up/api/webhook/no-showNo-show
A sale is closed/api/webhook/saleSale
A payment is received/api/webhook/paymentPayment
A refund is issued/api/webhook/refundRefund
An event of your own (beyond the 7 standard)/api/webhook/eventCustom event (named)

Custom events (your own events)

Beyond the 7 standard events, you can send any event, under any name you want ("Demo completed", "Deal moved to stage X", "Watched 80% of webinar"...).

The event name goes in the URL; the body only carries the contact data:

POST https://app.durum.ai/api/webhook/event?client_key=YOUR_KEY&event_name=demo_completed&source=custom
Content-Type: application/json

{
  "email": "client@example.com",
  "phone": "+15145550199",
  "value": 250,
  "occurred_at": "2026-07-07T14:00:00Z"
}

Recognized fields: email, phone, value, occurred_at, contact_id, calendar_name — plus the 13 attribution fields if you want to tie the event to an ad. Any other field is kept in the raw payload.

Where to create a custom event in the app

Settings -> Events -> "Add a custom event": name it, get its dedicated webhook URL + the JSON frame. It then shows up in your Conversions (Conversions page) and integration mappings (e.g. "this Calendly calendar = this event").

One event != three events

If 3 integrations all send leads, that's one Lead event fed by 3 sources — not 3 events. To split by source, use a filter at the conversion level, never a separate event. A custom event is only for a signal that does not exist among the 7 standard.


The 13 Ad Attribution Fields

These fields allow DURUM.ai to link each lead, booking, and sale to the exact ad that generated it. This powers the Marketing table, CPA calculation, ROAS, ROI, and all attribution in the app.

Without These Fields, the App Loses Its Core Value

A lead without UTMs arrives in DURUM.ai but it's impossible to know which ad it came from. Your marketing KPIs (CPA, ROAS, ROI) will be inaccurate. You won't know which ad is performing and which is wasting your budget.

The 5 UTMs (Ad Element Names)

These are the readable names of your campaigns, ads, and ad sets. DURUM.ai uses them to match events with your Meta ads.

#FieldAccepted AliasesWhat It Does in the AppExamplePriority
1utm_campaignutmcampaign, UTM_Campaign, campaign_nameLinks the event to the campaign. Used in the Marketing table, campaign filter, and per-campaign spend calculation.bootcamp-march-2026Non-negotiable
2utm_contentutmcontent, UTM_Content, ad_name, utm_ad_nameLinks the event to the ad. This is THE field that connects a lead to a Meta ad. Without it, no per-ad attribution.ad-testimonial-tx1-ix2Non-negotiable
3utm_sourceutmsource, UTM_SourceIdentifies the traffic source. Distinguishes Meta vs Google vs organic in reports.meta, google, tiktok, organicImportant
4utm_mediumutmmedium, UTM_MediumIdentifies the traffic type. Distinguishes paid from organic, email, social.paid, cpc, email, social, organicImportant
5utm_termutmterm, UTM_Term, utm_adset_name, adset_nameLinks the event to the ad set. Enables per-audience/ad set performance analysis.adset-lookalike-1pct, adset-retarget-30dRecommended

The 3 Meta IDs (Numeric Identifiers)

These are Meta Ads numeric IDs. They enable exact matching instead of name matching (more reliable if you rename a campaign).

#FieldAccepted AliasesWhat It Does in the AppExamplePriority
6utm_campaign_idcampaign_idExact match with the Meta campaign by ID instead of name120210987654321Recommended
7utm_ad_idad_idExact match with the Meta ad by ID instead of name120210123456789Recommended
8utm_adset_idadset_idExact match with the Meta ad set by ID instead of name120210111222333Recommended

Names vs IDs -- Why Both?

Names (utm_campaign, utm_content, utm_term) are readable and useful in tables. IDs (utm_campaign_id, utm_ad_id, utm_adset_id) are reliable even if you rename a campaign. Ideally, send both. If you can only send one, send the names.

The 3 Complementary Fields

#FieldAccepted AliasesWhat It Does in the AppExamplePriority
11product_keyproduct, funnel_keyIdentifies the product or service. Powers the per-product funnel, per-product revenue, and commissions.bootcamp_aiImportant
12assigned_user_nameassigned_to, Deal_Owner, rep_nameIdentifies the assigned sales rep. Powers the Sales Reps table and per-rep commissions.Marie DupontRecommended
13amountvalue, total, Amount, Grand_TotalDollar amount of the sale or payment. Without this field, ROI, ROAS, and revenue will be $0.2500Non-negotiable (sales/payments)

Complete Example with ALL Attribution Fields

json
{
  "email": "john.smith@email.com",
  "phone": "+15145551234",
  "name": "John Smith",
  "product_key": "bootcamp_ai",
  "amount": 2500,
  "assigned_user_name": "Marie Dupont",

  "utm_source": "meta",
  "utm_medium": "paid",
  "utm_campaign": "bootcamp-march-2026",
  "utm_content": "ad-testimonial-tx1-ix2",
  "utm_term": "adset-lookalike-1pct",

  "utm_campaign_id": "120210987654321",
  "utm_ad_id": "120210123456789",
  "utm_adset_id": "120210111222333"
}

Form Question Responses

Each client asks different questions in their forms (GHL, Typeform, Calendly). All responses are captured and stored, even if they don't match standard fields. Nothing is lost.

All responses arrive in the event's raw_payload field (JSONB format). This is a complete storage of the original payload -- every question, every answer, every custom field.

In addition to raw storage, certain fields are automatically extracted to dedicated columns (email, phone, name, UTMs). Others remain in raw_payload and are accessible for analyses, exports, or advanced filters.

Powered by DURUM.ai — ad attribution and operational intelligence