HTTP API
HTTP API reference
Programmatic access to the same Online pipelines: leads (one keyword per job), reviews (one place), and photos (one place). Authenticate with a personal Bearer key (gmf_…). Agent-capable Online plans only (Growth+)—see Pricing. Maps, reviews, and photos share one in-flight job per user.
Base URL: https://gmapsleadfinder.com
Prefer Remote MCP?
If you use Claude, Cursor, or another MCP client, install Remote MCP instead of calling HTTP by hand. MCP tools cover leads, reviews, and photos. The Agent & MCP docs cover setup, tools, and install snippets.
Prefer a client SDK?
Official Python, TypeScript, Go, Rust, PHP, Ruby, and .NET packages wrap create → poll → results for leads, reviews, and photos. Install, set GMF_API_KEY, and call scrape / scrapeReviews / scrapePhotos.
Authentication
Every /api/v1 request requires an Authorization header with your personal API key. Keys start with gmf_ and are issued in Account after you sign in on an agent-capable plan.
Authorization: Bearer gmf_<your_key>- Sign in at gmapsleadfinder.com on a plan that includes agent API.
- Open Account → API key, or visit /account#api-key.
- Copy the key (or regenerate). Pass it only from your client or secret store—never embed it in public frontends.
GET/POST /api/me/api-key require a browser session cookie and are for the Account UI—not for agent Bearer calls. Open Account API key
/api/v1/meGet plan & credits
Returns the authenticated user’s plan and credit snapshot. Useful before creating jobs.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
Response fields
| Field | Type | Description |
|---|---|---|
| plan | string | Effective plan (subscription tier, or starter when using permanent packs only) |
| creditsLimit | number | Subscription allotment total (or free+permanent ceiling when not subscribed) |
| creditsUsed | number | Credits already consumed from the subscription/free pool |
| creditsRemaining | number | Total spendable credits (subscription remaining + permanent) |
| permanentCredits | number | Non-expiring credits from one-time packs |
| subscriptionCreditsRemaining | number | Remaining credits from the current subscription period |
Error codes
- 401 — Missing or invalid API key
- 403 — Key valid but plan cannot use the agent API
curl
curl -sS https://gmapsleadfinder.com/api/v1/me \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
const res = await fetch("https://gmapsleadfinder.com/api/v1/me", {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const me = await res.json();
console.log(me.creditsRemaining, me.permanentCredits);Example response
{
"plan": "growth",
"creditsLimit": 80000,
"creditsUsed": 120,
"creditsRemaining": 81880,
"permanentCredits": 2000,
"subscriptionCreditsRemaining": 79880
}/api/v1/jobsCreate a job
Queues a single-keyword Maps scrape + enrich job. Exactly one keyword is required. Shares the one-running-job lock with the web extractor (HTTP 409 if busy).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| keyword | body | string | Yes | One search query (city + category works best). Multi-keyword strings are rejected. |
Response fields
| Field | Type | Description |
|---|---|---|
| jobId | string (uuid) | Job id for polling and results |
| keywordCount | number | Always 1 for API jobs |
| creditsRemaining | number | Credits left after queue (consumption occurs as rows are collected) |
Error codes
- 400 — Missing keyword or more than one keyword
- 401 — Missing or invalid API key
- 402 — No credits remaining
- 403 — Plan cannot use the agent API
- 409 — Another search job is already running for this user
curl
curl -sS -X POST https://gmapsleadfinder.com/api/v1/jobs \
-H "Authorization: Bearer $GMF_API_KEY" \
-H "Content-Type: application/json" \
-d '{"keyword":"dentists in Austin TX"}'JavaScript
const res = await fetch("https://gmapsleadfinder.com/api/v1/jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GMF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ keyword: "dentists in Austin TX" }),
});
const { jobId } = await res.json();Example response
{
"jobId": "3f2c8a1e-9b4d-4c2a-8e1f-0a1b2c3d4e5f",
"keywordCount": 1,
"creditsRemaining": 4880
}/api/v1/jobs/{id}Get job status
Poll job metadata until status is completed, partial, or failed. Includes per-keyword file progress when available.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| id | path | string (uuid) | Yes | Job id returned by POST /api/v1/jobs |
Response fields
| Field | Type | Description |
|---|---|---|
| id | string | Job id |
| status | string | queued | running | completed | partial | failed (and related pipeline states) |
| keywords | string[] | Keyword list for the job |
| keywordCount | number | Number of keywords |
| currentKeywordIndex | number | Progress index while running |
| rowCount | number | Rows collected so far / total for the job |
| error | string | null | Error message when failed |
| createdAt | string (ISO) | Created timestamp |
| finishedAt | string | null | Finished timestamp |
| files | object[] | Per-keyword file records: id, keyword, position, status, pageCount, rowCount, enrichStatus, error |
| creditsRemaining | number | Current credits remaining |
Error codes
- 401 — Missing or invalid API key
- 403 — Plan cannot use the agent API
- 404 — Job not found for this key’s user
curl
curl -sS https://gmapsleadfinder.com/api/v1/jobs/$JOB_ID \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
const res = await fetch(`https://gmapsleadfinder.com/api/v1/jobs/${jobId}`, {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const job = await res.json();
// poll while job.status is queued or runningExample response
{
"id": "3f2c8a1e-9b4d-4c2a-8e1f-0a1b2c3d4e5f",
"status": "completed",
"keywords": ["dentists in Austin TX"],
"keywordCount": 1,
"currentKeywordIndex": 0,
"rowCount": 42,
"error": null,
"createdAt": "2026-09-13T01:00:00.000Z",
"finishedAt": "2026-09-13T01:02:10.000Z",
"files": [
{
"id": "…",
"keyword": "dentists in Austin TX",
"position": 0,
"status": "completed",
"pageCount": 3,
"rowCount": 42,
"enrichStatus": "completed",
"error": null
}
],
"creditsRemaining": 4838
}/api/v1/jobs/{id}/resultsGet job results
Returns paginated place rows as JSON objects keyed by export column headers. Follow nextCursor until null. Column set matches Leads export-column preferences.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| id | path | string (uuid) | Yes | Job id |
| limit | query | integer | No | Page size 1–500 (default 100) |
| cursor | query | string | No | Offset cursor from a previous nextCursor (default 0) |
Response fields
| Field | Type | Description |
|---|---|---|
| jobId | string | Job id |
| status | string | Current job status |
| columns | string[] | Ordered export column headers |
| rows | object[] | Each row is { [column]: string } |
| count | number | Rows in this page |
| total | number | Total rows available for the job |
| cursor | number | Offset used for this page |
| nextCursor | string | null | Pass as cursor for the next page; null when done |
Error codes
- 401 — Missing or invalid API key
- 403 — Plan cannot use the agent API
- 404 — Job not found
curl
curl -sS "https://gmapsleadfinder.com/api/v1/jobs/$JOB_ID/results?limit=100" \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
async function fetchAllRows(jobId) {
const rows = [];
let cursor = "0";
while (cursor != null) {
const url = new URL(`https://gmapsleadfinder.com/api/v1/jobs/${jobId}/results`);
url.searchParams.set("limit", "100");
url.searchParams.set("cursor", cursor);
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const page = await res.json();
rows.push(...page.rows);
cursor = page.nextCursor;
}
return rows;
}Example response
{
"jobId": "3f2c8a1e-9b4d-4c2a-8e1f-0a1b2c3d4e5f",
"status": "completed",
"columns": ["Name", "Phone", "Website", "Emails"],
"rows": [
{
"Name": "Austin Smile Dental",
"Phone": "(512) 555-0142",
"Website": "https://example.com",
"Emails": "hello@example.com"
}
],
"count": 1,
"total": 42,
"cursor": 0,
"nextCursor": "1"
}/api/v1/review-jobsCreate a reviews job
Queues a single-place Google Maps reviews scrape. Exactly one place (Maps URL or business_id) is required. Shares the one-running-job lock with leads and photos (HTTP 409 if busy).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| place | body | string | Yes | Google Maps place URL or business_id (0x…:0x…) |
Response fields
| Field | Type | Description |
|---|---|---|
| jobId | string (uuid) | Job id for polling and results |
| creditsRemaining | number | Credits left after queue (consumption occurs as review rows are collected) |
Error codes
- 400 — Missing or invalid place
- 401 — Missing or invalid API key
- 402 — No credits remaining
- 403 — Plan cannot use the agent API
- 409 — Another job is already running for this user
curl
curl -sS -X POST https://gmapsleadfinder.com/api/v1/review-jobs \
-H "Authorization: Bearer $GMF_API_KEY" \
-H "Content-Type: application/json" \
-d '{"place":"https://maps.google.com/?cid=…"}'JavaScript
const res = await fetch("https://gmapsleadfinder.com/api/v1/review-jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GMF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ place: "https://maps.google.com/?cid=…" }),
});
const { jobId } = await res.json();Example response
{
"jobId": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
"creditsRemaining": 4800
}/api/v1/review-jobs/{id}Get reviews job status
Poll reviews job metadata until status is completed, partial, or failed.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| id | path | string (uuid) | Yes | Job id returned by POST /api/v1/review-jobs |
Response fields
| Field | Type | Description |
|---|---|---|
| id | string | Job id |
| status | string | queued | running | completed | partial | failed (and related pipeline states) |
| rowCount | number | Review rows collected so far / total |
| error | string | null | Error message when failed |
| createdAt | string (ISO) | Created timestamp |
| finishedAt | string | null | Finished timestamp |
| creditsRemaining | number | Current credits remaining |
Error codes
- 400 — Job exists but is not a reviews job
- 401 — Missing or invalid API key
- 403 — Plan cannot use the agent API
- 404 — Job not found for this key’s user
curl
curl -sS https://gmapsleadfinder.com/api/v1/review-jobs/$JOB_ID \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
const res = await fetch(`https://gmapsleadfinder.com/api/v1/review-jobs/${jobId}`, {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const job = await res.json();Example response
{
"id": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
"status": "completed",
"rowCount": 128,
"error": null,
"createdAt": "2026-09-19T01:00:00.000Z",
"finishedAt": "2026-09-19T01:03:40.000Z",
"creditsRemaining": 4672
}/api/v1/review-jobs/{id}/resultsGet reviews job results
Returns paginated review rows as JSON objects keyed by export column headers. Follow nextCursor until null. Column set matches Reviews export preferences.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| id | path | string (uuid) | Yes | Reviews job id |
| limit | query | integer | No | Page size 1–500 (default 100) |
| cursor | query | string | No | Offset cursor from a previous nextCursor (default 0) |
Response fields
| Field | Type | Description |
|---|---|---|
| jobId | string | Job id |
| status | string | Current job status |
| columns | string[] | Ordered export column headers |
| rows | object[] | Each row is { [column]: string } |
| count | number | Rows in this page |
| total | number | Total rows available for the job |
| cursor | number | Offset used for this page |
| nextCursor | string | null | Pass as cursor for the next page; null when done |
Error codes
- 400 — Not a reviews job
- 401 — Missing or invalid API key
- 403 — Plan cannot use the agent API
- 404 — Job not found
curl
curl -sS "https://gmapsleadfinder.com/api/v1/review-jobs/$JOB_ID/results?limit=100" \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
const res = await fetch(`https://gmapsleadfinder.com/api/v1/review-jobs/${jobId}/results?limit=100`, {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const page = await res.json();Example response
{
"jobId": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
"status": "completed",
"columns": ["Rating", "Text", "User", "Date"],
"rows": [
{
"Rating": "5",
"Text": "Great visit.",
"User": "Alex",
"Date": "2026-08-01"
}
],
"count": 1,
"total": 128,
"cursor": 0,
"nextCursor": "1"
}/api/v1/photo-jobsCreate a photos job
Queues a single-place Google Maps photos scrape. Exactly one place (Maps URL, business_id, or Place ID) is required. Shares the one-running-job lock with leads and reviews (HTTP 409 if busy).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| place | body | string | Yes | Google Maps place URL, business_id (0x…:0x…), or Place ID (ChIJ…) |
Response fields
| Field | Type | Description |
|---|---|---|
| jobId | string (uuid) | Job id for polling and results |
| creditsRemaining | number | Credits left after queue (consumption occurs as unique photo URLs are collected) |
Error codes
- 400 — Missing or invalid place
- 401 — Missing or invalid API key
- 402 — No credits remaining
- 403 — Plan cannot use the agent API
- 409 — Another job is already running for this user
curl
curl -sS -X POST https://gmapsleadfinder.com/api/v1/photo-jobs \
-H "Authorization: Bearer $GMF_API_KEY" \
-H "Content-Type: application/json" \
-d '{"place":"ChIJ…"}'JavaScript
const res = await fetch("https://gmapsleadfinder.com/api/v1/photo-jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GMF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ place: "ChIJ…" }),
});
const { jobId } = await res.json();Example response
{
"jobId": "9f0e1d2c-3b4a-5987-6543-210fedcba987",
"creditsRemaining": 4700
}/api/v1/photo-jobs/{id}Get photos job status
Poll photos job metadata until status is completed, partial, or failed.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| id | path | string (uuid) | Yes | Job id returned by POST /api/v1/photo-jobs |
Response fields
| Field | Type | Description |
|---|---|---|
| id | string | Job id |
| status | string | queued | running | completed | partial | failed (and related pipeline states) |
| rowCount | number | Photo URL rows collected so far / total |
| error | string | null | Error message when failed |
| createdAt | string (ISO) | Created timestamp |
| finishedAt | string | null | Finished timestamp |
| creditsRemaining | number | Current credits remaining |
Error codes
- 400 — Job exists but is not a photos job
- 401 — Missing or invalid API key
- 403 — Plan cannot use the agent API
- 404 — Job not found for this key’s user
curl
curl -sS https://gmapsleadfinder.com/api/v1/photo-jobs/$JOB_ID \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
const res = await fetch(`https://gmapsleadfinder.com/api/v1/photo-jobs/${jobId}`, {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const job = await res.json();Example response
{
"id": "9f0e1d2c-3b4a-5987-6543-210fedcba987",
"status": "completed",
"rowCount": 64,
"error": null,
"createdAt": "2026-09-19T02:00:00.000Z",
"finishedAt": "2026-09-19T02:02:15.000Z",
"creditsRemaining": 4636
}/api/v1/photo-jobs/{id}/resultsGet photos job results
Returns paginated photo URL rows as JSON objects keyed by export column headers. Follow nextCursor until null. Column set matches Photos export preferences. Unique photo URLs are billed 1 credit each after dedupe.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| Authorization | header | string | Yes | Bearer gmf_… API key |
| id | path | string (uuid) | Yes | Photos job id |
| limit | query | integer | No | Page size 1–500 (default 100) |
| cursor | query | string | No | Offset cursor from a previous nextCursor (default 0) |
Response fields
| Field | Type | Description |
|---|---|---|
| jobId | string | Job id |
| status | string | Current job status |
| columns | string[] | Ordered export column headers |
| rows | object[] | Each row is { [column]: string } |
| count | number | Rows in this page |
| total | number | Total rows available for the job |
| cursor | number | Offset used for this page |
| nextCursor | string | null | Pass as cursor for the next page; null when done |
Error codes
- 400 — Not a photos job
- 401 — Missing or invalid API key
- 403 — Plan cannot use the agent API
- 404 — Job not found
curl
curl -sS "https://gmapsleadfinder.com/api/v1/photo-jobs/$JOB_ID/results?limit=100" \
-H "Authorization: Bearer $GMF_API_KEY"JavaScript
const res = await fetch(`https://gmapsleadfinder.com/api/v1/photo-jobs/${jobId}/results?limit=100`, {
headers: { Authorization: `Bearer ${process.env.GMF_API_KEY}` },
});
const page = await res.json();Example response
{
"jobId": "9f0e1d2c-3b4a-5987-6543-210fedcba987",
"status": "completed",
"columns": ["Photo URL", "Width", "Height"],
"rows": [
{
"Photo URL": "https://lh3.googleusercontent.com/…=s1280-k-no",
"Width": "1280",
"Height": "960"
}
],
"count": 1,
"total": 64,
"cursor": 0,
"nextCursor": "1"
}Typical workflow
- Call GET /api/v1/me to confirm creditsRemaining > 0.
- Leads: POST /api/v1/jobs with one keyword. Reviews: POST /api/v1/review-jobs with one place. Photos: POST /api/v1/photo-jobs with one place. Store jobId.
- Poll GET /api/v1/jobs/{id}, /api/v1/review-jobs/{id}, or /api/v1/photo-jobs/{id} until status is completed, partial, or failed.
- GET …/results and follow nextCursor until null. Only one job (any type) may run at a time.
Errors & limits
| Code | Meaning |
|---|---|
| 400 | Bad request (e.g. not exactly one keyword/place) |
| 401 | Missing or invalid Bearer key |
| 402 | No credits remaining |
| 403 | Authenticated but plan cannot use agent API |
| 404 | Job not found |
| 409 | Another job is already running for this user (leads, reviews, or photos—web or API) |
- Credits: 1 place row (leads) / 1 review row / 1 unique photo URL.
- Leads API jobs accept exactly one keyword; reviews and photos accept exactly one place. Use the web UI for multi-keyword lead batches.
- Results column sets follow Leads / Reviews / Photos export preferences.
- Empty email/social cells mean nothing public was found—we never invent contacts.