
We’d love you to use LeadSync to send your Facebook leads wherever they need to go. But if you’re a developer integrating lead ads directly into your own app, you need the API, not a SaaS tool. This guide is for you.
It covers the whole build: webhook setup with working code, bulk lead retrieval through the Graph API, the current permissions list, rate limits, and the platform changes Meta shipped in 2025 and 2026 that most older guides (including the previous version of this one) missed.
Webhooks or Bulk Polling: Which Should You Use?
Use webhooks for real-time delivery and bulk reads as a backstop. Meta supports both, and they fail in different ways, which is exactly why production integrations usually run both.
| Webhooks | Bulk read (polling) | |
|---|---|---|
| Latency | Seconds | However often you poll |
| Build effort | Public HTTPS endpoint, verification handshake, App Review | A scheduled job and pagination handling |
| What you receive | A leadgen_id pointer (you fetch the lead separately) | Full lead objects as JSON |
| Failure mode | Silent. A dropped webhook just never arrives | Loud. A failed job errors and can be retried |
| Best for | Speed-to-lead, instant CRM sync, notifications | Backfill, reconciliation, low-urgency syncs |
The failure-mode row matters more than it looks. Webhook delivery can stop for reasons entirely outside your code: an expired token, a certificate change on Meta’s side, an app subscription that quietly dropped. Because leads expire after 90 days, a webhook-only integration that dies unnoticed doesn’t just delay leads, it loses them. We run this integration in production at LeadSync, and reconciliation polling has saved customer leads more than once.
What Is the Facebook Lead Ads API?

The Facebook Lead Ads API is the set of Graph API and Marketing API endpoints that let your app receive and read leads submitted through Facebook and Instagram instant forms. There’s no separate “Lead Gen API” product. It’s two pieces working together:
- A webhook subscription on the
leadgenfield of a Page, which notifies your server the moment someone submits a form. - Read endpoints that return the actual lead data (name, email, phone, custom answers) as JSON.
One thing that surprises most developers on their first build: the webhook does not contain the lead. It contains a leadgen_id. Your server has to make a second, authenticated call to fetch the field data. Plan for that round trip from the start.
What Permissions Does the Facebook Lead Ads API Need?
Meta’s leadgen webhooks documentation currently lists five required permissions:
| Permission | What it’s for |
|---|---|
leads_retrieval | Reading the lead data itself. The core permission |
pages_manage_metadata | Subscribing your app to the Page’s webhooks |
pages_show_list | Listing the Pages the user can grant you access to |
pages_read_engagement | Reading Page content your app interacts with |
ads_management | Accessing the ads and forms the leads come from |
Two notes from having taken an app through this process:
- App Review is mandatory for production access. Meta’s Lead Ads guide states your app must undergo App Review, with
leads_retrievalandpages_manage_adsin the submission. You’ll record a screencast demonstrating the lead flow end to end. Budget days to weeks, not hours, and expect at least one rejection asking for a clearer demo. - Check the docs, not old blog posts. The required list has changed over the years (the 2024 version of this very article cited only two permissions). Meta adjusts scopes at major versions, so verify against the current documentation before you submit for review.
You’ll also need a Page access token for the Pages you’re pulling leads from. Page tokens are the right choice here, both for scoping and because rate limits are calculated per Page.
How Do You Set Up Lead Ads Webhooks?

Four steps: verify an endpoint, configure the Webhooks product, subscribe the Page, then handle deliveries. Here’s each one with the code Meta’s docs describe, tested against v25.0.
Step 1: Build the verification endpoint
When you register a callback URL, Meta sends a GET request with hub.mode, hub.verify_token, and hub.challenge query parameters. Echo back the challenge if the token matches. In PHP (note that PHP converts the dots in parameter names to underscores, which trips up a lot of first attempts):
<?php
$verify_token = 'your-random-verify-token';
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// PHP renames hub.mode to hub_mode, etc.
if (($_GET['hub_mode'] ?? '') === 'subscribe'
&& ($_GET['hub_verify_token'] ?? '') === $verify_token) {
echo $_GET['hub_challenge'];
exit;
}
http_response_code(403);
exit;
}
// POST requests are webhook deliveries (handled in step 4)
The same handshake in Node/Express:
app.get('/webhook', (req, res) => {
if (req.query['hub.mode'] === 'subscribe'
&& req.query['hub.verify_token'] === process.env.VERIFY_TOKEN) {
return res.send(req.query['hub.challenge']);
}
res.sendStatus(403);
});
Step 2: Configure the Webhooks product
In your app’s dashboard, add the Webhooks product, choose the Page object, enter your callback URL and verify token, and subscribe to the leadgen field. The endpoint must be publicly reachable over HTTPS with a valid certificate.
Step 3: Install the app on the Page
Subscribing in the dashboard isn’t enough. The app must also be installed on each Page, done with a POST to the Page’s subscribed_apps edge using that Page’s access token:
curl -X POST "https://graph.facebook.com/v25.0/{page-id}/subscribed_apps" \
-d "subscribed_fields=leadgen" \
-d "access_token={page-access-token}"
This is the step integrations most often skip, and the symptom is maddening: verification succeeds, the dashboard looks right, and no webhooks ever arrive.
Step 4: Handle the delivery
A leadgen delivery looks like this:
{
"object": "page",
"entry": [
{
"id": "PAGE_ID",
"time": 1752105600,
"changes": [
{
"field": "leadgen",
"value": {
"leadgen_id": "444444444444",
"page_id": "111111111111",
"form_id": "222222222222",
"adgroup_id": "333333333333",
"ad_id": "333333333333",
"created_time": 1752105600
}
}
]
}
]
}
No lead data, just identifiers. Respond with a 200 quickly (queue the work, don’t process inline), then fetch the lead:
curl -G "https://graph.facebook.com/v25.0/{leadgen-id}" \
-d "fields=created_time,ad_id,form_id,field_data" \
-d "access_token={page-access-token}"
field_data is an array of question names and the user’s answers. Map each field explicitly to your own schema. Form questions vary per form, and custom questions arrive alongside the standard email and full name fields.
How Do You Retrieve Leads in Bulk via the Graph API?
Webhooks cover new leads. For backfill, reconciliation, or a simple scheduled sync, read leads in bulk from a form or an ad using the retrieval endpoints:
# All leads for a form
curl -G "https://graph.facebook.com/v25.0/{form-id}/leads" \
-d "fields=created_time,id,ad_id,form_id,field_data" \
-d "access_token={page-access-token}"
# All leads for a specific ad
curl -G "https://graph.facebook.com/v25.0/{ad-id}/leads" \
-d "fields=created_time,id,ad_id,form_id,field_data" \
-d "access_token={page-access-token}"
Responses are cursor-paginated. Follow paging.next (or the after cursor) until it’s absent, and don’t cache cursors between runs. To fetch only recent leads, filter on the creation timestamp with Unix times:
curl -G "https://graph.facebook.com/v25.0/{form-id}/leads" \
-d 'filtering=[{"field":"time_created","operator":"GREATER_THAN","value":1752019200}]' \
-d "fields=created_time,id,field_data" \
-d "access_token={page-access-token}"
If you’re a marketer looking for a one-off CSV rather than an API integration, that’s a different job. See our guide to getting your leads out of Meta’s interface instead, or manage them directly in the Leads Center.
What Are the Rate Limits?

Lead retrieval has its own rate limit, calculated per Facebook Page. Per Meta’s documentation: “The rate limit is 200 multiplied by 24 then multiplied by the number of leads created in the past 90 days for a Facebook Page.” That works out to 4,800 daily calls per lead generated in the trailing 90 days, so a Page with even modest lead volume has generous headroom. Exceed it within a 24-hour window and the API starts returning errors until the window rolls over.
Practical guidance:
- Use Page access tokens, not user tokens, so usage is attributed and scoped per Page.
- Batch bulk reads with the
fieldsparameter rather than making one call per lead. - Back off on errors. Retry with exponential backoff instead of hammering the endpoint, and alert yourself if throttling persists.
The limit rarely bites webhook-driven integrations, since each lead costs roughly one retrieval call. It bites aggressive pollers that re-read entire forms every few minutes.
What Changed in 2025 and 2026?
If you’re working from a guide written in 2024 (as most of the ones ranking for this topic still are), three things have moved:
Graph API v25.0 is current. Released 18 February 2026, per Meta’s changelog. v20.0, the version older tutorials reference, is available until 24 September 2026 and then stops working. Pin your integration to a recent version and diarise the deprecation dates; Meta ships two to three versions a year and each one eventually expires.
The mTLS certificate authority changed on 31 March 2026. Teams that verify Meta’s webhook deliveries with mutual TLS needed to trust Meta’s own CA certificate in place of the previous DigiCert-signed chain by that date. Servers that didn’t update their trust store stopped receiving webhooks entirely, with nothing but TLS handshake failures in the logs. If your webhook traffic went quiet around April 2026, check this first.
The 90-day window is a hard constraint. Lead data is available for 90 days from submission, per Meta’s Business Help Centre. After that it cannot be retrieved by any method. This is the single best argument for building retrieval automation properly: an integration that silently breaks for three months doesn’t delay your leads, it deletes them.
How Do You Test the Integration?
Use Meta’s Lead Ads Testing Tool to submit test leads against a real form without spending ad budget, then confirm the webhook arrives and the follow-up fetch returns the fields you expect. Delete the test lead in the tool before re-testing the same form, since it allows one test lead per form at a time. We’ve written a full walkthrough of testing Facebook lead ads covering the tool’s quirks and what to check at each stage.
Should You Build or Buy?

Building on the Lead Ads API is a genuinely reasonable choice when leads need to land inside your own product. The build itself is a few days of work. The part that surprises teams is the ownership cost afterwards, and we say this as a team that has run this exact integration in production for years:
- App Review recurs. New permissions, data-use checkups, and policy changes all trigger fresh review cycles.
- Versions expire on a schedule. Two to three Graph API releases a year, each with a deprecation date that eventually lands on your calendar.
- Platform changes arrive with deadlines, like the 2026 mTLS trust-store change above, and missing one silently stops your lead flow.
- Webhooks fail silently, so you need monitoring plus reconciliation polling to catch drops before the 90-day window erases them.
If the destination for your leads is a CRM, an inbox, or a phone rather than your own codebase, that maintenance load buys you nothing. LeadSync is the no-build path: connect your Facebook account, pick your destinations, and leads arrive in under 60 seconds via email, SMS, Slack, WhatsApp, or 30+ CRMs, as covered in our guide to connecting Facebook lead ads with CRMs. There’s even a webhook destination that POSTs each lead to your own URL, which gets you the real-time feed from this guide without the App Review, version upgrades, or certificate deadlines. You can try it free for 7 days, no credit card required.
Frequently Asked Questions
What permissions does the Facebook Lead Ads API require?
For leadgen webhooks, Meta’s documentation lists five permissions: leads_retrieval, pages_manage_metadata, pages_show_list, pages_read_engagement, and ads_management. Your app must be granted these through Meta App Review before it can read real lead data.
Do I need Meta App Review to retrieve leads?
Yes. Meta’s Lead Ads documentation states your app must undergo App Review, and your submission must include the leads_retrieval permission. You can develop and test against your own pages beforehand, but production access to lead data requires an approved app.
How long does Meta store lead data?
90 days from the time the lead is submitted. After that, the lead can no longer be retrieved through the API or from the Ads Manager interface, so your integration needs to run continuously rather than as an occasional batch job.
Should I use webhooks or polling to get leads?
Use webhooks as your primary delivery method because they push new leads to you within seconds. Add periodic bulk reads as a safety net, since a missed webhook is silent and leads expire after 90 days. Most production integrations run both.
What is the current version of the Facebook Lead Ads API?
Lead Ads endpoints are versioned with the Graph API. As of mid 2026 the current version is v25.0, released 18 February 2026. v20.0 is scheduled to stop working on 24 September 2026, so pin your calls to a recent version and review Meta’s changelog at each release.



