Docs
MCP server and API
Ask your AI assistant which clients dropped this week and why, or start a scan from a script. Included on every plan, Solo too.
1. Create a key
Sign in, open Settings → API and MCP and create a key. It starts with gw_ and is shown once. A key acts for your whole workspace; revoke it there at any time.
MCP endpoint: https://gridwhy.com/mcp (Streamable HTTP). Send the key as Authorization: Bearer gw_….
2. Connect your client
claude mcp add --transport http gridwhy https://gridwhy.com/mcp \
--header "Authorization: Bearer gw_your_key"{
"mcpServers": {
"gridwhy": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://gridwhy.com/mcp", "--header", "Authorization:${GRIDWHY_AUTH}"],
"env": { "GRIDWHY_AUTH": "Bearer gw_your_key" }
}
}
}Needs Node.js. The key sits in an environment variable so the space after “Bearer” survives on Windows.
{
"mcpServers": {
"gridwhy": {
"url": "https://gridwhy.com/mcp",
"headers": { "Authorization": "Bearer gw_your_key" }
}
}
}curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<model>",
"tools": [{
"type": "mcp",
"server_label": "gridwhy",
"server_url": "https://gridwhy.com/mcp",
"headers": { "Authorization": "Bearer gw_your_key" },
"require_approval": { "never": { "tool_names": ["get_history", "explain_change"] } }
}],
"input": "Which of my clients lost ground on Google Maps this week, and why?"
}'Connectors inside the ChatGPT app sign in with OAuth, which GridWhy does not offer yet; the API above takes the key directly.
3. Tools
get_historyLocations, tracked keywords and their scans, newest first: how many grid points rank in the top 20 and top 3, average and best rank, the one-line 'what changed', and a report link. Without arguments: every keyword with its latest scan, plus the manual scans left.
Arguments: location, keyword, keyword_id, limit (all optional)
explain_changeWhy the ranking changed between a scan and the one before it: findings (coverage, competitors that rose or appeared, review velocity, rating, category or name changes), each with a line to paste to the client, plus next steps. Pass scan_id, or a location and keyword for their latest finished scan.
Arguments: scan_id, location, keyword, keyword_id (all optional)
run_scanStarts a grid scan for one tracked keyword now (in addition to the schedule). Counts against the account's manual scans (per day and per 30 days); a keyword's first scan is free. Takes 15-30 seconds; then call explain_change with the returned scan_id.
Arguments: location, keyword, keyword_id (all optional)
Try: “Explain what changed for Wilson Plumbing on ‘plumber’ and write the update for the client.”
4. REST
The same three operations, the same key, limits and answers (JSON).
curl "https://gridwhy.com/api/v1/history?location=Wilson&keyword=plumber&limit=5" \
-H "Authorization: Bearer gw_your_key"curl "https://gridwhy.com/api/v1/explain?scan_id=<scan id>" \
-H "Authorization: Bearer gw_your_key"curl -X POST "https://gridwhy.com/api/v1/scans" \
-H "Authorization: Bearer gw_your_key" -H "Content-Type: application/json" \
-d '{ "location": "Wilson Plumbing", "keyword": "plumber" }'Errors come back as { "error": "…" } with 400, 401, 403, 404, 409 or 429 (with Retry-After).
5. Limits
| Plan | API calls an hour | run_scan (manual scans) |
|---|---|---|
| Solo | 100 | 5 a day, 30 per 30 days |
| Agency | 500 | 20 a day, 100 per 30 days |
| Agency+ | 2,000 | 50 a day, 250 per 30 days |
Scheduled scans are never limited by the API. The free trial has Solo’s limits. A key stops working when a trial ends or a subscription is canceled.