Zapier
Capture leads from Facebook Lead Ads, Typeform, Webflow and 6000+ other apps via Zapier, step by step.
Setup
Create a Zap with Facebook Lead Ads as source and Webhooks by Zapier as action.
Create a new Zap
In Zapier, click Create Zap. Name your Zap (e.g. Facebook Leads → Capturia).
Configure the Facebook Lead Ads trigger
As Trigger app, choose Facebook Lead Ads. Connect your Facebook Business account, select the Page and the Lead Form you want to route to Capturia. Click Test trigger — Zapier pulls a test lead from the form.
Add the Webhooks by Zapier action
As Action app, choose Webhooks by Zapier. As Event, select POST (not Custom Request, not GET).
Configure URL and authentication
URL: https://api.capturia.io/v1/leads/capture
Payload Type: JSON (not Form, not XML)
Headers: add Authorization with the value Bearer cap_live_xxxxxxxx (your full Capturia API key).
Map the fields
In the Data section, add the Capturia fields (see the mapping table below). Drag the matching Facebook Lead fields from the right-hand panel.
Nested fields: for utm and pipeline, write the flat key with a dot, as is: utm.source, utm.medium, pipeline.pipeline_slug, pipeline.stage_slug. Capturia files each key into its block.
Capture SMS consent
Recommended pattern: add a custom SMS consent question to your Facebook Lead Form (Custom Question type "Yes/No" or checkbox). Map this field to sms_consent.
Alternative pattern: if the custom question isn't possible, hardcode sms_consent: true but keep proof of consent (checkbox on the landing page, archived copy). See the LCAP section below.
Test and publish
Click Test action to send the test lead to Capturia. A 200 OK response with status: created or status: idempotent_replay confirms the connection. In Prospects on Capturia, the test lead appears immediately. If everything is OK, click Publish Zap to activate the connection in production.
Field mapping
Recommended mapping for Facebook Lead Ads → Capturia. Adapt source field names to your form — phone_number in some forms becomes phone in others.
| Capturia field | Required | Source field | Notes |
|---|---|---|---|
| phone | Yes | phone_number | E.164 (+15145551234), NANP 10 or 11 digits, or formatted (514) 555-1234 / 514-555-1234. 10-digit numbers auto-prefixed with +1. |
| sms_consent | Yes | consent_yes_no (custom question) | Boolean true OR string 'true' / 'yes' / 'oui' / 'vrai' / '1' / 'on' / 'checked' (case-insensitive). Accepted at the body root or inside the customData object (GoHighLevel webhooks). |
| first_name | No | first_name | Lead's first name |
| last_name | No | last_name | Last name |
| No | RFC 5322 valid email | ||
| source_label | No | (literal) fb_lead_ads | Free-form tag (e.g. 'webflow_form', 'fb_lead_ads') |
| utm. | No | (literal) facebook | Nested utm object, or the flat key utm.source |
| utm. | No | (literal) cpc | Nested utm object, or the flat key utm.medium |
| utm. | No | campaign_name | Nested utm object, or the flat key utm.campaign |
| tags | No | (literal) tag1, tag2 — or leave empty | Array of strings, or a comma-separated string |
| pipeline. | No | (literal) identifier copied from Capturia | Text identifier of the target pipeline (not its UUID). Copy it in Capturia: Administration, API Keys, "Your pipeline and stage identifiers" section. Without it, the default pipeline is targeted. Nested pipeline object, or flat key. |
| pipeline. | No | (literal) identifier copied from Capturia | Text identifier of the target stage, copied from the same place. Without it, the stage marked "Default stage" next to the identifiers. Sent without pipeline_slug, it is looked up in your default pipeline. Nested pipeline object, or flat key. |
SMS Consent — CASL / Quebec Law 25
The sms_consent field is required. Canada's Anti-Spam Law (CASL) and Quebec's Law 25 require explicit consent before any commercial SMS. Capturia stores a timestamped record of this attestation for your legal protection.
Recommended pattern — consent captured at source
Add a custom consent question directly in the source form (FB Lead Form custom question, Typeform field, GHL form checkbox). Map this field to sms_consent. Consent is explicit, dated, and tied to the lead who gave it.
Alternative pattern — checkbox on the landing page
If the source form doesn't allow custom questions, add a consent checkbox on the landing page before the ad. Keep a copy of the page (Wayback Machine, dated screenshot) as evidence.
Legal grey area
Hardcoding sms_consent: true without real lead attestation = legal risk. In case of complaint, Capturia may be required to provide proof of consent. Without proof, liability falls on the business that sends the lead.
Step-by-step test
In Zapier, click Test trigger to pull a test lead from Facebook (use Meta's "Lead Ads Testing Tool"). Then Test action to send the lead to Capturia. A 200 OK response with status: created or status: idempotent_replay confirms it works. Then check Prospects in Capturia to see the lead.
Error catalog
| Code | Error | Cause | Fix |
|---|---|---|---|
| 400 | invalid_payload | Empty body or malformed JSON (extra comma, missing quote) | Validate the JSON you send, then send again |
| 401 | missing_api_key | Authorization header absent or malformed | Add the header Authorization: Bearer cap_live_... |
| 401 | invalid_api_key | Key revoked, expired, or mistyped | Check the key in Capturia, generate a new one if needed |
| 403 | terms_acceptance_required | API terms of use not accepted (or a new version to accept) | The account owner accepts the terms in Capturia, on the API Keys page |
| 403 | insufficient_scope | Key lacks the leads:capture scope | Create a new key with the "Lead capture" preset |
| 415 | invalid_content_type | Body sent as a form (Form, x-www-form-urlencoded) instead of JSON | Send as JSON (Payload Type = JSON, Encoding = JSON, Body content type = application/JSON) |
| 422 | invalid_phone | Phone missing or format not recognized | Use E.164 (+15145551234) or NANP 10 digits (5145551234) |
| 422 | invalid_email | Malformed email | Send a valid address, or leave the field out |
| 422 | missing_consent | sms_consent absent, false, or unrecognized value — the field is looked up at the body root AND inside the customData object (GHL) | Map the consent field to sms_consent (true / yes / oui). From GHL: fixed value true behind a condition on the consent checkbox |
| 422 | invalid_payload | Another field refused (text too long, malformed date, negative value, etc.) — details names the field | Fix the field named in details, then send again |
| 422 | pipeline_not_found | pipeline.pipeline_slug matches no pipeline of the account | Copy the pipeline's text identifier again from the API Keys page (it is not its UUID) |
| 422 | stage_not_found | pipeline.stage_slug matches no stage of the targeted pipeline | Copy the stage's text identifier again from the API Keys page, under the right pipeline |
| 429 | rate_limit_exceeded | The key's request quota is exceeded | Space out sends at the source (the Retry-After header gives the delay) |
| 429 | rate_limited_ip | More than 100 requests per minute from the same IP address | Reduce the rate or contact support |
FAQ — common pitfalls
| Symptom | Cause |
|---|---|
| Platform test green (200 OK) but lead doesn't show up in pipeline | The same contact was already sent in the last 5 minutes — response status: idempotent_replay, no duplicate (tests often reuse the same number). If the contact already existed, it keeps its stage: see the "not in the right pipeline" entry below. |
| 415 "Unsupported Content-Type" or 400 "Body is not valid JSON" | 415: the tool sends a form (Payload Type set to Form, form-encoded Encoding) instead of JSON. 400: the JSON is malformed, often an extra comma or a missing quote around a variable. |
| 200 OK response but no SMS sent to lead | sms_consent: true but AI agent not configured, or SMS AI agent disabled, or no Twilio number provisioned for the client. |
| 200 OK response but the lead is not in the right pipeline or stage | Read ignored_fields in the response: it names every received field that was not applied. unknown_field: the field carries a name the API does not know (pipeline.id instead of pipeline.pipeline_slug, for instance). existing_contact_kept: the contact already existed and keeps its pipeline and stage. duplicate_field: the same field arrived twice (root and Custom Data, for instance) and the other value was kept. |
| Lead created without UTM tracking | Field sent under a name the API does not know (utm_source). Send the nested utm object or the flat key utm.source; ignored_fields names the field that was not applied. |
| 403 terms_acceptance_required after an update that used to work | A new version of the API terms of use must be accepted: the account owner accepts it in Capturia, on the API Keys page, and the key works again. |
| UTM lost despite mapping | The key does not carry a name the API knows (utm_source with a single underscore, for instance). Write utm.source (flat key), or utm__source with Unflatten = Yes. Capturia's response names the field that was not applied in ignored_fields. |