# GeoGrid Rank Tracker API > GeoGrid Rank Tracker scans how a business ranks in Google local search results across a geographic grid. Submit a scan with a business name, keyword, and center coordinates, then retrieve an interactive Leaflet.js heatmap showing rank at each grid point. ## Base URL `https://YOUR_DOMAIN/dominator` All endpoints below are relative to this base URL. ## Discovery - `GET /dominator/llms.txt` — This documentation - `GET /dominator/.well-known/llms.txt` — Redirects to `/dominator/llms.txt` - `GET /dominator/robots.txt` — Robots file with `Llms-Txt` directive ## Authentication All API endpoints (except `/health`, `/scan/{scan_id}/map`, `/llms.txt`, `/robots.txt`) require an `X-API-Key` header. ``` X-API-Key: your_api_key_here ``` ## Endpoints ### GET /health Health check. No authentication required. **Response:** ```json {"status": "ok"} ``` --- ### POST /scan Create a new geogrid scan. The scan runs asynchronously in the background. **Headers:** - `X-API-Key` (required): Your API key - `Content-Type: application/json` **Request Body (JSON):** | Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `business` | string | Yes | — | Business name to track. Can also be a Google Place ID (starts with "ChIJ"). | | `keyword` | string | Yes | — | Search keyword (e.g. "plumber", "dentist near me"). | | `lat` | float | Yes | — | Center latitude of the grid. | | `lng` | float | Yes | — | Center longitude of the grid. | | `grid_size` | int | No | 7 | Grid dimension. Must be one of: 3, 5, 7, 9, 13, 15. Creates an NxN grid (e.g. 7 = 49 points). | | `grid_spacing_m` | int | No | 3219 | Distance between grid points in meters. Default is ~2 miles (3219m). | | `scan_type` | string | No | "local_finder" | Search type: `"local_finder"`, `"maps"`, `"both"`, or `"organic"`. | **Example Request:** ```bash curl -X POST https://YOUR_DOMAIN/dominator/scan \ -H "X-API-Key: your_api_key" \ -H "Content-Type: application/json" \ -d '{ "business": "Dzala General Contractor LLC", "keyword": "general contractor", "lat": 38.9186, "lng": -77.2311, "grid_size": 7, "grid_spacing_m": 3219, "scan_type": "local_finder" }' ``` **Response (202-style):** ```json { "scan_id": "sc_a1b2c3d4e5", "status": "processing", "points": 49, "estimated_seconds": 98, "poll_url": "/dominator/scan/sc_a1b2c3d4e5", "html_url": "/dominator/scan/sc_a1b2c3d4e5/map" } ``` **Scan Types Explained:** - `local_finder` — Google Local Finder results (default, recommended). Shows the local business listings that appear when users click "More businesses" on Google. - `maps` — Google Maps search results. - `both` — Runs both `maps` and `local_finder` at each point (2x the cost). Uses maps rank as the primary display rank. - `organic` — Standard organic search results, filtering out directory sites (Yelp, Facebook, etc.). --- ### GET /scans List all scans for the authenticated API key. Returns up to 200 scans, sorted newest first. Does not include the heavy `points` data — use `GET /scan/{scan_id}` for full results. **Headers:** - `X-API-Key` (required): Your API key **Response:** ```json [ { "scan_id": "sc_a1b2c3d4e5", "status": "complete", "business": "Dzala General Contractor LLC", "keyword": "general contractor", "grid_size": 7, "scan_type": "local_finder", "created_at": "2026-02-09 01:59:31.750000", "summary": { "avg_rank": 4.76, "top3_pct": 0.35, "not_found_pct": 0.14 }, "html_url": "/dominator/scan/sc_a1b2c3d4e5/map" } ] ``` --- ### GET /scans/view Browser-friendly HTML page listing all scans. Pass API key as a query parameter. **No header needed** — use `?api_key=` instead. If no key is provided, shows a login form. **URL:** ``` https://YOUR_DOMAIN/dominator/scans/view?api_key=your_api_key ``` Displays a table with scan ID (linked to map), status, business, keyword, grid size, type, avg rank, top 3%, and creation date. --- ### GET /scan/{scan_id} Poll scan status or retrieve completed results. Scans are scoped to the API key that created them. **Headers:** - `X-API-Key` (required): Must match the key used to create the scan **Response (processing):** ```json { "scan_id": "sc_a1b2c3d4e5", "status": "processing", "progress": "12/49" } ``` **Response (complete):** ```json { "scan_id": "sc_a1b2c3d4e5", "status": "complete", "business": { "place_id": "ChIJb0nIRwazt4kRyBAuQXFQwns", "cid": "8917778659502067912", "name": "Dzala General Contractor LLC", "address": "1934 Old Gallows Rd Suite 350, Tysons, VA 22182" }, "keyword": "general contractor", "grid_size": 7, "html_url": "/dominator/scan/sc_a1b2c3d4e5/map", "summary": { "avg_rank": 4.76, "top3_pct": 0.35, "not_found_pct": 0.14 }, "points": [ { "row": 0, "col": 0, "lat": 38.8319, "lng": -77.3178, "rank": 3, "top_results": [ { "rank": 1, "name": "Some Contractor", "place_id": "ChIJ...", "cid": "123...", "rating": 4.8, "reviews": 125, "address": "123 Main St..." } ] } ] } ``` **Response (failed):** ```json { "scan_id": "sc_a1b2c3d4e5", "status": "failed", "error": "Business not found: Invalid Business Name" } ``` --- ### GET /scan/{scan_id}/map Interactive HTML map visualization. **No authentication required** — this URL is shareable. - While processing: shows a spinner with progress bar (auto-refreshes every 5 seconds) - On completion: renders a full Leaflet.js map with color-coded rank markers - On failure: shows error message **Rank Color Legend:** - Green: Rank 1-3 - Yellow: Rank 4-10 - Red: Rank 11-20 - Gray: Not found in top 20 Click any grid point on the map to see the full top-20 rankings in the right panel. --- ## Workflow 1. **Submit scan** via `POST /dominator/scan` — returns `scan_id` 2. **Poll status** via `GET /dominator/scan/{scan_id}` — check `status` field until `"complete"` or `"failed"` 3. **View results** via `GET /dominator/scan/{scan_id}/map` in a browser, or parse the JSON from step 2 4. **List all scans** via `GET /dominator/scans` — see history of all your scans Typical processing time: 60-120 seconds for a 7x7 grid (49 points). ## Error Codes | Code | Description | |------|-------------| | 400 | Invalid request body (missing fields, invalid grid_size, invalid scan_type) | | 401 | Invalid or missing API key | | 404 | Scan not found (or belongs to different API key) | ## Summary Fields | Field | Description | |-------|-------------| | `avg_rank` | Average rank across all grid points where the business was found. `null` if never found. | | `top3_pct` | Fraction of total grid points where business ranked 1-3 (0.0 to 1.0). | | `not_found_pct` | Fraction of total grid points where business was not in top 20 (0.0 to 1.0). | ## Cost Uses DataForSEO Standard mode (normal priority). Cost per grid point: ~$0.0012. A 7x7 grid (49 points) costs ~$0.06. Using `scan_type: "both"` doubles the cost.