Guides & Tutorials11 min read

Build a Telegram to CRM Pipeline for Lead Generation with OpenClaw

By Riley Chen

TL;DR

This guide walks you through building a Telegram to CRM pipeline with OpenClaw. You will create a bot, secure the webhook with a secret header, map message fields to contact properties, and push new records into your CRM with retry logic and audits. The result is a reliable chat based intake that supports consent capture, enrichment, and monitoring. It is designed for teams that want fast setup without sacrificing security or data quality for lead generation. You will finish with a simple monitoring checklist.

What you will build

You will set up a Telegram bot that collects contact details through a structured chat flow and posts them to a CRM as new contacts. The OpenClaw playbook will accept Telegram webhook events, validate authenticity, transform input to a clean schema, upsert into HubSpot, and store a consent trail. The approach works with other CRMs too, because the HTTP request step abstracts the destination.

Why Telegram for intake

Telegram delivers a low friction chat surface that can capture interest the moment it appears. For marketing teams this is useful when a visitor discovers your community channel or a campaign drives traffic to a bot. With a webhook you can process messages in real time and route qualified conversations to sales, support, or automation.

For a deeper look at what the product can automate, see the overview of AI marketing automation features. If you are new to the platform, start with ButterGrow to understand how the hosted OpenClaw assistant works for go to market teams.

Architecture at a glance

  • Telegram bot receives a message such as "/start" or a command like "/lead".
  • Telegram sends an HTTPS POST to your OpenClaw webhook with a secret token header.
  • OpenClaw validates the secret, normalizes the payload, and runs policy checks.
  • A transform maps chat fields to CRM properties and builds an idempotency key.
  • An HTTP request upserts the contact and logs consent and attribution.

Here is a quick comparison of ways to receive updates from Telegram.

Approach Latency Reliability considerations Operational notes
Webhook to OpenClaw Low Requires HTTPS and header validation Best for production and observability
Long polling Medium Process restarts drop in flight updates Acceptable for prototypes only
Third party middleware Variable Adds another failure point and cost Useful when your CRM is not directly reachable

This tutorial is the practical answer to how to connect a Telegram bot to HubSpot using OpenClaw. If you came looking for a Telegram webhook to CRM tutorial, you can follow the steps below and adapt the destination to any system with an HTTP API.

Prerequisites

  • A Telegram account and a bot created via BotFather.
  • A stable HTTPS domain for your webhook endpoint.
  • An OpenClaw workspace with permission to create playbooks and secrets.
  • A HubSpot account with a Private App token that can create contacts.

Step by step build

Step 1Create a Telegram bot and note the token

  1. In Telegram, start a chat with BotFather and run /newbot to name your bot and receive the token. 2) Keep the token secure. You will store it as an OpenClaw secret. 3) Decide which commands you want to support. For this tutorial we will accept /start for a welcome flow and /lead to collect contact details.

Step 2Set the webhook with a secret token

Telegram supports a secret header on every webhook delivery. Generate a 32 character random value and pass it as secret_token when calling setWebhook. Telegram will include X-Telegram-Bot-Api-Secret-Token in each request. Your webhook must reject requests with a missing or mismatched header.

Use this call to set the webhook.

curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.yourdomain.com/hooks/telegram/<bot_username>",
    "secret_token": "<A_32_CHAR_RANDOM_VALUE>",
    "allowed_updates": ["message"]
  }'

For API details, see the official Telegram Bot API documentation and the setWebhook method reference.

Step 3Create secrets in OpenClaw

Add two secrets to your workspace.

  • TELEGRAM_SECRET_TOKEN equals the 32 character value you set above.
  • HUBSPOT_PRIVATE_APP_TOKEN equals your HubSpot Private App token.

You will reference both in the playbook with secrets.<NAME>.

Step 4Scaffold the OpenClaw playbook

Create a new playbook and add a webhook trigger that accepts Telegram events. The snippet below shows a minimal version you can paste into a new playbook. Adjust names to match your workspace conventions.

name: telegram-to-crm-intake
version: 1
triggers:
  - id: tg_webhook
    type: http_webhook
    config:
      method: POST
      path: /hooks/telegram/:bot
      auth: none
      rate_limit_per_minute: 600
      validation:
        headers:
          - name: X-Telegram-Bot-Api-Secret-Token
            operator: equals
            value: ${secrets.TELEGRAM_SECRET_TOKEN}
      schema:
        type: object
        required: [message]
        properties:
          update_id: { type: integer }
          message:
            type: object
            required: [chat, text, date]
            properties:
              message_id: { type: integer }
              date: { type: integer }
              text: { type: string }
              chat:
                type: object
                required: [id, type]
                properties:
                  id: { type: integer }
                  type: { type: string }
                  username: { type: string }
                  first_name: { type: string }
                  last_name: { type: string }

steps:
  - id: parse
    type: transform
    with:
      code: |
        const m = input.message || {};
        const text = (m.text || "").trim();
        const parts = text.split(/\s+/);
        const cmd = parts[0];
        const args = Object.fromEntries(parts.slice(1).map(p => {
          const [k, v] = p.split(":");
          return [k?.toLowerCase(), v];
        }));
        const email = args.email || "";
        const phone = args.phone || "";
        const source = args.source || "telegram";
        const chat = m.chat || {};
        const idempotency = `${chat.id}:${email || phone}`;
        return {
          cmd,
          email,
          phone,
          source,
          chat_id: chat.id,
          username: chat.username,
          first_name: chat.first_name,
          last_name: chat.last_name,
          idempotency
        };

  - id: guard
    type: policy
    with:
      rules:
        - if: "!output.parse.email && !output.parse.phone"
          then: "deny"
          reason: "missing contact handle"
        - if: "output.parse.cmd !== '/lead' && output.parse.cmd !== '/start'"
          then: "deny"
          reason: "unsupported command"

  - id: create_contact
    type: http_request
    with:
      url: https://api.hubapi.com/crm/v3/objects/contacts
      method: POST
      headers:
        Authorization: "Bearer ${secrets.HUBSPOT_PRIVATE_APP_TOKEN}"
        Content-Type: application/json
        Accept: application/json
        Idempotency-Key: "${output.parse.idempotency}"
      body:
        properties:
          email: "${output.parse.email}"
          phone: "${output.parse.phone}"
          firstname: "${output.parse.first_name}"
          lastname: "${output.parse.last_name}"
          hs_utm_source: "${output.parse.source}"
          tg_username: "${output.parse.username}"

  - id: consent_log
    type: data_log
    with:
      table: consent_events
      record:
        subject: "telegram:${output.parse.chat_id}"
        event: "opt_in"
        policy_version: "v1"
        timestamp: "${now()}"

on_error:
  - id: retry
    type: retry
    with:
      for: [create_contact]
      strategy: exponential
      max_attempts: 5
      min_backoff_ms: 500

This playbook exposes an HTTPS endpoint, validates the Telegram secret header, parses a simple command format, and upserts a contact in HubSpot. The Idempotency-Key header ensures repeated deliveries do not create duplicates.

Step 5Map fields and normalize input

You can guide users to provide contact details in a single message. A typical format is /lead email:ana@example.com phone:+14155550123 source:community. You can also switch the flow to a multistep chat and store intermediate state in OpenClaw if your use case needs progressive profiling.

If you need to add more properties, extend the transform and the request body. Keep field names consistent and convert phone numbers to E.164 format to reduce downstream errors.

Step 6Verify the secret header in code

If you prefer to add a code based check, you can verify the header in a custom step or an edge function. Here is a simple Node.js example that rejects requests that do not present the expected secret.

export default async function handler(req, res) {
  const expected = process.env.TELEGRAM_SECRET_TOKEN;
  const got = req.headers["x-telegram-bot-api-secret-token"] || "";
  if (!expected || got !== expected) {
    return res.status(401).json({ ok: false, error: "unauthorized" });
  }
  // continue processing
  res.status(204).end();
}

This endpoint logic mirrors the declarative header validation in the playbook. Use one path or the other to avoid double handling.

Step 7Create a HubSpot contact manually to test

Before wiring the transform to the live request, confirm your token works by creating a test contact with curl.

curl -X POST 'https://api.hubapi.com/crm/v3/objects/contacts' \
  -H 'Authorization: Bearer <HUBSPOT_PRIVATE_APP_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{
    "properties": {
      "email": "ana+test@example.com",
      "firstname": "Ana",
      "lastname": "Lead",
      "phone": "+14155550123",
      "hs_utm_source": "telegram"
    }
  }'

If you receive HTTP 201 your token and scope are valid. If you see HTTP 401 or 403, double check scopes and rotate the token if needed.

Step 8Test the end to end flow

Send a message to your bot like this.

/lead email:ana@example.com phone:+14155550123 source:community

Inspect the OpenClaw run. The transform step should extract fields, the policy step should allow the command, and the HTTP request should return HTTP 201 or 204. In the CRM, verify that properties are populated, including the username if available.

Even if you already record an opt in event, you often need a stronger trail. Add a prompt that asks the user to confirm marketing consent explicitly. Create a second data log step for consent updates and store the policy version and timestamp. Later, you can gate outbound campaigns on the latest event per subject.

For routing, consider adding a branch that sends a notification to Slack or email when the message contains target keywords. You can also use CRM workflows to assign owners based on region or product interest.

Step 10Harden for production

  • Enforce HTTPS and prefer a stable domain for the webhook URL.
  • Restrict allowed updates to only the message types you process.
  • Add IP allow listing if your edge supports it and document the ranges.
  • Turn on alerting and a dead letter queue for failed deliveries.
  • Track success, failure, and retry counts with a dashboard or logs.

Troubleshooting and common pitfalls

  • Webhook not firing. Verify that setWebhook returns ok true and that your endpoint returns HTTP 200 on a simple health check. Inspect OpenClaw logs for header validation failures.
  • Duplicate contacts. Ensure the idempotency key is stable and unique. Upsert on email in the CRM and handle retry side effects.
  • Missing properties. Confirm that your transform returns the expected fields and that property names match the CRM schema exactly.
  • Timeouts. Keep processing inside the webhook fast and move slow work to background jobs when needed.

Next steps

If you plan to automate downstream messaging, read our WhatsApp drip campaigns tutorial on OpenClaw for ideas on nurture flows and audience selection. For a broader view of the platform, browse AI marketing automation features and then explore more from the ButterGrow blog to see what other teams have shipped.

To follow this guide in your workspace, you can get started in minutes. The onboarding flow creates a sample project and shows how to set it up with a secure webhook and a first destination.

Building this with the hosted assistant keeps you focused on outcomes while we run the infrastructure. If you want hands on help, the answers to common questions in the FAQ are a good place to start.

References

Frequently Asked Questions

How do I verify Telegram webhook requests in OpenClaw?+

Set a secret_token when calling Telegram setWebhook and validate the X-Telegram-Bot-Api-Secret-Token header in your webhook step. Reject any request without an exact match and log the failure.

Which HubSpot permissions are required to create contacts from bot messages?+

Use a Private App token with crm.objects.contacts.write and crm.objects.contacts.read. Store the token in OpenClaw secrets, reference it from the HTTP request step, and never hardcode credentials in playbooks.

Can I capture UTM parameters or campaign codes in this flow?+

Yes. Extend the bot command to accept key value pairs or prompt the user for source and campaign, then map those fields to HubSpot properties like hs_utm_source and hs_utm_campaign in the transform step.

How do I prevent duplicate contacts when a user sends multiple messages?+

Create an idempotency key using the Telegram chat id and a normalized email or phone if present. In HubSpot requests, upsert on the email property and handle HTTP 409 or 204 responses gracefully to avoid duplicates.

What is the recommended approach for consent and opt out in Telegram?+

Treat consent as an event stream. Record explicit opt in and opt out events with timestamps and the policy version, store them in a durable log, and gate any outbound messaging on the latest consent state for that chat id.

How can I test this end to end without a public URL?+

Use a secure tunnel such as an HTTPS forwarding service to expose your local OpenClaw webhook endpoint. Point Telegram setWebhook at the tunnel URL during development and switch to a stable domain before launch.

Ready to try ButterGrow?

See how ButterGrow can supercharge your growth with a quick demo.

Book a Demo