# lead.received

A new lead was submitted against a Meta Lead Gen (Instant) form and ingested via the Page `leadgen` webhook.

### Payload notes

`lead.fields` maps question key to answer; multiple-choice values are the option key (for example `k1`), not the display label.

### Provenance

`lead.formId`, `lead.adId` and `lead.campaignId` give provenance. `lead.adId` is null for organic or test leads.

### Consents

`lead.consents` lists the answer to every custom disclaimer checkbox, for example `{ "checkboxKey": "call_consent", "isChecked": true }`. Route call and SMS consent into your CRM from it. Empty when the form has no checkboxes.

### Checkbox keys

When no key was set on the checkbox, Meta derives `checkboxKey` from its text, so match on the full key. `GET /v1/ads/leads` and `GET /v1/ads/lead-forms/{formId}/leads` return the same array.

### Deduplication

Deduplicate on `lead.leadgenId` (Meta's lead id) or the event `id`.

### Routing

`account.profileId` names the Zernio profile of the Facebook account that received the lead, for multi-tenant routing. Always present, `null` only when no profile is on record.

### Requires ads enabled

Needs ads enabled on the team. Zernio asks for `leads_retrieval` at Facebook consent only then; without it Meta refuses the Page's `leadgen` subscription. Accounts connected earlier need a reconnect.

### Lost subscription

A Page can lose its `leadgen` subscription while other events keep arriving. `leadgen: false` (with a `warning`) on the Page's webhook subscription means leads are not reaching Zernio; re-subscribe the Page.




**Payload for `lead.received`:**

- **id** (required) `string`: Stable webhook event ID: the dedupe key, also sent as the X-Zernio-Event-Id header and identical on every retry and redelivery. It identifies the event only, never an account or other resource.
- **profiles**: `WebhookProfiles` - See schema definition
- **test** `boolean`: Always true when present: only a sample sent by POST /v1/webhooks/test with an event carries it. Real deliveries never do.
- **event** (required) `string`: No description - one of: lead.received
- **lead** (required) `object`: 
  - **id** (required) `string`: Zernio lead ID (AdLead document ID)
  - **leadgenId** (required) `string`: Meta lead ID (the platform's leadgen_id)
  - **formId** (required) `string`: Lead Gen form ID the lead was submitted against
  - **formName** `string,null`: Human-readable form name (best-effort; may be null)
  - **adId** `string,null`: Meta ad ID that drove the lead (null for organic/test leads)
  - **adsetId** `string,null`: No description
  - **campaignId** `string,null`: No description
  - **fields** (required) `object`: Flattened question key -> answer map. For multiple-choice questions the value is the option key (e.g. "k1"), not the display label.

  - **consents**: Sent on every delivery since 2026-10-25. Absent when an older event is redelivered, since redeliveries replay the stored payload.
  - **isOrganic** (required) `boolean`: True when the lead came from an organic post rather than a paid ad
  - **createdAt** (required) `string` (date-time): Meta's lead creation time (ISO 8601)
- **account** (required) `object`: 
  - **id** (required) `string`: Account ID (the facebook account owning the Page)
  - **accountId** `string`: Account ID (same as id); canonical field for account filtering.
  - **platform** (required) `string`: No description - one of: facebook
  - **profileId** (required) `string,null`: Profile ID of the account that received the lead. Null when the lead has no profile on record.
- **timestamp** (required) `string` (date-time): UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.