Lyre Leads API
Integrate AI-powered Google Maps lead generation directly into your applications, AI agents, LangChain pipelines, and automation workflows. Search businesses, retrieve 50+ company-level data points per lead, including verified emails, AI-discovered contacts with personal LinkedIn profiles, and 1,200+ tech stack detections, each one judged against the query you searched for. All via a simple REST API.
Quick Start
Get your first API call working in under 2 minutes.
Get an API Key
Log in → Account → API Keys → Generate Key. Save it immediately, shown once.
Check Your Balance
Call GET /api/v1/balance with your Bearer key to confirm it works.
Search for Leads
Call POST /api/v1/search with query, city, and country.
Keep what matched
Every enriched row carries relevance and the quote behind it. Filter on "yes".
First API call
curl https://lyreleads.com/api/v1/balance \
-H "Authorization: Bearer lyre_your_api_key_here"
import requests
API_KEY = "lyre_your_api_key_here"
BASE_URL = "https://lyreleads.com"
headers = {"Authorization": f"Bearer {API_KEY}"}
resp = requests.get(f"{BASE_URL}/api/v1/balance", headers=headers)
print(resp.json())
# {'tier': 'Growth', 'tokens_balance': 4500, 'tokens_monthly_allocation': 5000, ...}
const res = await fetch('https://lyreleads.com/api/v1/balance', {
headers: { 'Authorization': 'Bearer lyre_your_api_key_here' }
});
const data = await res.json();
console.log(data.tokens_balance); // 4500
Authentication
All API v1 requests require an API key sent as a Bearer token in the Authorization header:
Authorization: Bearer lyre_<your-64-hex-key>
API keys are scoped to your account. They inherit your token balance and tier permissions. You can create up to 10 active keys per account and revoke them at any time from the Account page.
Error Handling
The API uses standard HTTP status codes. All error responses are JSON with an error field:
| Status | Meaning | Common cause |
|---|---|---|
| 200 | OK | Request succeeded |
| 400 | Bad Request | Missing required field or invalid parameter |
| 401 | Unauthorized | Missing, invalid, or revoked API key |
| 402 | Payment Required | Insufficient tokens, buy more or wait for monthly reset |
| 403 | Forbidden | Plan upgrade required, or account suspended |
| 404 | Not Found | Resource not found (model, result) |
| 429 | Too Many Requests | Rate limit exceeded (120 req/min per key) |
| 500 | Server Error | Something went wrong on our end |
{
"error": "Insufficient tokens.",
"tokens_needed": 20,
"tokens_balance": 5,
"upgrade_url": "/pricing"
}
Rate Limits
The API allows 120 requests per minute per API key. Exceeding this returns a 429 response. The limit resets every 60 seconds.
Each search result or AI evaluation costs 1 token. Check your balance at any time via GET /api/v1/balance.
MCP Server (AI Agents)
Lyre Leads ships a Model Context Protocol endpoint, so Claude, Cursor, and any MCP-compatible client can search markets, enrich them, find and verify decision-maker emails, and read the relevance verdict on each result directly. It exposes nine tools: search_leads, list_results, estimate_list, count_saved_leads, enrich_leads, find_decision_makers, verify_emails, get_job_status, and get_balance, backed by the same routes documented below (same auth, limits, and token costs).
count_leads is free and exact at any size. Agents should size a segment before spending on it, so counting is never billed and never rationed.
Point your agent at lyreleads.com/for-agents first.
It is a working guide written for an AI assistant rather than a human: what each field means,
what a blank value does and does not tell you, where our coverage is weak, and the four mistakes
that produce confidently wrong lead lists. Raw markdown at /for-agents.md.
Building a client on top of this API? lyreleads.com/build carries complete,
implementable specs an AI coding agent can follow to build a local dashboard, territory runner,
outreach queue or change monitor in about one session each.
Connect via streamable HTTP with your API key as a bearer token:
{
"mcpServers": {
"lyre-leads": {
"type": "http",
"url": "https://lyreleads.com/mcp",
"headers": { "Authorization": "Bearer lyre_your_key_here" }
}
}
}
Typical agent flow: search_leads for a keyword and city, then poll list_results with the returned search_id while background enrichment fills in emails, verification status, tech stack, and the relevance verdict, then filter on relevance: "yes" before you spend anything else on the batch.
Endpoints
Token Balance
No request body required.
Response
{
"tier": "Growth",
"tokens_balance": 4500,
"tokens_monthly_allocation": 5000,
"tokens_reset_date": "2026-02-01T00:00:00.000Z",
"tokens_next_reset": "2026-03-01T00:00:00.000Z"
}
Search for Leads
Request Body
| Parameter | Type | Description |
|---|---|---|
| queryrequired | string | Business type or keyword (e.g. "plumbers") |
| cityrequired | string | City to search in (e.g. "Berlin"). For disambiguation, include the region: "London, England" or "Springfield, Illinois" |
| countryrequired | string | Country name (e.g. "Germany") |
| pagesoptional | integer 1–5 | Pages of results (20 results/page). Default: 1 |
{
"query": "plumbers",
"city": "Berlin",
"country": "Germany",
"pages": 2
}
{
"results": [
{
"name": "Müller Plumbing GmbH",
"address": "Hauptstraße 42, 10115 Berlin",
"phone": "+49 30 12345678",
"website": "https://mueller-plumbing.de",
"rating": 4.7,
"review_count": 183,
"type": "Plumber"
}
],
"results_count": 40,
"tokens_used": 40,
"tokens_remaining": 4460,
"query": "plumbers",
"city": "Berlin",
"country": "Germany"
}
Python example
resp = requests.post(
f"{BASE_URL}/api/v1/search",
headers=headers,
json={
"query": "plumbers",
"city": "Berlin",
"country": "Germany",
"pages": 2
}
)
data = resp.json()
for biz in data["results"]:
print(biz["name"], biz.get("website", ", "))
Retrieve Past Results
| Query param | Type | Description |
|---|---|---|
| limitoptional | integer | Results per page (default 20, max 100) |
| offsetoptional | integer | Pagination offset (default 0) |
| queryoptional | string | Filter by search query (partial match) |
| search_idoptional | integer | Filter by search history ID |
curl "https://lyreleads.com/api/v1/results?limit=50&query=plumbers" \
-H "Authorization: Bearer lyre_..."
{
"results": [ /* array of result objects */ ],
"total": 2540,
"limit": 50,
"offset": 0,
"has_more": true
}
Each result object contains enrichment data including email, facebook_url, instagram_url, linkedin_url, has_facebook_pixel, has_google_analytics, cms_platform, tech_stack (JSON array of all 200+ detected technologies), plus categorized tech columns: tech_frameworks, tech_analytics, tech_advertising, tech_marketing, tech_ecommerce, tech_customer_tools, tech_infrastructure. Boolean signals: has_ad_pixels, has_marketing_automation, has_ecommerce, has_reviews_widget, has_scheduling. AI visibility: ai_crawler_access (open/partial/blocked/unknown, whether the site's robots.txt blocks AI crawlers like GPTBot, ClaudeBot, PerplexityBot), ai_bots_blocked, has_llms_txt. Also includes chat_widget, booking_system, crm_platform, has_ssl, contact_name, contact_title, contact_linkedin, relevance, and relevance_evidence.
Relevance
Google Maps returns businesses that are not what you asked for. Across 284 businesses we hand-checked, 72.2% of results matched the keyword, ranging from 95.8% for roofing contractor to 28.0% for home remodeling contractors.
So enrichment reads each company's own website and judges it against the query that row came from. The verdict ships with the sentence that justifies it, quoted from the page, so you can audit any call we make. This runs automatically on every enriched lead and costs nothing beyond the search token.
| Field | Type | Description |
|---|---|---|
| relevance | string | yes, no, unclear, or null. null means never judged (no website, unreadable page, or a row created without a query). It never means "no". |
| relevance_evidence | string | The phrase copied verbatim from the company's page that justifies the verdict. |
// POST /api/v1/count, free at any size
{
"filters": { "relevance": "yes", "has_email": true }
}
// A row from GET /api/v1/results
{
"name": "Bergen Roofing & Sheet Metal",
"query": "roofing contractor",
"relevance": "yes",
"relevance_evidence": "Residential and commercial roof replacement since 1994"
}
In a 284-business study we published, a model reading the company's website kept 98.8% of the genuine businesses, against 87.4% for filtering on the Google Maps category, which silently discards about one real business in eight. That measures the method rather than this exact check, and both raters in the study were language models, which is the weakness. We publish the study including the half that argues against us.
OpenAPI Spec
Returns a complete OpenAPI 3.0 spec. Use this to auto-configure LLM tool-use, Postman, Swagger UI, or any OpenAPI-compatible tooling. No API key required to fetch the spec.
from langchain.tools import OpenAPISpec, APIOperation
from langchain.chains import OpenAPIEndpointChain
spec = OpenAPISpec.from_url("https://lyreleads.com/api/v1/openapi.json")
# Agent can now auto-discover and call Lyre Leads endpoints
Lyre Leads