# 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://mysdr.app/api/v1`. REST sends `Authorization: Bearer gtk_…`, with the key from **Connect assistant → API keys**. MCP is `POST https://mysdr.app/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 **403** `api_not_enabled` on those routes, with what the key can do instead. 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 **1 credit**. 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" }, "limit": 25, "max_credits": 25 } } }
```

```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": 25 } }
```

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 row holds.

`search_signals` waits up to 25 seconds. If the search is still running, call `get_search_results` 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`. Read the rows with `GET /searches/{search_id}/results`. 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 signals: a funding company is **1 credit**, a technology company is **3**, a person in a new role is **1**. `funding_raised` and `tech_adoption` return companies: take those 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`. **1 credit** per person. The ids start with `per_`.

```json
{ "name": "company_leads", "arguments": { "companies": [{ "linkedin_url": "https://www.linkedin.com/company/acme-analytics" }], "filters": { "titles": ["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 `titles`, `seniority` or `departments` is required. Seniority is `c_level`, `vp`, `director` or `manager`. Titles rank the rows. Departments (LinkedIn's function of the role), seniority and countries exclude. One call is one page across the companies and returns at most 25 people; with `per_company` (for "the CFO of each of these companies") each company is searched on its own, without a next page.

A person row from `search_signals` already is a person. Do not call `company_leads` for it.

## 4. Why this lead

Say: "Why them, and why now?"

There is no extra call: every row carries its own why, for free. A person row from `search_signals` has `signals`: up to 3 things they did, each with the post and, for a comment, its text, or the new role they started. A company row has the round or the technology, with its evidence. A person from `company_leads` has their current role in `signals`: the why is the company you named.

## 5. Enrich the contact

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

**MCP** — `enrich`. A profile is **1 credit**. `include_email: true` adds **1 credit** when an address is found. There is no phone argument: a phone number is [Find Phone](/docs/api-reference/find-phone) (`POST /person/phone`, or `find_phones` on the assistant server), **10 credits** per person with a number found, once.

For a `per_` id from `search_signals` or `company_leads`:

```json
{ "name": "enrich", "arguments": { "person_ids": ["per_…"], "include_email": true, "max_credits": 15 } }
```

For someone you found yourself, send `profile_urls` instead of `person_ids`.

**REST** — `POST /person/enrich` with `profile_urls` or `person_ids`, and `include_email`. `POST /person/enrich/preview` is free. `max_credits` works with every key; `person_ids` is 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, monitor or set of people. The Signals REST responses do not include `dashboard_url`; the tables, outreach and LinkedIn routes do.

LinkedIn outreach: your assistant writes the sequence and sends its own emails, mySDR sends the LinkedIn steps from the user’s own LinkedIn account, with a `per_…` from this page or a `linkedin_url`. With your `gtk_` key that is `POST /api/v1/outreach/linkedin/sequences`; on the assistant server (`POST https://mysdr.app/api/mcp`, connected with Allow or an `ejk_` key) it is `start_linkedin_sequence`. There is no approval step in mySDR: send it first with `dry_run`, show the user the texts, and start the sequence after they said yes in the conversation. The tools, the limits and that 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).
