Skip to main content
Naturalead uses inbound webhooks to receive leads from external systems and messages from messaging channels. Each webhook type has its own authentication mechanism and setup process.

Lead Webhooks

Token-based authentication. Push leads from any CRM or form tool into Naturalead.

WhatsApp (Meta)

HMAC-SHA256 signature verification via the Meta Cloud API.

Telegram

Registered as a Telegram bot webhook URL via BotFather.

Email (Resend)

Inbound email events from Resend with conversation threading.

Lead inbound webhook

The lead webhook lets you push leads into Naturalead from any external system (CRM, landing page, form builder, etc.) without API key authentication. Each account has a unique webhook token.
1
Find your webhook token
2
Your webhook token is available in the account settings. It is unique per account.
3
curl
# Get your account details (includes webhookToken)
curl "${API_URL}/api/accounts/current" \
  -H "X-API-Key: ${API_KEY}"
4
Send leads to the webhook
5
Post a JSON body with lead data to the webhook URL. The only required field is phone.
6
curl
curl -X POST "${API_URL}/api/webhooks/leads/${WEBHOOK_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Doe",
    "phone": "+1234567890",
    "email": "[email protected]",
    "tags": ["website", "high-intent"],
    "company": "Acme Corp",
    "source_page": "/pricing"
  }'
Python
import requests

webhook_url = f"{API_URL}/api/webhooks/leads/{WEBHOOK_TOKEN}"

lead = {
    "name": "Jane Doe",
    "phone": "+1234567890",
    "email": "[email protected]",
    "tags": ["website", "high-intent"],
    "company": "Acme Corp",
    "source_page": "/pricing",
}

response = requests.post(webhook_url, json=lead)
data = response.json()

if data["created"]:
    print(f"New lead created: {data['leadId']}")
else:
    print(f"Lead already exists: {data['leadId']}")
Node.js
const webhookUrl = `${API_URL}/api/webhooks/leads/${WEBHOOK_TOKEN}`;

const response = await fetch(webhookUrl, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "Jane Doe",
    phone: "+1234567890",
    email: "[email protected]",
    tags: ["website", "high-intent"],
    company: "Acme Corp",
    source_page: "/pricing",
  }),
});

const data = await response.json();
console.log(data.created ? `New lead: ${data.leadId}` : `Existing lead: ${data.leadId}`);
7
Leads are deduplicated by phone number. If a lead with the same phone already exists, the webhook returns 201 with created: false and the existing lead ID. Any additional string fields beyond name, phone, email, and tags are stored as custom fields.
8
Handle the response
9
StatusMeaning201New lead created200Lead already exists (deduplicated)400Validation error (e.g. missing phone)401Invalid webhook token

WhatsApp webhook (Meta Cloud API)

The WhatsApp integration uses the Meta Cloud API. You need to configure your WABA (WhatsApp Business Account) in the Meta Developer Portal and point the webhook to Naturalead.
1
Set environment variables
2
Configure these environment variables on the Naturalead backend:
3
VariableDescriptionMETA_WEBHOOK_VERIFY_TOKENA secret string you choose for webhook verificationFB_APP_SECRETYour Facebook App Secret (used for signature verification)FB_APP_IDYour Facebook App ID
4
Register the webhook URL in Meta
5
In the Meta Developer Portal, navigate to your app’s WhatsApp configuration and set the webhook URL:
6
https://your-api-domain.com/api/webhooks/meta-whatsapp
7
Enter the same verify token you set in META_WEBHOOK_VERIFY_TOKEN. Meta will send a GET request with a challenge that Naturalead echoes back to complete verification.
8
Signature verification
9
Every inbound POST from Meta includes an X-Hub-Signature-256 header containing an HMAC-SHA256 hash of the request body, signed with your FB_APP_SECRET.
10
Naturalead validates this signature automatically. Here is how the verification works internally:
11
const crypto = require("crypto");

function validateSignature(rawBody, signature, appSecret) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", appSecret).update(rawBody).digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
12
If FB_APP_SECRET is not configured, signature validation is skipped (development mode only). Always set it in production.
13
Connect your WABA
14
After the webhook is verified, connect your WhatsApp Business Account through the Naturalead dashboard settings page. The integration stores your WABA ID, phone number ID, and access token for sending outbound messages.
The WhatsApp webhook always returns HTTP 200, even on errors. This is required by Meta — non-200 responses cause Meta to retry with exponential backoff and eventually disable the webhook.

Telegram webhook

The Telegram integration uses a bot token from BotFather. Naturalead registers itself as the bot’s webhook endpoint.
1
Create a Telegram bot
2
  • Open Telegram and message @BotFather
  • Send /newbot and follow the prompts
  • Copy the bot token (e.g. 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
  • 3
    Configure in Naturalead
    4
    curl
    curl -X PUT "${API_URL}/api/integrations/telegram" \
      -H "X-API-Key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d '{ "telegramBotToken": "123456789:ABCdefGHIjklMNOpqrsTUVwxyz" }'
    
    Python
    response = requests.put(
        f"{API_URL}/api/integrations/telegram",
        headers={
            "X-API-Key": API_KEY,
            "Content-Type": "application/json",
        },
        json={"telegramBotToken": "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"},
    )
    
    data = response.json()
    print(f"Bot configured: @{data['botUsername']}")
    
    Node.js
    const response = await fetch(`${API_URL}/api/integrations/telegram`, {
      method: "PUT",
      headers: {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        telegramBotToken: "123456789:ABCdefGHIjklMNOpqrsTUVwxyz",
      }),
    });
    
    const data = await response.json();
    console.log(`Bot configured: @${data.botUsername}`);
    
    5
    Naturalead verifies the token by calling the Telegram getMe API. If valid, the token is saved and the webhook URL is:
    6
    https://your-api-domain.com/api/webhooks/telegram
    
    7
    Register the webhook with Telegram
    8
    Set the webhook URL using the Telegram Bot API:
    9
    curl "https://api.telegram.org/bot${BOT_TOKEN}/setWebhook?url=https://your-api-domain.com/api/webhooks/telegram"
    
    10
    How it works
    11
    When a user sends a text message to the bot, Telegram posts an Update object to the webhook. Naturalead:
    12
  • Parses the inbound message (non-text messages are ignored)
  • Looks up the account by matching the stored bot token
  • Routes the message to the conversation engine for LLM processing
  • Sends the AI response back through the Telegram bot

  • Email webhook (Resend)

    The email integration uses Resend for both sending and receiving emails. Inbound emails are received via Resend webhook events.
    1
    Configure email sending
    2
    First, set up your sending email address and verify the domain:
    3
    curl
    # Step 1: Configure the from address
    curl -X PUT "${API_URL}/api/integrations/email" \
      -H "X-API-Key: ${API_KEY}" \
      -H "Content-Type: application/json" \
      -d '{
        "emailFromAddress": "[email protected]",
        "emailFromName": "Naturalead Bot"
      }'
    
    # Step 2: Add the DNS records returned in the response
    
    # Step 3: Verify the domain
    curl -X POST "${API_URL}/api/integrations/email/verify" \
      -H "X-API-Key: ${API_KEY}"
    
    4
    The configure endpoint returns DNS records (SPF, DKIM, etc.) that must be added to your domain before verification will pass.
    5
    Set up Resend inbound webhook
    6
  • In the Resend dashboard, go to Webhooks
  • Create a new webhook pointing to: https://your-api-domain.com/api/webhooks/email
  • Subscribe to the email.received event
  • 7
    Configure the receiving domain
    8
    Set the RESEND_RECEIVING_DOMAIN environment variable to your inbound email domain. Naturalead uses the pattern reply+{conversationId}@{domain} for email threading, allowing it to match inbound replies to the correct conversation.
    9
    How email threading works
    10
  • When Naturalead sends an outbound email, it sets the reply-to address to reply+{conversationId}@{domain}
  • When the lead replies, the email is routed to the Resend webhook
  • Naturalead extracts the conversation ID from the to address
  • The full email content is fetched from the Resend API
  • The message is routed to the conversation engine

  • Webhook token management

    Each Naturalead account has a unique webhookToken generated at account creation. This token is used exclusively for the lead inbound webhook and is separate from API keys.
    • The webhook token is visible via GET /api/accounts/current (requires account:view permission)
    • Webhook tokens do not expire — if compromised, contact support to regenerate
    • All leads created via webhook are logged to the audit trail with source: "webhook"

    Troubleshooting

    ProblemSolution
    Lead webhook returns 401Check that the token in the URL matches your account’s webhookToken
    WhatsApp messages not arrivingVerify the webhook URL is registered in Meta Developer Portal and the META_WEBHOOK_VERIFY_TOKEN matches
    WhatsApp signature validation failsEnsure FB_APP_SECRET is set correctly and the raw request body is preserved
    Telegram bot not respondingRun getWebhookInfo to confirm the URL is registered: curl https://api.telegram.org/bot${BOT_TOKEN}/getWebhookInfo
    Email replies not detectedCheck that RESEND_RECEIVING_DOMAIN matches your domain and DNS records are verified
    Email content is emptyVerify the Resend webhook is subscribed to email.received events and RESEND_API_KEY is set