BasedOnB Documentation
Automate Google Maps lead scraping with the REST API, or connect directly to your AI assistants via the MCP server.
Ready to build?
Generate your first API key in Settings and start scraping in minutes.
Automate Google Maps lead scraping with the REST API, or connect directly to your AI assistants via the MCP server.
Generate your first API key in Settings and start scraping in minutes.
curl https://www.basedonb.com/api/v1/account \
-H "Authorization: Bearer bdb_live_YOUR_KEY_HERE"All API requests (except GET /health) require an API key. Generate one from API & Webhooks → API Keys.
Pass your key in one of two ways:
Authorization header (recommended)
Authorization: Bearer bdb_live_...
X-API-Key header
X-API-Key: bdb_live_...
Use the REST API from a trusted backend. Browser cross-origin requests are intentionally disabled, and API keys must never be exposed in client-side code.
REST responses include X-Request-Id. Authenticated requests also include RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset; limited requests include Retry-After.
https://www.basedonb.com/api/v1
100 requests / minute per API key. Exceeding this returns 429.
Look up the country / state / city values accepted by the Scrapes API. States follow the GeoNames dotted code format (US.CA, TR.34, DE.BE). Countries without a state subdivision return an empty states array. Submit those jobs with only country.
Webhooks deliver real-time event notifications to your endpoint. Each request includes an X-Webhook-Signature header for verification.
API keys are created and revoked only from the authenticated dashboard. Choose the minimum required scopes when creating a key: mcp, scrapes:read, scrapes:write, account:read, geodata:read, webhooks:read, and webhooks:write. Keys cannot create or manage other keys through the public API.
Example scrape.done payload delivered to your endpoint:
POST https://your-server.com/webhook
Content-Type: application/json
X-Webhook-Id: delivery-uuid
X-Webhook-Event-Id: event-uuid
X-Webhook-Timestamp: 2026-07-18T10:05:00Z
X-Webhook-Signature: v1=abc123...
X-Event-Type: scrape.done
User-Agent: BasedOnB-Webhook/2.0
{
"id": "event-uuid",
"event": "scrape.done",
"created_at": "2026-01-15T10:05:00Z",
"data": {
"scrape_id": "job-uuid",
"query": "restaurants",
"queries": ["restaurants"],
"city": "Istanbul",
"country": "TR",
"state": "TR.34",
"state_name": "İstanbul",
"status": "done",
"leads_found": 47,
"credits_charged": 47,
"error": null,
"results_path": "/api/v1/scrapes/job-uuid/results"
}
}Verify the X-Webhook-Signature header to ensure requests come from BasedOnB. Save the signing secret shown once when the webhook is created or rotated.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyWebhook(body: string, timestamp: string, signature: string, secret: string): boolean {
const match = /^v1=([0-9a-f]{64})$/i.exec(signature);
if (!match) return false;
const expected = createHmac("sha256", secret)
.update(timestamp + "." + body)
.digest();
const received = Buffer.from(match[1], "hex");
return received.length === expected.length && timingSafeEqual(received, expected);
}
// In your endpoint handler:
const body = await req.text();
const sig = req.headers.get("X-Webhook-Signature") ?? "";
const timestamp = req.headers.get("X-Webhook-Timestamp") ?? "";
if (!verifyWebhook(body, timestamp, sig, process.env.WEBHOOK_SECRET!)) {
return new Response("Unauthorized", { status: 401 });
}Return any 2xx status to acknowledge delivery. Failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, and 2 hours, for at most 5 attempts. Store X-Webhook-Event-Id and ignore events already processed. The timestamp is the event creation time and remains unchanged across retries, so do not reject a valid retry solely because that timestamp is old.
| HTTP Status | Code | Description |
|---|---|---|
| 400 | bad_request | Invalid request parameters |
| 401 | unauthorized | Missing, invalid, expired, or revoked credential |
| 402 | insufficient_credits | Not enough credits to start a scrape |
| 402 | payment_required | Subscription payment is past due |
| 403 | forbidden | Credential is missing the required scope |
| 404 | not_found | Resource not found |
| 409 | conflict | Idempotency-key conflict or resource limit conflict |
| 429 | rate_limited | Per-key request limit, webhook-test limit, or open scrape capacity limit exceeded |
| 500 | internal_error | Unexpected server error |
| 503 | service_unavailable | A required dependency is unavailable |
Error response format:
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits. You have 3 but need 50."
}
}OAuth-capable clients can connect without copying a long-lived API key. BasedOnB uses authorization code + PKCE, rotates refresh tokens, and lets you revoke access from the dashboard.
https://www.basedonb.com/api/mcpCustom remote connectors are available on Claude Pro, Max, Team, and Enterprise. In Claude Desktop, add remote servers from Settings → Connectors.
https://www.basedonb.com/api/mcpFull custom MCP apps, including BasedOnB's write tools, are currently available on the web for ChatGPT Business, Enterprise, and Edu workspaces when an admin enables developer mode.
https://www.basedonb.com/api/mcpChatGPT Pro developer mode supports remote MCP read/fetch tools, but BasedOnB also includes write tools such as submit_scrape and cancel_scrape. Plus is not supported for custom MCP apps. Availability is controlled by OpenAI and workspace policy.
Use the built-in MCP Client Tool node version 1.2 or newer.
https://www.basedonb.com/api/mcpConnect BasedOnB to Claude, ChatGPT, n8n, Cursor, or another Streamable HTTP MCP client. OAuth connectors and API keys share the same account credits and expose 10 tools.
For local clients that use static credentials, create a minimum-scope API key from API & Webhooks, then use the MCP URL and Authorization header below. Claude Desktop remote servers must be added from Settings → Connectors, not claude_desktop_config.json.
Pick your client, copy the snippet. Replace the placeholder key with your own.
claude mcp add --transport http basedonb https://www.basedonb.com/api/mcp \
--header "Authorization: Bearer bdb_live_xxxxxxxxxxxxxxxxx"Run this from the project where you want to use BasedOnB. Claude Code stores it in local project scope by default; use --scope user for all projects.
Every tool also returns the same payload under structuredContent.data, alongside JSON text content. Tool errors set isError=true and include the API error code and HTTP status.
The MCP endpoint accepts either an OAuth access token with the mcp scope or a bdb_live_… API key that includes the mcp scope.
Supported authentication methods:
Authorization: Bearer eyJ...Authorization: Bearer bdb_live_...BasedOnB implements authorization code with PKCE, Dynamic Client Registration (RFC 7591), Authorization Server Metadata (RFC 8414), and Protected Resource Metadata (RFC 9728). The only OAuth scope is mcp.
GET /.well-known/oauth-protected-resource: Protected resource metadata (RFC 9728).GET /.well-known/oauth-authorization-server: Authorization server metadata (RFC 8414).POST /oauth/register: Public-client Dynamic Client Registration; PKCE S256 is required.GET /oauth/authorize: Sign-in and consent endpoint for the authorization-code flow.POST /oauth/token: Exchanges a code or rotating refresh token for tokens.POST /oauth/revoke: Revokes a refresh token and its token family (RFC 7009).Access tokens are HS256 JWTs with a 15-minute lifetime. Refresh tokens are opaque, expire after 30 days, rotate on every use, and revoke their entire family if reuse is detected. Authorization codes expire after 60 seconds.