Lead Form Webhooks
Lead form webhooks send captured lead data from ResultFly to an external system such as a CRM, CDP, email platform, or custom backend.
Use them when you want a server-to-server delivery after a visitor submits a lead form.
Delivery events
Lead form webhooks can be delivered for two lead-form event types:
submitted: the final submit step of a lead form.draft_submitted: a non-final step submit in a multi-step lead form.
Use submitted when you want only completed leads.
Use draft_submitted when you also want to capture partial leads from earlier steps. This is useful for capturing valuable lead data even when visitors abandon the form before completion — you can follow up with incomplete submissions and recover potential customers.
Important: When a visitor completes the form and the final submitted event is sent, it includes all the data accumulated from previous draft steps. You do not need to manually map or combine draft submissions — the final payload already contains the complete, up-to-date form data.
What marketers can use
A lead form webhook gives you two views of the same submission:
- Data: a simple object with the most useful named fields, ready for CRM mapping.
- Fields: a complete map of all submitted fields by field ID, including fields that do not have a public field name.
This keeps integrations easy for common cases without losing information from the original form.
Example payload
{
"eventId": "evt_01",
"eventType": "lead.captured",
"version": 1,
"occurredAt": "2026-03-25T12:00:00Z",
"campaign": {
"id": "cmp_123",
"name": "Spring promo"
},
"session": {
"id": "f9440f27-ce8e-4543-b2b4-dbbfad18612a"
},
"context": {
"embedUrl": "https://resultfly.com/campaign/123456"
},
"data": {
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"consent": {
"accepted": true
}
},
"fields": {
"field_first_name_uuid": {
"fieldName": "firstName",
"label": "First name",
"semanticKey": "first_name",
"valueType": "text",
"required": true,
"hidden": false,
"readonly": false,
"value": "John",
"source": "user"
},
"field_last_name_uuid": {
"fieldName": "lastName",
"label": "Last name",
"semanticKey": "last_name",
"valueType": "text",
"required": true,
"hidden": false,
"readonly": false,
"value": "Doe",
"source": "user"
},
"field_email_uuid": {
"fieldName": "email",
"label": "Email",
"semanticKey": "email",
"valueType": "email",
"required": true,
"hidden": false,
"readonly": false,
"value": "john.doe@example.com",
"source": "user"
},
"field_consent_uuid": {
"fieldName": "consent",
"label": "Privacy consent",
"semanticKey": "consent",
"valueType": "boolean",
"required": true,
"hidden": false,
"readonly": false,
"value": true,
"source": "user"
},
"field_without_name_uuid": {
"fieldName": null,
"label": "City",
"semanticKey": null,
"valueType": "text",
"required": false,
"hidden": false,
"readonly": false,
"value": "Barcelona",
"source": "user"
}
}
}How data is built
data is optimized for quick setup in tools that expect named fields.
ResultFly can fill standard keys from field meaning:
emailfirstNamelastNamephoneNumberconsent.accepted
Custom fields can also appear in data when they have a Field name.
If a field has no Field name and no standard meaning, it is not added to data. It still appears in fields.
How fields is built
fields is the complete view of the submission.
Each key is the internal field ID, and each value includes:
fieldName: the field name used for integrations, ornullwhen not setlabel: the label shown in the formsemanticKey: standard meaning such asemail,first_name, orconsent, ornullwhen not setvalueType: expected value format, such astext,email, orbooleanrequired: whether the field is requiredhidden: whether the field is hidden from the visitorreadonly: whether the field is read-onlyvalue: the submitted valuesource: whether the value came from the visitor or from prefill
Consent is included in fields like any other form field.
Field names
Use Field name for fields that should be easy to map in a CRM or automation tool.
Good examples:
firstNamelastNameemailcompanycity
Do not rely on the label as the integration key. Labels are user-facing text and may change for copy, branding, or localization reasons.
Consent
For the simple data view, consent is represented as:
{
"consent": {
"accepted": true
}
}The event timestamp is already available as occurredAt, so consent does not include a separate timestamp in the standard webhook payload.
The full consent field still appears in fields with its field ID, label, value type, required state, and submitted value.
Multiple webhook configs per campaign
You can set up multiple webhook configurations for the same campaign to send lead data to different destinations. Each webhook config can be independently:
- Enabled or disabled using the enable toggle — pause delivery without deleting the configuration
- Edited to update endpoint URLs, headers, or event types
- Tested before activation
This is useful when you want to send leads to multiple CRM systems, analytics platforms, or internal services simultaneously, or when you need to temporarily pause one integration while keeping others active.
Test before launch
Before publishing, send a test webhook from the campaign Integrations modal and verify:
- your endpoint accepts the request with a
2xxresponse; - your CRM/automation mapping reads the expected fields from
dataandfields; - your team can distinguish
submittedanddraft_submittedflows.