Geogrid Map
Draw a finished geogrid scan on a street map and get it back as a PNG or WebP: one circle per grid point, numbered with its rank and coloured by it, with the business, keyword and headline numbers on top, ready to drop into a report or show in a chat.
When to use this
A grid of numbers is hard to read and harder to send to a client. This turns a scan you have already run into the picture everyone expects: the whole service area on a map, green where the business ranks in the top 3, red where it falls behind, grey where it is not found. Run the same scan again later and the map shows how far each point moved since the last one. Ask for it after the scan completes; the scan itself is not charged again.
/v1/geogrid/mapParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| job_id | string | Yes | The job_id of a completed geogrid scan, from the scan submit or from geogrid status. It must belong to your account. |
| size | integer | No | 600, 800 or 1000. Default: 800 |
| scale | integer | No | Pixel density: 2 (default) draws twice size in pixels for sharing and print; 1 draws size in pixels for chat and email |
| format | string | No | "png" (default) or "webp", about a fifth of the size. With no format, Accept: image/webp picks webp |
| style | string | No | "light" or "dark". Default: "light" |
| compare | boolean | No | Show the change since your previous scan of the same keyword, business, grid, zoom, radius and centre, when there is one. Default: true |
| compare_to | string | No | job_id of a specific earlier scan to compare against instead, e.g. the first scan of an engagement; it applies even with compare false. Must be your own completed, older scan of the same keyword, business, grid size, zoom, radius and centre (409 otherwise, nothing charged) |
Example Request
curl -X POST https://api.localseodata.com/v1/geogrid/map \
-H "Authorization: Bearer sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"job_id": "geo_a1b2c3d4e5",
"size": 800,
"style": "light"
}'Example Response
{
"status": "success",
"credits_used": 2,
"data": {
"job_id": "geo_a1b2c3d4e5",
"image_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
"mime_type": "image/png",
"width": 1600,
"height": 1600,
"style": "light",
"format": "png",
"business_name": "Joe's Plumbing",
"keyword": "plumber",
"atrp": 10.1,
"found": 24,
"points": 25,
"compared_to": { "job_id": "geo_9z8y7x6w5v", "date": "2026-10-01T12:04:00.000Z", "atrp": 12.4 },
"attribution": "© OpenMapTiles © OpenStreetMap contributors"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
| job_id | string | The scan the map shows |
| image_base64 | string | The image, base64 encoded |
| mime_type | string | "image/png" or "image/webp" |
| width | integer | Image width in pixels: size times scale |
| height | integer | Image height in pixels: size times scale |
| style | string | "light" or "dark" |
| format | string | "png" or "webp" |
| business_name | string | The business the scan tracked |
| keyword | string | The scan's keyword |
| atrp | number | The average rank on the map, with points where the business was not found counted as 21. The scan endpoints' average_rank counts found points only, so the two differ |
| found | integer | Points where the business was found |
| points | integer | Grid points drawn |
| compared_to | object | null | The earlier scan the changes are against (job_id, date, atrp), or null when there was none or compare was false |
| attribution | string | Map credit. Keep it with the image wherever it is shown |
Notes
- Each circle is numbered with the rank at that point and coloured: green for 1-3, lime for 4-7, orange for 8-10, red for 11 and below. Grey circles are points where the business was not found (–) or that could not be checked (?). The average rank in the header is the average over every answered point, with not found counted as 21.
- When you have scanned the same keyword, business, grid size, zoom, radius and centre before, a small badge on each point shows how many places it moved since your most recent earlier scan (green up arrow improved, red down arrow slipped), and the header shows the average rank change. Pass compare: false to leave it out.
- Send Accept: image/png (or image/webp) to get the image itself instead of JSON, with X-Request-Id, X-Credits-Used and X-Credits-Remaining headers. Useful for no-code tools that can't decode base64. Sandbox keys get the placeholder the same way.
- A scan that is still running returns a 409 job_not_complete, and a failed scan a 409 job_failed; neither costs anything. Collect a running scan with geogrid status first.
- A compare_to scan that hasn't completed, isn't older, or isn't the same scan returns a 409 (baseline_not_complete, baseline_not_earlier or baseline_mismatch) and costs nothing. The automatic comparison looks at your 20 most recent earlier scans of the same keyword, grid and business.
- If the map can't be drawn the call is refunded: 502 or 504 when drawing failed or timed out, 503 when the renderer is busy (try again shortly), and 500 map_render_failed when this scan can't be drawn at all (send support the request_id).
- A job_id that does not exist or belongs to another account returns job_not_found.
- The map is drawn for each request and not stored, so ask again whenever you need it. Each request is charged.
- Returns 503 not_configured, with nothing charged, on a deployment where maps are not turned on. Sandbox keys (sk_test_) get a 1x1 placeholder image, free.