Language

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.

Open Agent & MCP docs

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.

Open Client SDKs

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.

http
Authorization: Bearer gmf_<your_key>
  1. Sign in at gmapsleadfinder.com on a plan that includes agent API.
  2. Open Account → API key, or visit /account#api-key.
  3. 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

GET/api/v1/me

Get plan & credits

Returns the authenticated user’s plan and credit snapshot. Useful before creating jobs.

Parameters

Name In Type Required Description
AuthorizationheaderstringYesBearer gmf_… API key

Response fields

Field Type Description
planstringEffective plan (subscription tier, or starter when using permanent packs only)
creditsLimitnumberSubscription allotment total (or free+permanent ceiling when not subscribed)
creditsUsednumberCredits already consumed from the subscription/free pool
creditsRemainingnumberTotal spendable credits (subscription remaining + permanent)
permanentCreditsnumberNon-expiring credits from one-time packs
subscriptionCreditsRemainingnumberRemaining 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

bash
curl -sS https://gmapsleadfinder.com/api/v1/me \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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

json
{
  "plan": "growth",
  "creditsLimit": 80000,
  "creditsUsed": 120,
  "creditsRemaining": 81880,
  "permanentCredits": 2000,
  "subscriptionCreditsRemaining": 79880
}
POST/api/v1/jobs

Create 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
AuthorizationheaderstringYesBearer gmf_… API key
keywordbodystringYesOne search query (city + category works best). Multi-keyword strings are rejected.

Response fields

Field Type Description
jobIdstring (uuid)Job id for polling and results
keywordCountnumberAlways 1 for API jobs
creditsRemainingnumberCredits 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

bash
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

js
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

json
{
  "jobId": "3f2c8a1e-9b4d-4c2a-8e1f-0a1b2c3d4e5f",
  "keywordCount": 1,
  "creditsRemaining": 4880
}
GET/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
AuthorizationheaderstringYesBearer gmf_… API key
idpathstring (uuid)YesJob id returned by POST /api/v1/jobs

Response fields

Field Type Description
idstringJob id
statusstringqueued | running | completed | partial | failed (and related pipeline states)
keywordsstring[]Keyword list for the job
keywordCountnumberNumber of keywords
currentKeywordIndexnumberProgress index while running
rowCountnumberRows collected so far / total for the job
errorstring | nullError message when failed
createdAtstring (ISO)Created timestamp
finishedAtstring | nullFinished timestamp
filesobject[]Per-keyword file records: id, keyword, position, status, pageCount, rowCount, enrichStatus, error
creditsRemainingnumberCurrent 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

bash
curl -sS https://gmapsleadfinder.com/api/v1/jobs/$JOB_ID \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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 running

Example response

json
{
  "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
}
GET/api/v1/jobs/{id}/results

Get 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
AuthorizationheaderstringYesBearer gmf_… API key
idpathstring (uuid)YesJob id
limitqueryintegerNoPage size 1–500 (default 100)
cursorquerystringNoOffset cursor from a previous nextCursor (default 0)

Response fields

Field Type Description
jobIdstringJob id
statusstringCurrent job status
columnsstring[]Ordered export column headers
rowsobject[]Each row is { [column]: string }
countnumberRows in this page
totalnumberTotal rows available for the job
cursornumberOffset used for this page
nextCursorstring | nullPass 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

bash
curl -sS "https://gmapsleadfinder.com/api/v1/jobs/$JOB_ID/results?limit=100" \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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

json
{
  "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"
}
POST/api/v1/review-jobs

Create 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
AuthorizationheaderstringYesBearer gmf_… API key
placebodystringYesGoogle Maps place URL or business_id (0x…:0x…)

Response fields

Field Type Description
jobIdstring (uuid)Job id for polling and results
creditsRemainingnumberCredits 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

bash
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

js
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

json
{
  "jobId": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
  "creditsRemaining": 4800
}
GET/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
AuthorizationheaderstringYesBearer gmf_… API key
idpathstring (uuid)YesJob id returned by POST /api/v1/review-jobs

Response fields

Field Type Description
idstringJob id
statusstringqueued | running | completed | partial | failed (and related pipeline states)
rowCountnumberReview rows collected so far / total
errorstring | nullError message when failed
createdAtstring (ISO)Created timestamp
finishedAtstring | nullFinished timestamp
creditsRemainingnumberCurrent 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

bash
curl -sS https://gmapsleadfinder.com/api/v1/review-jobs/$JOB_ID \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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

json
{
  "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
}
GET/api/v1/review-jobs/{id}/results

Get 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
AuthorizationheaderstringYesBearer gmf_… API key
idpathstring (uuid)YesReviews job id
limitqueryintegerNoPage size 1–500 (default 100)
cursorquerystringNoOffset cursor from a previous nextCursor (default 0)

Response fields

Field Type Description
jobIdstringJob id
statusstringCurrent job status
columnsstring[]Ordered export column headers
rowsobject[]Each row is { [column]: string }
countnumberRows in this page
totalnumberTotal rows available for the job
cursornumberOffset used for this page
nextCursorstring | nullPass 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

bash
curl -sS "https://gmapsleadfinder.com/api/v1/review-jobs/$JOB_ID/results?limit=100" \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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

json
{
  "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"
}
POST/api/v1/photo-jobs

Create 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
AuthorizationheaderstringYesBearer gmf_… API key
placebodystringYesGoogle Maps place URL, business_id (0x…:0x…), or Place ID (ChIJ…)

Response fields

Field Type Description
jobIdstring (uuid)Job id for polling and results
creditsRemainingnumberCredits 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

bash
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

js
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

json
{
  "jobId": "9f0e1d2c-3b4a-5987-6543-210fedcba987",
  "creditsRemaining": 4700
}
GET/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
AuthorizationheaderstringYesBearer gmf_… API key
idpathstring (uuid)YesJob id returned by POST /api/v1/photo-jobs

Response fields

Field Type Description
idstringJob id
statusstringqueued | running | completed | partial | failed (and related pipeline states)
rowCountnumberPhoto URL rows collected so far / total
errorstring | nullError message when failed
createdAtstring (ISO)Created timestamp
finishedAtstring | nullFinished timestamp
creditsRemainingnumberCurrent 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

bash
curl -sS https://gmapsleadfinder.com/api/v1/photo-jobs/$JOB_ID \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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

json
{
  "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
}
GET/api/v1/photo-jobs/{id}/results

Get 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
AuthorizationheaderstringYesBearer gmf_… API key
idpathstring (uuid)YesPhotos job id
limitqueryintegerNoPage size 1–500 (default 100)
cursorquerystringNoOffset cursor from a previous nextCursor (default 0)

Response fields

Field Type Description
jobIdstringJob id
statusstringCurrent job status
columnsstring[]Ordered export column headers
rowsobject[]Each row is { [column]: string }
countnumberRows in this page
totalnumberTotal rows available for the job
cursornumberOffset used for this page
nextCursorstring | nullPass 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

bash
curl -sS "https://gmapsleadfinder.com/api/v1/photo-jobs/$JOB_ID/results?limit=100" \
  -H "Authorization: Bearer $GMF_API_KEY"

JavaScript

js
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

json
{
  "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

  1. Call GET /api/v1/me to confirm creditsRemaining > 0.
  2. 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.
  3. Poll GET /api/v1/jobs/{id}, /api/v1/review-jobs/{id}, or /api/v1/photo-jobs/{id} until status is completed, partial, or failed.
  4. GET …/results and follow nextCursor until null. Only one job (any type) may run at a time.

Errors & limits

Code Meaning
400Bad request (e.g. not exactly one keyword/place)
401Missing or invalid Bearer key
402No credits remaining
403Authenticated but plan cannot use agent API
404Job not found
409Another 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.

Related