# From companies to leads

Company, then a signal, then people by role, then why this lead, then a contact. A prompt, the MCP tool, and the REST call at every step.

The base URL is `https://foundermcp.dev/api/v1`. REST sends `Authorization: Bearer gtk_…`, with the key from **API Access → API Keys**. MCP is `POST https://foundermcp.dev/api/v1/mcp` with the same key. A missing, invalid or revoked key is **401** on every `/api/v1` call, including while an API is closed. A valid key while the Company API or the Signals API is closed for your organization answers **404** on those routes. People search, people enrich and usage answer for every valid key.

Each step below is something you can say to the assistant, the tool that runs, and the REST call that does the same thing. Call `preview_cost` before a step that can spend credits. `max_credits` stops the call before the next row would pass the cap. A row that does not fit is left out and not charged.

## 1. Company

Say: "Look up Acme Analytics and use that company page."

**MCP** — `lookup_company`. Free.

```json
{ "name": "lookup_company", "arguments": { "name": "Acme Analytics" } }
```

**REST** — `GET /companies/lookup?q=Acme%20Analytics`. Free. Only pages whose name matches.

Enriching that company (`enrich` with a company, or `POST /company/enrich`) is **1 credit** when a company is found. [Search companies](/docs/api-reference/search-companies) is the same **1 credit** per company on the page.

## 2. Signal or context

Say: "Who reacted to that company's posts in the last 30 days? Show me the cost first, then keep the finance leaders in Belgium."

**MCP** — `preview_cost` (free), then `search_signals`. Everyone who reacted or commented comes back as LinkedIn shows them: name, headline, what they did and the post. No AI judged them. A person is **5 credits**. A search that finds nobody costs nothing.

```json
{ "name": "preview_cost", "arguments": { "endpoint": "searches", "body": { "signal": { "type": "linkedin_engagement", "company": { "linkedin_url": "https://www.linkedin.com/company/acme-analytics" }, "leads_from": "reactors" }, "mode": "raw", "limit": 25, "max_credits": 125 } } }
```

```json
{ "name": "search_signals", "arguments": { "signal": { "type": "linkedin_engagement", "company": { "linkedin_url": "https://www.linkedin.com/company/acme-analytics" }, "leads_from": "reactors" }, "limit": 25, "max_credits": 125 } }
```

Then the assistant judges: it reads each row's `person.headline` and the `post_snippet` of what they did, keeps the finance leaders in Belgium, and enriches only those (step 5). [Recipes](/docs/guides/recipes) explains what a raw row holds.

To let FounderMCP judge instead, `find_leads` runs the same signal screened: our AI checks every person against a buyer profile. An exact lead is **20 credits**. Someone just outside is **5 credits**.

```json
{ "name": "find_leads", "arguments": { "signal": { "type": "linkedin_engagement", "company": { "linkedin_url": "https://www.linkedin.com/company/acme-analytics" }, "leads_from": "reactors" }, "buyer_profile": { "roles": ["finance"], "levels": ["c_level"], "countries": ["BE"] }, "max_leads": 5, "max_credits": 100 } }
```

Both wait up to 25 seconds. If the search is still running, call `get_search_results` (raw) or `find_leads` (screened) again with `search_id`. The MCP POST sends `Accept: application/json, text/event-stream`.

**REST** — `POST /searches/preview`, then `POST /searches` with the same body and a required `Idempotency-Key`. Mode `raw` is the default: read the rows with `GET /searches/{search_id}/results`. With `"mode": "screened"` and a `buyer_profile`, read `GET /searches/{search_id}/leads`. The start answers **202** while the search runs. Poll `GET /searches/{search_id}` until `succeeded`.

If you already know the company and only want people in a role, skip the signal. Say "CFOs at this company in Belgium" and use the next step.

The other raw signals: a funding company is **1 credit**, a technology company is **20**, a person in a new role is **5**. `tech_adoption` has no screened mode: take those companies into the next step.

## 3. People by role, seniority or department

Say: "At Acme Analytics, the CFOs in Belgium. Cap it at 15 credits."

**MCP** — `preview_cost` with `endpoint` `leads`, then `company_leads`. **5 credits** per person. The ids are `per_`, not `lead_`.

```json
{ "name": "company_leads", "arguments": { "companies": [{ "linkedin_url": "https://www.linkedin.com/company/acme-analytics" }], "filters": { "roles": ["CFO"], "seniority": ["c_level"], "departments": ["finance"], "countries": ["BE"] }, "limit": 3, "max_credits": 15 } }
```

**REST** — `POST /leads/preview`, then `POST /leads` with the same body. At least one of `roles`, `seniority` or `departments` is required. Seniority is `c_level`, `vp`, `director` or `manager`. Titles rank the rows. Seniority and countries exclude. One call is one page and returns at most 25 people.

A screened `find_leads` already returned qualified leads, and a raw person row from `search_signals` already is a person. Do not call `company_leads` for those.

## 4. Why this lead

Say: "Explain the first lead. Why them, and why now?"

**MCP** — `explain_lead`. Free. The id has to be a `lead_` from `find_leads` or `watch_signal`. Do not pass a `per_` id from `search_signals` or `company_leads`: a raw row carries its own why, in `signals` (the post, the comment, the round or the new role).

```json
{ "name": "explain_lead", "arguments": { "lead_id": "lead_…" } }
```

**REST** — `GET /leads/{lead_id}`. Free. The body has the person, `fit`, `why_now`, and the evidence. `links.people` is the enrich URL. `links.company` is set when the company page is known and the Company API is open.

## 5. Enrich the contact

Say: "Find a work email for that lead. Do not look up a phone."

**MCP** — `enrich`. A profile is **2 credits**. `include_email: true` adds **10 credits** when an address is found. There is no phone argument. A work email and a phone together are the in-app contact reveal at **40 credits**, not a field on this API.

For a `lead_` id:

```json
{ "name": "enrich", "arguments": { "lead_id": "lead_…", "include_email": true, "max_credits": 15 } }
```

For a `per_` id from `search_signals` or `company_leads`, send `person_ids` instead of `lead_id`.

**REST** — `POST /person/enrich` with `profile_urls` or `person_ids`, and `include_email`. `POST /person/enrich/preview` is free. `person_ids` and `max_credits` are accepted only when the Signals API is open.

## 6. Outreach and the dashboard

Say: "Give me the dashboard link. Do not send anything."

The Signals API does not send the message. A tool result includes `dashboard_url`. It opens `/en/gtm/leads` or `/en/gtm/signals` for that search, watch, monitor or lead. REST responses do not include `dashboard_url`.

LinkedIn outreach goes through the assistant server (`POST https://foundermcp.dev/api/mcp`, key `ejk_`): your assistant writes the sequence and sends its own emails, FounderMCP sends the LinkedIn steps (`start_linkedin_sequence`, with a `per_…` or `lead_…` from this page). Nothing is sent until a person approves it, unless an admin turned on Autopilot. The tools, the limits and the approval rule are on [Follow-up](/docs/guides/follow-up).

More copy-paste paths are on [Recipes](/docs/guides/recipes). The credit table is [Credits & costs](/docs/api/credits-and-limits).
