ChatGPTSalesFinding leadsAI score · PendingAI-assisted edit · no obvious prompt-injection riskn8n.io

Telegram Voice or Text Triggers Apollo Lead Scraping, Parsed by GPT-4, Stored in Supabase

Input: Telegram voice/text command → Process: Whisper transcription + GPT parameter extraction → Apify Apollo Scraper → verify and deduplicate → Output: Supabase new leads table + Telegram receipt

ExperiencedStepsWorkflowPrompt
Who
Growth hackers, SDR teams, and founders who want to collect and organize prospect leads via Telegram voice or text commands
You get
Turn natural-language commands into verified, deduplicated structured leads written directly to a Supabase database, with a Telegram count confirmation
You need
n8n · telegram · apify · supabase · postgres

Constraints

Requires n8n v0.231+ (self-hosted or Cloud), Telegram Bot Token, OpenAI API Key, Apify account with Apollo-io Scraper Actor, and Supabase project credentials (or swap for Airtable/Sheets). Credential types: telegramApi, openAiApi, apifyApi, postgres. The workflow.json can be imported directly into n8n.

What they did

Author diagopl published an official n8n template (2025-07-02) demonstrating how to receive voice or text commands via Telegram Bot, use OpenAI Whisper and GPT-4.1-nano to parse search parameters (location, industry, job title), generate an Apollo.io search URL via a Code node, call the Apify Apollo-io Scraper Actor to fetch up to 500 contacts, filter for verified emails only, deduplicate against an existing Postgres table, insert fresh leads into a Supabase table named Leads_n-mail, and return the new count via Telegram. The template includes sticky notes explaining target users, setup steps, customization options, and required credentials.

How it went

The author reports the flow achieves 'voice-to-database in under 30 seconds', '95%+ verified email addresses', '500+ leads per request', and '100% hands-free operation'. These are author-reported claims (author_report) and have not been verified by this site.

Worth knowing

1. The Confirmation message text mentions 'Google Sheet', but data is actually written to the Supabase table Leads_n-mail—this is legacy wording in the template that users should correct. 2. The chatId is hardcoded as 123456789 and must be replaced. 3. The Apify token may be hardcoded in the template and should be moved to an environment variable. 4. The Keep only the new leads node has mergeByFields set to an empty object {}, so deduplication matching may not work correctly on emailAddress and requires user correction. 5. The Create rows with new leads node does not map seniority and Number fields, which is inconsistent with the sticky-notes table schema. 6. The businessIndustry field expression references a nonexistent node 'Apollo Scraper' (actual node is 'Run an Actor') and will evaluate to null; this must be corrected. 7. No runtime logs or actual scraped samples are provided by the source; data-quality claims (95% verified) are author-reported only. 8. If Apollo Scraper Actor parameters or Apify pricing change, availability may be affected. 9. The storage target can be swapped for Airtable, Google Sheets, or HubSpot, but node reconfiguration is required.

n8n workflow template

Structure checked · Not run-tested

Use “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.

Setup and test checklist

Credentials to connect

  • Download File1 node: connect Telegram API credentials.
  • Transcribe1 node: connect OpenAI API credentials.
  • OpenAI Chat Model1 node: connect OpenAI API credentials.
  • Select already scraped mails node: connect Postgres credentials.
  • Confirmation message node: connect Telegram API credentials.
  • User message node: connect Telegram API credentials.
  • Run an Actor node: connect apifyApi credentials.

Configuration to replace

  • Source template is n8n public workflow #5611 (~28 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
  • Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.

Test input and expected output

  • Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
  • Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.

Template changes

  • Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
  • No business-logic edits; verify keys, quotas and privacy compliance before use.

Template retrieved: 2026-10-24

Steps

  1. Set up Telegram trigger and receive voice or text messages

    After importing the workflow into n8n, confirm the Telegram Trigger node (User message) is configured with a Bot Token. Send a text message or voice message to the bot. For voice, the flow routes through the Download File node to fetch the audio; for text, it proceeds directly.

  2. Transcribe voice with Whisper and extract structured search parameters via GPT

    Voice messages are transcribed by the OpenAI Whisper node (Transcribe1); text messages pass through directly. Then the AI Agent node (Scraper agent) uses the GPT-4.1-nano model, following its systemMessage, to parse natural-language instructions into a fixed-format JSON array. The JSON contains location, business, and job_title fields, with values in lowercase and spaces replaced by plus signs. The Structured Output Parser node enforces the output format; Simple Memory provides conversation context. The Generate query payload node wraps the JSON as {"query": {{ $json.output }}}.

    Execution prompt · Source text。Scraper agent node's systemMessage field (AI Agent node → Options → System Message)

    =# Role
    You are LeadChat. Your single job is to return a **JSON array of one object** that tells the sub-workflow what to scrape.
    
    # Required JSON schema
    ```json
    [
      {
        "location": ["city+country"],      // lowercase, spaces→+
        "business": ["industry"],          // lowercase, words→+
        "job_title": ["role"]              // lowercase, words→+
      }
    ]
  3. Generate Apollo search URL and call Apify Scraper to fetch leads

    The Create URL node (Code node) reads the {"query": ...} structure and builds an Apollo.io people-search URL with parameters including personTitles[], personLocations[], qOrganizationKeywordTags[], etc. Then the Run an Actor node calls the Apify Apollo-io Scraper Actor (ID: jljBwyyQakqrL1wae), passing the generated URL with totalRecords=500, getPersonalEmails=true, getWorkEmails=true, timeout=10000, waitForFinish=60.

    Execution prompt · Source text。Create URL node's JS Code field (Code node → JavaScript)

    /************************************************************
     * Build Apollo People-search URL from parser output
     * Handles both shapes:
     *   { query: [ { … } ] }      ← array
     *   { query: { … } }          ← object
     ************************************************************/
    
    // 1. Obtener el JSON que llega del nodo anterior
    const inputData = $json;
    
    // 2. Normalizar para que paramsData siempre sea un objeto
    let paramsData;
    
    if (Array.isArray(inputData.query)) {
      // Caso antiguo: query es un array
      paramsData = inputData.query[0];
    } else if (inputData.query) {
      // Caso nuevo: query es un objeto
      paramsData = inputData.query;
    } else {
      throw new Error('Falta la propiedad "query" en el input');
    }
    
    // 3. URL base de Apollo (interfaz web)
    //    Para llamar a la API REST cambia a https://api.apollo.io/v1/mixed_people/search
    const baseURL = 'https://app.apollo.io/#/people';
    
    // 4. Construir los parámetros dinámicos
    const queryParts = [
      'sortByField=recommendations_score',
      'sortAscending=false',
      'page=1',
    ];
    
    // Helper para arrays → personTitles[]=ceo
    const addArrayParams = (paramName, values) => {
      values.forEach((val) => {
        const decoded = val.replace(/\+/g, ' ');          // “barcelona+spain” ⇒ “barcelona spain”
        queryParts.push(`${paramName}[]=${encodeURIComponent(decoded)}`);
      });
    };
    
    // job_title → personTitles[]
    if (Array.isArray(paramsData.job_title)) {
      addArrayParams('personTitles', paramsData.job_title);
    }
    
    // location → personLocations[]
    if (Array.isArray(paramsData.location)) {
      addArrayParams('personLocations', paramsData.location);
    }
    
    // business → qOrganizationKeywordTags[]
    if (Array.isArray(paramsData.business)) {
      addArrayParams('qOrganizationKeywordTags', paramsData.business);
    }
    
    // campos estáticos
    queryParts.push('includedOrganizationKeywordFields[]=tags');
    queryParts.push('includedOrganizationKeywordFields[]=name');
    
    // 5. Montar la URL final
    const finalURL = `${baseURL}?${queryParts.join('&')}`;
    
    // 6. Devolver resultado
    return [{ json: { finalURL } }];
  4. Extract fields, filter verified emails only, and deduplicate against existing records

    Data returned by Apify is mapped to unified fields by the Extract Info node: firstName, lastName, emailAddress, linkedInURL, jobTitle, companyName, location, country, websiteURL, businessIndustry, seniority, Number, emailStatus. The Only Keep Verified Emails node filters for entries where emailStatus='verified'. The Select already scraped mails node reads existing emailAddress values from the Postgres Leads_n-mail table. The Keep only the new leads node (Compare Datasets) has mergeByFields set to an empty object {} in the template, so the deduplication matching logic may not work as intended and requires user correction.

  5. Insert new leads into Supabase database

    The Create rows with new leads node (Supabase) writes deduplicated new leads into the Leads_n-mail table. Field mappings use variables from the previous step. Note: the businessIndustry field expression references a nonexistent node 'Apollo Scraper' (actual node name is 'Run an Actor'), so this expression will evaluate to null and requires user correction. Also, the template sticky-notes declare columns including seniority and number, but the insert node does not map these fields, which is another template defect. You must create the corresponding columns in Supabase beforehand.

  6. Limit count and send confirmation via Telegram

    The Limit node controls the final receipt volume. The Set Telegram message node constructs the text. The Confirmation message node (Telegram) sends this to the specified chatId. Note: the template hardcodes chatId as 123456789, which must be replaced; the message text refers to 'Google Sheet' as legacy wording, while data is actually written to the Supabase table.

    Execution prompt · Source text。Confirmation message node's Text field (Telegram node → Message → Text) and Set Telegram message node's assignments[0].value

    ={{ $input.all().length }} new contacts have been added to the Google Sheet!

Prompt you can copy

Setup guidance · Editorial suggestion。Hand to setup assistant; confirm inputs and permissions first

This block is the prompt. Ads are never placed here.

You are an n8n workflow setup assistant. The user wants to replicate a Telegram-driven AI lead-scraping flow. Assist in this order: 1) Confirm the user has an n8n instance and required credentials (Telegram Bot Token, OpenAI API Key, Apify API Token, Supabase/Postgres credentials); 2) Guide importing workflow.json; 3) Check credential configuration node by node, especially Apollo Scraper Actor parameters and Supabase table name; 4) Remind the user to fix template defects: complete the Keep only the new leads mergeByFields, correct the businessIndustry node reference, and add seniority/number field mappings; 5) Suggest testing with a text message first, then a voice message; 6) Remind the user to replace hardcoded chatId and Apify token with environment variables or credential references.

Before building, confirm all API credentials are configured and create the Leads_n-mail table with corresponding columns in Supabase. Pay special attention to fixing the missing mergeByFields and incorrect node reference in the template.

Source

AI-powered lead generation with Apollo, GPT-4, and Telegram to database · diagopl · n8n.io · 2025-07-02

Comments & feedback

Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.

Loading…

    Related