One endpoint for finding business contacts by industry, city, or country — your own vocabulary, not low-level pass-through parameters.
The B2BLeads API is a single MCP-friendly discovery endpoint. Base URL:
https://api.b2bleadsapi.comEvery response is JSON. There is no SDK required — plain HTTPS requests work from any language or from an AI agent's native tool-calling.
Pass your API key as a bearer token. Create keys from the dashboard under API Keys.
Authorization: Bearer b2bl-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxRequests without a valid key return 401 Unauthorized. Each key is rate-limited per minute and capped by your plan's monthly search quota.
Finds companies matching your own search vocabulary — clean, purpose-built options rather than low-level request fields. At least one of q, industry, or city is required.
| Parameter | Type | Description |
|---|---|---|
| q | string | Free-text query, e.g. "family-owned bakeries". Optional if industry or city is set. |
| industry | enum | One of our own industry values — see GET /v1/search-leads/industries for the full list. |
| city | string | City or region name, e.g. "Munich" or "Austin, TX". Combine with radius_km for a bounded search. |
| radius_km | number | Search radius around city, in kilometers (max 50). Ignored without city. |
| min_rating | number 0–5 | Only return companies with at least this rating, filtered server-side for accurate pagination. |
| has_website | boolean | true to only return companies with a listed website. |
| verified_only | boolean | true to exclude permanently/temporarily closed businesses. |
| open_now | boolean | true to only return businesses that are currently open. |
| price_level | enum, comma-separated | One or more of: budget, moderate, expensive, luxury. E.g. price_level=budget,moderate. |
| rank_by | enum | relevance (default) or distance. distance requires city to be set. |
| limit | number 1–20 | Max results per page. Defaults to 20 (per-request cap). |
| page_token | string | Value from a previous response's nextPageToken, to fetch the next page. When set, all other filters are ignored (already baked into the token). |
| lang | string | Language for result names/addresses, e.g. "pt" or "pt-BR". Overrides your account's dashboard language for this request; falls back to it when omitted. |
| list_id | string | Save these results into an existing saved list you own. Adds a savedTo object to the response. |
| list_name | string | Save into a list with this name, creating it if it doesn't exist yet. Ignored if list_id is also set. |
| save_to_list | boolean | true saves into a list named "API searches" (created on first use) when neither list_id nor list_name is given. |
curl "https://api.b2bleadsapi.com/v1/search-leads?industry=construction&city=Munich&radius_km=25&min_rating=4&has_website=true&open_now=true&rank_by=distance" \
-H "Authorization: Bearer b2bl-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"results": [
{
"id": "ChIJ...",
"name": "Bauunion GmbH",
"address": "Landsberger Str. 12, 80339 München",
"phone": "+49 89 1234567",
"website": "https://bauunion.de",
"rating": 4.7,
"ratingCount": 128,
"status": "OPERATIONAL",
"priceLevel": null,
"openNow": true
}
],
"nextPageToken": "AY1v..."
}Pass nextPageToken back as page_token to fetch the next page. It's null once there are no more results.
Note for AI agents: on plans with Email Finder, a saved lead's email field can come back as the literal string CFD* instead of an address. This means every scrape attempt (a plain HTTP fetch, then a headless-browser fallback) was blocked by the target site's Cloudflare bot protection — it is not an empty result and not an error, and retrying the same site will not succeed. Treat CFD* as "no email available" rather than as a real address, and don't report it to the end user as their contact email.
Public, unauthenticated endpoint — returns the current list of supported industry values, so clients and agents never need to hardcode them.
curl "https://api.b2bleadsapi.com/v1/search-leads/industries"{
"industries": [
{ "value": "construction", "label": "Construction" },
{ "value": "restaurants", "label": "Restaurants" },
{ "value": "retail", "label": "Retail" },
{ "value": "manufacturing", "label": "Manufacturing" },
{ "value": "logistics", "label": "Logistics & Freight" },
{ "value": "it_services", "label": "IT Services" },
{ "value": "healthcare", "label": "Healthcare" },
{ "value": "real_estate", "label": "Real Estate" },
{ "value": "hospitality", "label": "Hospitality" },
{ "value": "professional_services", "label": "Professional Services" }
]
}Errors are plain JSON with a single error field.
| Parameter | Type | Description |
|---|---|---|
| 400 | Bad Request | Missing all of q/industry/city, unknown industry/price_level/rank_by value, rank_by=distance without city, or an out-of-range radius_km/min_rating/limit. |
| 401 | Unauthorized | Missing or invalid API key. |
| 402 | Payment Required | Monthly search quota exceeded for this key's plan. |
| 403 | Forbidden | Account is suspended or banned. |
| 429 | Too Many Requests | Per-key rate limit exceeded — back off and retry. |
| 502 | Bad Gateway | Upstream discovery provider failed; safe to retry. |
| 503 | Service Unavailable | Lead search is temporarily disabled via feature flag. |
Each API key has a per-minute rate limit and a monthly search quota, both set by your plan. Check current usage anytime from the dashboard's Billing page, or via the GET /v1/billing endpoint if you're authenticated with a session token.
We publish an official MCP server that wraps this API as a search_leads tool for Claude Desktop, Claude Code, Cursor, and any other MCP-compatible client — no manual REST integration needed.
Add it to your MCP client config with an API key from the API Keys page:
{
"mcpServers": {
"b2bleads": {
"command": "npx",
"args": ["-y", "b2bleads-mcp"],
"env": {
"B2BLEADS_API_KEY": "your-api-key-here"
}
}
}
}Prefer to wire it up yourself over plain REST? The parameters above map directly to the tool's input schema — the agent picks an industry and city in plain language, and B2BLeads takes care of translating that into a live discovery query behind the scenes.
{
"name": "search_leads",
"description": "Find companies by industry, city and radius",
"parameters": {
"q": "string, optional free-text query",
"industry": "enum, see /v1/search-leads/industries",
"city": "string",
"radius_km": "number, max 50",
"min_rating": "number 0-5",
"has_website": "boolean",
"verified_only": "boolean",
"open_now": "boolean",
"price_level": "enum, comma-separated: budget, moderate, expensive, luxury",
"rank_by": "enum: relevance, distance (requires city)",
"limit": "number 1-20",
"page_token": "string, from a previous response's nextPageToken"
}
}