API

The same leads,
from your own code.

No separate plan, no extra charge, no different data. The API and the dashboard are the same code path, so a call can never return more than the same customer sees on screen, and a credit costs exactly what it costs anywhere else.

Getting started

Two minutes

  1. Sign up and take the 3 free credits.
  2. Create a key under AI apps and API in the dashboard. It is shown once, then stored as a hash we cannot reverse.
  3. Send it as a bearer token on every request.
curl -X POST https://www.fresh-leads.io/api/v1/leads \
  -H "Authorization: Bearer fl_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"niche":"dentists","location":"Austin, TX","limit":20}'
AI apps

Use it from Claude, ChatGPT or Cursor

Fresh Leads works as an MCP connector, the standard way AI apps use outside tools. Add this address, sign in, and ask in plain words: “find 20 dentists in Austin with no website and open the best five.”

https://www.fresh-leads.io/api/mcp
Claude
Settings, then Connectors, then Add custom connector. Paste the address and connect.
ChatGPT
Settings, then Apps and Connectors, then Create. Custom connectors may need Developer mode switched on.
Cursor
Settings, then MCP, then Add new MCP server, and paste the address.
Claude Code
claude mcp add --transport http fresh-leads https://www.fresh-leads.io/api/mcp
VS Code
Command Palette, then MCP: Add Server, then HTTP, and paste the address. Use it from Copilot Chat in agent mode.
Gemini CLI
gemini mcp add --transport http fresh-leads https://www.fresh-leads.io/api/mcp
Any other app
Anything that supports remote MCP over HTTP. Sign in when asked, or send your API key as Authorization: Bearer fl_live_...

What the AI can do

ToolWhat it doesCost
search_leadsFind businesses for a trade in an area. A slow search returns a searchId instead of making the AI wait.Free
get_search_resultsCollect the results of a search that returned a searchId.Free
my_leadsThe leads you have already opened, newest first, plus your balance and plan.Free
draft_emailA first email to a lead you have opened, written from what we found there. Nothing is sent.Free
unlock_leadOpen a lead: verified phone, email, address and what to pitch.1 credit, never twice for the same business
reveal_ownerThe person who runs the business, where we can find one.1 credit
export_leadsLeads as CSV or JSON, or ready for HubSpot or Salesforce.Free for opened leads, 1 credit for each locked one
enrich_listFill in the gaps in a list you already have.1 credit per row enriched
buy_creditsA Stripe checkout link for you to open and pay. The AI cannot pay.Nothing until you pay

What keeps it safe

  • You sign in with your Fresh Leads account, including your second factor, and see what the app will be allowed to do before you allow it.
  • Each connected app gets its own key, shown under AI apps and API in the dashboard as MCP followed by the app's name. Revoke it to disconnect.
  • An AI app can spend at most 30 credits in one action. Anything bigger is refused, so a misled AI cannot drain your balance. Larger jobs are done on the website or the plain API.
  • The same rate limits apply as everywhere else, and the connector is part of the yearly plan, like the API.
Endpoints

Everything you can call

POST/api/leads/unlock

Open a lead

Spend one credit to reveal a lead in full: verified phone, verified email, address, the grade breakdown and what to pitch.

One credit. Charged once per business, forever. Opening the same lead again is free.
Body
leadId
string, required. The id from a search result.
Returns
{ lead: Lead, creditsLeft: number }
  • The charge happens inside one database function, so two calls at once cannot spend two credits on the same business.
  • If the phone and mailbox both turn out to be dead, you are not charged at all.
POST/api/v1/my-leads

Your leads and balance

Every lead your account has opened, newest first and in full, with your credit balance and plan status. A lead a teammate opened is yours too, and is listed.

Free. Reading what you already own never spends a credit.
Body
limit
number, 1 to 200. Defaults to 50.
offset
number. Where to start, for the next page.
Returns
{ credits: number, subscribed: boolean, totalUnlocked: number, leads: Lead[] }
POST/api/leads/owner

Reveal the owner

The person who runs the business, where we can find one: name, role, and a personal email or profile if it exists.

One credit, once, permanently.
Body
leadId
string, required. Must already be open.
Returns
{ owner: Owner | null, creditsLeft: number }
  • The lead has to be open first: selling the owner of a business you cannot otherwise see would be selling a fragment.
  • We find an owner on roughly four in ten businesses, and it varies by trade: a dental practice or a vet usually names the practitioner, a restaurant or a salon usually does not. When we are not confident, we return null rather than a guess.
POST/api/leads/draft-email

Write the first email

A first cold email to an opened lead, written from what we found there: the specific problem, the change, the hiring post. Edit it and send it from your own mailbox.

Free for leads you have opened.
Body
leadId
string, required. Must already be open.
Returns
{ subject: string, body: string, ai: boolean, to: string | null }
  • The draft uses only facts we checked about the business. It never invents details, results or client names.
  • ai is false when the draft came from a template instead of the model, for example during an outage. It is still built from the same findings.
  • The owner's name is used only if you have revealed the owner.
POST/api/leads/export

Export

Take leads out as a spreadsheet, a JSON payload, a printable call sheet, or under the column names HubSpot and Salesforce expect.

Free for leads you have already opened. One credit each for any that are still locked.
Body
leadIds
string[], 1 to 1000 ids.
format
string: csv, xlsx, json, pdf, hubspot or salesforce. Defaults to csv.
Returns
A file, with the matching content type.
POST/api/enrich

Enrich your own list

Send a CSV of businesses you already have and get it back with the gaps filled: verified phone and email, the owner where findable, and what we know about their website.

One credit per row we actually enrich. A row we cannot identify comes back untouched and costs nothing.
Body
file
multipart/form-data, up to 500 rows.
Returns
A CSV with our columns appended, plus fl_status on every row.
When something goes wrong

Errors

ResponseWhat it means
401No key, or a key that has been revoked.
402 subscription_requiredThe account needs the yearly plan.
402 insufficient_creditsNot enough credits for that call.
429 rate_limitedToo many calls. Retry-After says how long to wait. Per account, per hour: 60 searches, 300 unlocks, 300 owner reveals, 30 exports, 20 enrich uploads.
400The body did not match the shape above.
500Our fault. Safe to retry: every paid action is idempotent. The body carries a short `reference`; quote it and we can find the exact failure in our logs.

Every paid action is idempotent, so retrying a call that failed halfway cannot charge you twice. Opening the same lead again is free whether it is the second attempt or the fiftieth.

Build against it free

3 free credits, no card. Enough to search, open a lead and see the exact shape of what comes back before you write a line of integration.