This workflow corresponds to n8n.io template #13910 — we link there as the canonical source.
This workflow follows the Agent → OpenRouter Chat recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "z57chhZkWbOpBs5n",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Enrich leads with Firecrawl and store in Supabase",
"tags": [],
"nodes": [
{
"id": "82e8b97a-c916-41b0-b273-7fc8c31ab167",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-320
],
"parameters": {
"color": 7,
"width": 464,
"height": 112,
"content": "## Supabase setup\nRun the SQL migration from the workflow README to create the `lead_enrichment` table with auto-updating timestamps."
},
"typeVersion": 1
},
{
"id": "9ca4cd14-9fb6-4eb4-b48c-8d5b108da22f",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-480,
-512
],
"parameters": {
"width": 384,
"height": 560,
"content": "### How it works\n1. A webhook receives a company URL via POST request\n2. The URL is validated and normalized\n3. Firecrawl scrapes the website and searches for additional company data\n4. An AI agent (OpenRouter) extracts structured business signals: industry, pricing, tech stack, funding stage, hiring status, and more\n5. Supabase checks for duplicates, then saves the enriched profile\n6. The webhook returns the enriched result or a validation error\n\n### Setup\n1. Create a Supabase project and run the SQL from the \"Supabase setup\" sticky to create the `lead_enrichment` table\n2. Add your Firecrawl API key\n3. Add your OpenRouter API key (or swap for any OpenAI-compatible provider)\n4. Add your Supabase credentials (URL + service role key)\n5. Activate the workflow and send a POST request with `{\"url\": \"firecrawl.dev\"}` to the webhook"
},
"typeVersion": 1
},
{
"id": "62943a2f-b3c2-49f0-82c3-c53a0db40024",
"name": "Receive company URL",
"type": "n8n-nodes-base.webhook",
"position": [
-464,
96
],
"parameters": {
"path": "dedaa64a-3dc9-43ea-82ac-7fac034af0b2",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "4c7ca918-834c-4954-90ca-342757ed032e",
"name": "Validate and normalize URL",
"type": "n8n-nodes-base.code",
"onError": "continueErrorOutput",
"position": [
-240,
96
],
"parameters": {
"jsCode": "const body = $input.first().json.body;\nconst raw = body?.url?.trim();\n\nif (!raw) {\n return [{\n json: {\n status: 422,\n message: \"Missing 'url' field in request body.\"\n }\n }];\n}\n\n// Strip protocol and path to get clean domain\nconst domain = raw.replace(/^https?:\\/\\//i, \"\").replace(/\\/.*$/, \"\");\n\n// Validate domain format\nconst isValid = /^[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z]{2,})+$/.test(domain);\n\nif (!isValid) {\n throw new Error(`Invalid URL: \"${raw}\" is not a valid domain or URL.`);\n}\nreturn [{\n json: {\n status: 200,\n domain: domain,\n url: `https://${domain}`\n }\n}];"
},
"typeVersion": 2
},
{
"id": "9dd6f876-e97b-4d57-9c32-af4809e73d44",
"name": "Extract business signals with AI",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
112,
-160
],
"parameters": {
"text": "=url: {{ $json.url }}",
"options": {
"systemMessage": "You will receive a url, and should use firecrawl's tools to extract some of the business's signals. (Only use the search tool if you need more context). Then output structured data. Example:\n\n{\n \"domain\": \"acme.io\",\n \"company_name\": \"Acme\",\n \"industry\": \"HR Tech\",\n \"pricing_model\": \"subscription\",\n \"has_free_trial\": true,\n \"employee_signal\": \"50-200\",\n \"funding_stage\": \"Series A\",\n \"tech_stack\": [\"AWS\", \"Stripe\", \"Intercom\"],\n \"integrations\": [\"Slack\", \"BambooHR\", \"Workday\"],\n \"target_customer\": \"mid-market HR teams\",\n \"trust_signals\": [\"SOC 2\", \"500+ customers\", \"4.8 on G2\"],\n \"hiring\": true,\n \"open_roles_count\": 12\n}"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 3.1
},
{
"id": "48741495-021d-408a-8b79-7cb490d7f131",
"name": "OpenRouter LLM",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"position": [
-16,
64
],
"parameters": {
"model": "anthropic/claude-sonnet-4.6",
"options": {}
},
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "fa0674b2-3f3f-45d7-b0e1-02db4e267d8f",
"name": "Scrape company website",
"type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
"position": [
144,
64
],
"parameters": {
"url": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('URL', ``, 'string') }}",
"parsers": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Parsers', ``, 'string') }}",
"operation": "scrape",
"requestOptions": {}
},
"credentials": {
"firecrawlApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "9701d370-aadc-4c39-b546-4224a49431f7",
"name": "Search company data",
"type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
"position": [
320,
64
],
"parameters": {
"limit": 3,
"query": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Query', ``, 'string') }}",
"sources": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Sources', ``, 'string') }}",
"resource": "MapSearch",
"operation": "search",
"requestOptions": {}
},
"credentials": {
"firecrawlApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "427e93e2-595a-481f-83fe-749809eeb604",
"name": "Parse into structured profile",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
480,
64
],
"parameters": {
"jsonSchemaExample": "{\n \"domain\": \"acme.io\",\n \"company_name\": \"Acme\",\n \"industry\": \"HR Tech\",\n \"pricing_model\": \"subscription\",\n \"has_free_trial\": true,\n \"employee_signal\": \"50-200\",\n \"funding_stage\": \"Series A\",\n \"tech_stack\": [\"AWS\", \"Stripe\", \"Intercom\"],\n \"integrations\": [\"Slack\", \"BambooHR\", \"Workday\"],\n \"target_customer\": \"mid-market HR teams\",\n \"trust_signals\": [\"SOC 2\", \"500+ customers\", \"4.8 on G2\"],\n \"hiring\": true,\n \"open_roles_count\": 12\n}"
},
"typeVersion": 1.3
},
{
"id": "daccc2ad-5283-4c13-947a-640d2013718e",
"name": "Check for duplicate in Supabase",
"type": "n8n-nodes-base.supabase",
"position": [
576,
-64
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "domain",
"keyValue": "={{ $json.output.domain }}"
}
]
},
"tableId": "lead_enrichment",
"operation": "get"
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "9d7822f4-441d-4d0a-b92f-f114567a00e2",
"name": "Skip if already enriched",
"type": "n8n-nodes-base.if",
"position": [
800,
-64
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "fc4c27fb-9647-4457-a19b-2737a50dfb9f",
"operator": {
"type": "object",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{$input.all()[0].json}}",
"rightValue": "1"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "9cf3219c-b671-40b4-be38-696e97c60d98",
"name": "Prepare profile for insert",
"type": "n8n-nodes-base.code",
"position": [
1056,
48
],
"parameters": {
"jsCode": "return $('Extract business signals with AI').all().map(item => ({\n json: item.json.output\n}));"
},
"typeVersion": 2
},
{
"id": "5a1823a8-0293-4571-b577-6c32257afa18",
"name": "Save enriched profile to Supabase",
"type": "n8n-nodes-base.supabase",
"position": [
1232,
48
],
"parameters": {
"tableId": "lead_enrichment",
"dataToSend": "autoMapInputData"
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b72fa969-c647-41b4-9789-7a39aa5affc3",
"name": "Return enriched profile",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1424,
-80
],
"parameters": {
"options": {
"responseKey": "={{ $('Extract business signals with AI').item.json }}",
"responseCode": 200
}
},
"typeVersion": 1.5
},
{
"id": "daca8e6b-8ad3-4850-a76e-7a39bd515e2e",
"name": "Return URL validation error",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
176,
240
],
"parameters": {
"options": {
"responseKey": "={{ $json.error }}",
"responseCode": 422
}
},
"typeVersion": 1.5
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "c42d155b-80b4-476f-a30e-36548bcef29a",
"connections": {
"OpenRouter LLM": {
"ai_languageModel": [
[
{
"node": "Extract business signals with AI",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Receive company URL": {
"main": [
[
{
"node": "Validate and normalize URL",
"type": "main",
"index": 0
}
]
]
},
"Search company data": {
"ai_tool": [
[
{
"node": "Extract business signals with AI",
"type": "ai_tool",
"index": 0
}
]
]
},
"Scrape company website": {
"ai_tool": [
[
{
"node": "Extract business signals with AI",
"type": "ai_tool",
"index": 0
}
]
]
},
"Skip if already enriched": {
"main": [
[
{
"node": "Return enriched profile",
"type": "main",
"index": 0
}
],
[
{
"node": "Prepare profile for insert",
"type": "main",
"index": 0
}
]
]
},
"Prepare profile for insert": {
"main": [
[
{
"node": "Save enriched profile to Supabase",
"type": "main",
"index": 0
}
]
]
},
"Validate and normalize URL": {
"main": [
[
{
"node": "Extract business signals with AI",
"type": "main",
"index": 0
}
],
[
{
"node": "Return URL validation error",
"type": "main",
"index": 0
}
]
]
},
"Parse into structured profile": {
"ai_outputParser": [
[
{
"node": "Extract business signals with AI",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Check for duplicate in Supabase": {
"main": [
[
{
"node": "Skip if already enriched",
"type": "main",
"index": 0
}
]
]
},
"Extract business signals with AI": {
"main": [
[
{
"node": "Check for duplicate in Supabase",
"type": "main",
"index": 0
}
]
]
},
"Save enriched profile to Supabase": {
"main": [
[
{
"node": "Return enriched profile",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
firecrawlApiopenRouterApisupabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
What this does
Source: https://n8n.io/workflows/13910/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Turn any prompt into structured web data. Send a POST request with a natural language prompt and an optional JSON schema, and get back clean, structured results scraped from the web by an AI agent pow
⏺ 🚀 How it works
Production-ready Reddit lead generation system with progressive data loading for optimal UX. This workflow integrates with a web frontend, sending results in real-time as they're processed instead of
This workflow automatically processes new free-trial / lead sign-ups in real time: Catches a webhook from any source (Webflow form, Intercom, custom agent, etc.) Filters out personal / disposable / .e
Transform your WhatsApp group conversations into actionable business intelligence through automated AI analysis and daily reporting. This workflow eliminates manual conversation monitoring by capturin