From companies to leads
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.
{ "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 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.
{ "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 } } }
{ "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 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_.
{ "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 (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:
{ "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.
More copy-paste paths are on Recipes. The credit table is Credits & costs.