Skip to content

Lead delivery ​

This page is for the administrator, and for whoever writes the system that receives the leads. It covers the Lead delivery page of the management page.

With lead delivery on, a person can add a lead feed for a Facebook Page, a Google Ads account or a LinkedIn ad account. The server then looks for new leads every few minutes and sends them to one address that you set: your organisation's CRM or an automation tool. The server asks the platforms itself, so this works on an installation that has no public address. For the marketer's side, see Leads.

Contact data leaves the server by itself

A lead is a person's name and contact details. A lead feed sends them on with nobody asking at that moment. Switch this on only for an address that your organisation runs, and make sure your own privacy policy says so first. See the privacy policy and Contact data.

Switch it on ​

Everything here is off or empty on a new installation.

  1. Open Lead delivery.
  2. Under Lead webhook, type the address in Webhook URL, such as https://crm.example.com/hooks/leads.
  3. Type a Signing secret of at least 16 characters. Give the same secret to whoever runs the receiver.
  4. Tick Allow a private address only if the receiver is on the server's own machine or network. See The lead webhook.
  5. Under Pushing leads, tick Let lead feeds push leads to the webhook below.
  6. Press Save lead delivery.
  7. Press Send a test lead and read the answer. See Send a test lead.

It takes effect at once. The switch cannot be saved on without an address and a secret.

Two more things have to be true before a person can add a feed:

  • The platform's own switch for reading leads is on. It is on Meta app, LinkedIn app or Safety limits: see Leads.
  • The person has write access, and their connection holds the platform's permission.

All of it is checked again every time a feed looks.

SettingStarts atWhat it does
Let lead feeds push leads to the webhook belowOffOff, no feed can be added and none is read. Feeds that were already added wait, and start again with the leads that arrived meanwhile once it is back on.
A feed looks every (minutes)5How often each feed asks the platform for new leads. 2 is the least.
Feeds one person may have10Empty means no limit.
Webhook URLEmptyThe one address that leads are sent to.
Signing secretEmptySigns every body. Required.
Allow a private addressOffLets the address be on the server's own network.

Every look costs calls on the feed owner's own connection: a listing of the forms, and a call for each form that has leads. For Google it is one query for the account. Keep that in mind before you lower the minutes or raise the number of feeds.

The same settings can be given as environment variables: see Settings.

The lead webhook ​

There is one address for the whole installation, and only this page (or the environment) can set it. No AI client, no tool and no feed can name another. A feed says which leads; it never says where to.

The rules for the address:

  • It must start with https://. Plain http:// is accepted only for the server's own machine (localhost).
  • It must be a public address, unless Allow a private address is ticked. Before anything is sent, the server looks the name up, checks that every address it leads to is public, and connects to exactly the address that it checked.
  • With Allow a private address ticked, the address is not judged. Use it for a CRM or an automation tool on the same machine or network. HTTPS is still required unless it is the machine itself.
  • A redirect is never followed. Save the address where the receiver finally lives.
  • Proxy settings from the server's environment are not used for this connection.

The secret is shown only while you type it. Afterwards the page says only that one is set. Leave the field empty to keep it; type a new one to replace it. Remove the signing secret stops every feed, because nothing is ever sent unsigned.

What the receiver gets ​

A POST with Content-Type: application/json, with at most 100 leads in one body:

json
{
  "kind": "leads",
  "delivery_id": "0f6c1a...",
  "sent_at": "2026-10-08T09:15:00+00:00",
  "test": false,
  "feed": {"id": 3, "platform": "meta", "source_id": "100000000000000"},
  "count": 1,
  "leads": [{
    "key": "meta:1234567890123456",
    "platform": "meta",
    "lead_id": "1234567890123456",
    "created_at": "2026-10-08T09:12:41+00:00",
    "form_id": "5551",
    "form_name": "Acme demo",
    "campaign_id": "501",
    "campaign_name": "Leads KW",
    "ad_id": "9001",
    "ad_name": "Demo ad",
    "fields": {"full_name": "...", "phone": "...", "email": "..."},
    "custom": [{"question": "...", "answer": "..."}],
    "click_id": null,
    "test": false
  }]
}
PartWhat it is
delivery_idNew for every request, also when the same leads are sent again.
feedWhich feed sent it: its number, the platform, and the Page or account id.
keyplatform:lead_id. The same on every send of that lead.
fieldsThe usual answers under one name on every platform: email, work_email, phone, full_name, first_name, last_name, company, job_title, city, state, country, zip and a few more.
customAny other question the form asked, with its question.
click_idGoogle's click id, for a Google lead.
testTrue on the body for Send a test lead. True on a lead for the test lead, and for a LinkedIn test lead in a real delivery.

A lead has the same shape that an export gives: see Leads.

Verify the signature ​

Every body is signed. The header X-Nama-Signature holds sha256= followed by the HMAC-SHA256 of the body with the signing secret, in hexadecimal.

The receiver must:

  1. Take the body as the raw bytes that arrived, before parsing the JSON.
  2. Compute the HMAC-SHA256 of those bytes with the secret.
  3. Compare it with the header, and drop the body when they differ.

In Python, for example:

python
import hashlib
import hmac

def came_from_marketing_mcp(secret: str, raw_body: bytes, header: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header)

TIP

Compute the signature over the bytes exactly as received. A body that was parsed and written out again will not match.

The receiver must accept a lead twice ​

Delivery is at least once. A lead can arrive more than once; a lead is never dropped while the platform still holds it.

  • Only an answer in the 200s counts as taken. An error, a timeout or a redirect all count as not taken.
  • Nothing is kept on the server to send again. After a failure, the same leads are read from the platform at a later look and sent again, under a new delivery_id.
  • Store by key. It is the same on every send, so a repeat then changes nothing.
  • Answer within 10 seconds. Do slow work after answering.
  • A form with many new leads arrives over several requests. On Meta the newest come first.

Send a test lead ​

Send a test lead sends one plainly fake lead to the address that is saved, not to what is typed in the fields, so save first. It goes through the same checks and carries the same signature as a real delivery. It reads no platform.

The test lead has test true on the body and on the lead, and platform is test. A receiver should drop it.

The page then shows one of:

  • Taken, with the status that the receiver answered.
  • Failed, with the reason: the address could not be reached, it answered with a redirect, or it answered with an error.
  • Not set up, when no address is saved.

When the receiver is down ​

  • Nothing is marked as sent. The server keeps no copy of the leads.
  • The feed keeps trying, less often while it fails: the wait doubles, up to an hour apart.
  • The feed's owner gets one notification for the outage, not one for each try. It comes at once when the server may no longer read the leads (the owner was disabled, lost write access or the connection, or a switch was closed), and on the second failure in a row when the receiver or the platform does not answer.
  • Lead feeds on the owner's History page marks the feed Failing, with the reason.
  • Once it works again, everything that the platform still holds is sent. Meta and LinkedIn keep leads; Google keeps them for 60 days.

What is stored and logged ​

  • Nothing of a lead is stored. For each feed and form the server keeps a time and the ids of the leads of that moment, to know where to go on. It moves that mark only after the receiver answered in the 200s.
  • The activity log keeps one row for each delivery: the feed, the forms, how many leads and the status. It also keeps the platform's usual row for a read that brought a new lead. A look that finds nothing new writes nothing. See Activity log.
  • The webhook address and the secret are in no activity row and no answer to an AI client.
  • A feed, and how far it has sent, is deleted when its owner disconnects that platform or their user is deleted.