This workflow follows the HTTP Request → Supabase 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 →
{
"updatedAt": "2026-01-08T14:42:40.000Z",
"createdAt": "2025-12-23T14:24:12.179Z",
"id": "ZGREMEac60ej1UTs",
"name": "02_HUNTER_Serper",
"active": false,
"isArchived": true,
"nodes": [
{
"parameters": {},
"id": "70adbc9c-d799-4e04-80f0-e5483575152d",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"method": "POST",
"url": "https://google.serper.dev/maps",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-API-KEY",
"value": "={{ $credentials.serperApiKey }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.term }} in {{ $json.location }}"
},
{
"name": "num",
"value": "20"
}
]
},
"options": {}
},
"id": "ca25ff4b-c911-44cb-b612-373037a5ba6b",
"name": "Serper - Google Maps Search",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
208,
0
],
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Get the Serper response\nconst serperData = $input.all();\n\n// Extract batch info from the original input\nconst originalInput = $('Manual Trigger').item.json;\nconst batchId = originalInput.batch_id || null;\nconst userId = originalInput.user_id || '00000000-0000-0000-0000-000000000000'; // Hardcoded for Sprint 0\n\n// Transform each place into a lead\nconst transformedLeads = [];\n\nfor (const item of serperData) {\n const places = item.json.places || [];\n \n for (const place of places) {\n // Clean phone number\n let cleanPhone = place.phone || place.phoneNumber || null;\n if (cleanPhone) {\n cleanPhone = cleanPhone.replace(/[^\\d+]/g, '');\n if (!cleanPhone.startsWith('+')) {\n cleanPhone = '+1' + cleanPhone; // Assume US\n }\n }\n \n transformedLeads.push({\n batch_id: batchId,\n user_id: userId,\n name: place.title || place.name || 'Unknown',\n phone: cleanPhone,\n email: null, // Not provided by Google Maps\n address: place.address || null,\n website: place.website || null,\n rating: place.rating || null,\n reviews_count: place.reviews || place.reviewsCount || 0,\n status: 'raw',\n raw_data: place, // Store complete original data\n created_at: new Date().toISOString()\n });\n }\n}\n\n// Log for debugging\nconsole.log(`Transformed ${transformedLeads.length} leads`);\n\n// Return array of leads\nreturn transformedLeads.map(lead => ({ json: lead }));"
},
"id": "d528de06-7cb5-4f7c-86f6-a0d9a28735c7",
"name": "Transform Leads",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
0
]
},
{
"parameters": {
"operation": "insert"
},
"id": "b3e01949-f6dd-4f14-94da-a8101d258d3d",
"name": "Insert Leads to Supabase",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
608,
0
]
},
{
"parameters": {
"jsCode": "// Count successful inserts\nconst insertedLeads = $input.all();\nconst successCount = insertedLeads.length;\n\n// Get batch_id from first item\nconst batchId = insertedLeads[0]?.json?.batch_id;\n\nreturn [{\n json: {\n workflow: '02_HUNTER',\n status: 'success',\n leads_found: successCount,\n batch_id: batchId,\n timestamp: new Date().toISOString(),\n message: `Successfully inserted ${successCount} leads`\n }\n}];"
},
"id": "98d9e09b-196d-42fb-bebc-47f31f7ec701",
"name": "Create Summary",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
800,
0
]
},
{
"parameters": {
"operation": "update",
"tableId": "batches"
},
"id": "62a7390a-986e-4a95-bb86-9e26ab1ed92f",
"name": "Update Batch Status",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
1008,
0
]
}
],
"connections": {
"Manual Trigger": {
"main": [
[
{
"node": "Serper - Google Maps Search",
"type": "main",
"index": 0
}
]
]
},
"Serper - Google Maps Search": {
"main": [
[
{
"node": "Transform Leads",
"type": "main",
"index": 0
}
]
]
},
"Transform Leads": {
"main": [
[
{
"node": "Insert Leads to Supabase",
"type": "main",
"index": 0
}
]
]
},
"Insert Leads to Supabase": {
"main": [
[
{
"node": "Create Summary",
"type": "main",
"index": 0
}
]
]
},
"Create Summary": {
"main": [
[
{
"node": "Update Batch Status",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"meta": null,
"versionId": "15d36b20-cdd8-4009-9073-9e36fbb3d8e6",
"activeVersionId": null,
"triggerCount": 0,
"shared": [
{
"updatedAt": "2025-12-23T14:24:12.190Z",
"createdAt": "2025-12-23T14:24:12.190Z",
"role": "workflow:owner",
"workflowId": "ZGREMEac60ej1UTs",
"projectId": "HHopAZ4lOFgjhBzT"
}
],
"activeVersion": null,
"tags": []
}
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.
httpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
02_HUNTER_Serper. Uses httpRequest, supabase. Event-driven trigger; 6 nodes.
Source: https://github.com/abde0112/n8n_bkv2/blob/main/02_hunter_serper-ZGREMEac60ej1UTs.json — 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.
Reddit Monitor Master v3. Uses airtable, supabase, slack, httpRequest. Event-driven trigger; 52 nodes.
Reddit Monitor Tool. Uses airtable, supabase, slack, httpRequest. Event-driven trigger; 52 nodes.
This enables webhooks for nearly realtime updates (every 5 seconds) from Notion Databases.
dummy_client - Shopify abandoned carts. Uses httpRequest, shopifyTrigger, whatsApp, supabase. Event-driven trigger; 25 nodes.
This workflow automatically collects historical price data from Polymarket Up/Down markets and stores it in Supabase, creating a structured and query-ready dataset for analysis. By continuously fetchi