A weekly list that fills itself
A schedule trigger runs the same niche across a rotating set of cities every Monday morning, so the sales team opens the week with new contacts already in the sheet.
Everything the dashboard does is available over an HTTP API, so the search you run by hand on Monday can run itself every Monday. This page builds the whole thing in n8n — trigger, search, poll, filter, deliver — with nothing left as an exercise.
The API is the same engine the dashboard runs on, without the dashboard. Four things teams wire up most often:
A schedule trigger runs the same niche across a rotating set of cities every Monday morning, so the sales team opens the week with new contacts already in the sheet.
Verified addresses are enrolled into an Instantly, Smartlead or Lemlist sequence as they arrive — no CSV downloaded, no CSV uploaded, no step where a file sits on somebody's desktop.
A webhook fires when a deal is created, searches for similar businesses in the same city, and writes the results back as related leads.
One workflow per client, each with its own niche and territory, delivering a clean list into the client's own folder on a schedule they agreed to.
Three calls, in a loop. A search returns an id straight away, you poll that id until it reports done, and then you read the rows off the finished job.
Schedule Trigger
│
▼
HTTP Request ──▶ POST /api/v1/search → { id, status, poll }
│
▼
Wait (30s) ◀───────────────┐
│ │
▼ │
HTTP Request ──▶ GET {{ $json.poll }} → { status, leads[] }
│ │
▼ │
IF status = done ? ──no──┘
│ yes
▼
Split Out (leads) ──▶ Filter (emailStatus) ──▶ CRM / Sheet / SequenceThe loop is the part worth getting right. A real search runs for minutes, and holding an HTTP connection open that long fails at whatever proxy sits between n8n and us — which is why the API never asks you to.
Open the GoLeadX dashboard, go to Billing → API keys, and create one. It is shown once and stored only as a hash, so copy it before closing the panel. API access is on the Scale plan.
In n8n, create a Generic Credential Type → Header Auth credential. Name: Authorization. Value: Bearer glx_live_… — the key you just copied. Every node in the workflow reuses this one credential.
Use a Schedule Trigger for a recurring list — weekly on Monday at 07:00 is a common choice — or a Webhook node if another system decides when a search should run.
HTTP Request node, POST to https://goleadx.com/api/v1/search with your queries, locations and sources as JSON. It returns an id immediately rather than holding the connection open, so nothing times out.
A Wait node of 30 seconds, an HTTP Request node that GETs the poll URL from the previous response, and an IF node that loops back to Wait while status is not done. Most searches finish inside a couple of minutes.
Split Out on the leads array, then a Filter node keeping emailStatus equal to valid or risky. Sending to invalid addresses is what costs a sender reputation, so this node is not optional.
Push each row wherever it belongs: an HTTP Request node into your CRM, the Google Sheets node for a shared list, or your sending tool's node to enrol contacts in a sequence directly.
Sent by the first HTTP Request node. Every keyword runs against every location, so three keywords across four cities is twelve searches in one call.
{
"queries": ["dental clinics", "orthodontists"],
"locations": ["Miami", "Orlando", "Tampa"],
"sources": ["google_maps", "web_search"],
"maxResults": 200,
"verifyEmails": true,
"enrich": true
}Rows appear in leads during the run, not only at the end, so a workflow that wants to start sending early can read them before status flips to done.
{
"id": "9f2c…",
"status": "running",
"progress": { "found": 128, "withEmail": 54, "verified": 41 },
"leads": [
{
"name": "Northside Dental Studio",
"email": "hello@example.com",
"emailStatus": "valid",
"phone": "+1 305 555 0142",
"website": "https://example.com",
"city": "Miami",
"source": "google_maps"
}
]
}Every address carries a verdict. Keep valid and risky — role addresses such as info@ resolve correctly and are graded risky rather than bad — and drop invalid before anything sends.
{{ $json.emailStatus === "valid" || $json.emailStatus === "risky" }}None of this is specific to n8n. It is bearer authentication and JSON over HTTP, so any tool that can make three requests can run the same workflow.
# 1 — start
curl -X POST https://goleadx.com/api/v1/search \
-H "Authorization: Bearer glx_live_xxxx" \
-H "Content-Type: application/json" \
-d '{"queries":["dental clinics"],"locations":["Miami"],"sources":["google_maps"]}'
# 2 — poll, until "status": "done"
curl https://goleadx.com/api/v1/search/9f2c… \
-H "Authorization: Bearer glx_live_xxxx"In Make, use the HTTP module with a repeater and a sleep between polls. In Zapier, Webhooks by Zapier covers the same three calls, though its step limits make long polls awkward — a schedule that re-checks a stored job id works better there.
| What you see | What it means |
|---|---|
401 | The header is missing, malformed or the key was revoked. The value must be Bearer glx_live_…, with the space. |
402 | No active subscription, or the monthly credits are spent. |
403 | The plan does not include API access. Scale does; Basic and Pro do not. |
422 | The body is invalid. The response names the offending fields. |
429 | Over 60 requests a minute, or five searches already running. Read Retry-After and feed it into a Wait node. |
| A loop that never ends | The IF node is comparing against the wrong field. Check {{ $json.status }}, and cap the loop so a stuck job cannot run forever. |
| Far fewer emails than leads | Expected. Not every business publishes an address; the lead count and the contactable count are different numbers. |
Build the search in the dashboard, check the rows are what you expected, and only then wire it into n8n. A scheduled workflow that runs the wrong query is just a faster way to spend credits.
Open the dashboard →