API
Automations (scheduled searches)
Schedule a search to re-run on a cadence and export itself — over the API, not just in the app.
API
Schedule a search to re-run on a cadence and export itself — over the API, not just in the app.
API
Schedule a search to re-run on a cadence and export itself — over the API, not just in the app.
An automation re-runs a search on a schedule and sends the results wherever you want, with no one at a keyboard. Anything you can set up on the Automations page you can also do here — and both read the same records, so a schedule created over the API shows up in the dashboard immediately.
Every run spends leads — one per result, same as a manual search. Pause an automation to stop it spending.
GET/api/v1/schedules
Lists your automations with their cadence, destination, next run and last result.
POST/api/v1/schedules
| keyword | Required. The niche to search, e.g. "roofing contractor". |
| locations | Required. Cities as plain strings — ["Austin, TX"] — or {location_code, location_name} objects, mixed in any order. Max 25. Every city string must be found: if one isn't, nothing is saved and the 400 names it. In an object, location_code must be a positive whole number, as /locations returns it — anything else is a 400 naming the entry, and nothing is saved. A code the location list holds is saved under that code's own place name, whatever location_name says; a code it doesn't hold is a place outside the US, and is a 400 naming the entry — nothing is saved; a US territory's code (Puerto Rico, Guam …) is saved under its own place name, as a US one is. Every object is saved as sent if the location list can't be read at all just then. |
| US places only | Automations search US places only for now: a city outside the US, such as "London, UK", is a 400, and nothing is saved. |
| cadence | Required. once | daily | weekly | monthly | yearly. |
| destination | Where each run's leads go — see Destinations below. Omit it (or send null) to just save them to your library. |
| spreadsheet_id | With destination "google_sheets": add each run to this spreadsheet, one LeadMarina created in an earlier export, instead of making a new one. |
| start_at | First run, as an ISO 8601 timestamp string such as "2026-11-02T09:00:00Z" — a number or an unreadable date is refused. Omitted, null or in the past means now: the next tick runs it, within 15 minutes. At most 2 years ahead. |
Destinations. destination is a name or an object:
| none | Save the leads to your library only — the same as leaving destination out. Object: {"provider": "none"}. |
| csv | xlsx | json | Email each run's leads to you as that file. Object: {"provider": "email", "format": "xlsx"} — format defaults to csv. |
| ghl | Upsert each run into your connected GoHighLevel sub-account. Object: {"provider": "ghl"}. |
| close | Push each run into Close with your saved field mapping, updating leads it sent before. Object: {"provider": "close", "updateExisting": false} sends only leads Close hasn't had yet. |
| google_sheets | A new spreadsheet every run. To add to one LeadMarina created earlier, send its spreadsheet_id beside the name, or {"provider": "google_sheets", "spreadsheet_id": "…"}: rows already there are updated, unless "updateExisting": false, which appends every row. |
Names are read in any case. Anything else — “email”, “gohighlevel”, {"provider": "csv"}, a file format other than csv, xlsx or json — is refused with a 400 that says what to send, and nothing is saved.
curl -X POST https://leadmarina.com/api/v1/schedules \
-H "Authorization: Bearer lm_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"keyword": "roofing contractor",
"locations": ["Austin, TX", "Dallas, TX"],
"cadence": "weekly",
"destination": { "provider": "email", "format": "csv" },
"start_at": "2026-11-02T09:00:00Z"
}'The 201 response echoes what was saved — the cities it resolved, the destination as each run will read it, and the first run — so you can confirm you got what you meant:
{
"id": "9f2c...81a",
"locations": [
{ "location_code": 200635, "location_name": "Austin, TX, Texas, United States" },
{ "location_code": 1026339, "location_name": "Dallas, Texas, United States" }
],
"destination": { "provider": "email", "format": "csv" },
"next_run_at": "2026-11-02T09:00:00.000Z"
}A close, ghl or google_sheets destination is checked when you create the schedule, not at 3am on the first run — if the integration isn’t connected (or Close has no saved field mapping yet) you get a 400 right away instead of a schedule that fails silently every week. If a city string or your integrations can’t be looked up just then, the answer is a 503 and nothing is saved — try again shortly.
PATCH/api/v1/schedules/:id
Pause or resume: { "active": false }. Pausing keeps the automation but stops it running and spending, and cancels any run still waiting in the queue.
DELETE/api/v1/schedules/:id
Deletes the schedule and cancels any run still waiting in the queue. Leads collected by past runs are kept. A schedule that isn’t yours, or an id that isn’t one, returns 404 — up to 20 automations per account.