# Find people at companies

People who work at up to 25 companies, filtered on role, seniority, department and country. One call reads one page and returns at most 25 people. Each person costs 5 credits. A company that cannot be matched, and a page with nobody on it, cost nothing.

People who work at up to 25 companies, filtered on role, seniority, department and country. One call reads one page and returns at most 25 people. Each person costs 5 credits. A company that cannot be matched, and a page with nobody on it, cost nothing.

Name a company by `id` (`cmp_…` from an earlier row), `domain`, or `linkedin_url`. Send `next_cursor` back as `cursor` with the same companies and filters. No profile is fetched: use POST /person/enrich with `person_ids` for the full profile and a work email.

This is not a buying signal. `signal_type` on each row is null. The person did not do anything; they hold a role at a company you named.

## Authentication

Send `Authorization: Bearer gtk_…`. Create the key under **API Access → API Keys**. A missing, invalid or revoked key is **401**, including while this API is closed. A valid key while the API is closed for your organization answers **404**, the same body as an unknown path. Every response includes `FounderMCP-Api-Version` and `FounderMCP-Request-Id`.

### Body parameters

- **`companies`** `object[]` · **required** — 1 to 25 companies. Each object has exactly one of `id`, `domain` or `linkedin_url`.
- **`filters`** `object` · **required** — At least one of `roles` (job titles, up to 10), `seniority` (`c_level`, `vp`, `director`, `manager`) or `departments` (the same department keys as a buyer profile). `countries` is ISO alpha-2, up to 20. Titles rank people but do not exclude them. Seniority and countries do.
- **`limit`** `integer` — At most this many people, 1 to 100. One call still returns at most 25. Defaults to 25.
- **`cursor`** `string | null` — `next_cursor` of the previous response, with the same companies and filters.
- **`max_credits`** `integer | null` — Stop before the next person would pass this.

## Response

- **`object`** `string` · **required** — Always `list`.
- **`data`** `object[]` · **required** — People. `id` is `per_…` (send it to POST /person/enrich as `person_ids`). `from_company_id` is the company they were found at. `signals` is the current role.
- **`companies`** `object[]` · **required** — One entry per company you sent, in order: `status` `matched`, `not_found` or `invalid`, `company_id`, `rows`, `message`.
- **`next_cursor`** `string | null` · **required** — The next page.
- **`credits_used`** `integer` · **required** — People delivered times 5.
- **`truncated_by`** `string | null` · **required** — `max_credits` when the cap left people out.

## Credits

5 credits per person delivered. Misses are free. Errors and empty lookups are free. A call that spent credits puts that number in `credits_used`, in `X-Credits-Used` and in `X-Credits-Charged`. When the wallet can be read, the response also sends `X-Credits-Remaining`.

## Errors

- **503** `service_unavailable` — A company could not be looked up just now. `param` names `companies[i]`. Nothing was charged.
- **400** `invalid_request` — The body is not valid JSON, a field is unknown or has the wrong type, or a value is not allowed.
- **401** `authentication_error` — The Authorization header is missing, or the key is unknown or revoked.
- **403** `permission_error` — API access is not part of your plan, or your account is suspended.
- **404** `not_found` — The endpoint does not exist.
- **429** `rate_limit_error` — More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header.
- **429** `daily_limit_reached` — The request could take your organization over its daily credit limit. The limit resets at midnight (Europe/Brussels).
- **402** `insufficient_credits` — The credit balance is lower than this request could cost. Nothing was charged. Add credits, or send a smaller request. The error includes code, fix and a link to the credits docs.
- **502** `upstream_error` — The data source did not answer. Retry later.
- **503** `service_unavailable` — The API is temporarily unavailable. Retry later.
- **500** `internal_error` — Something went wrong on our side.
- **402** `max_credits_exceeded` — max_credits is lower than the credits of the first row, so nothing could be returned. Nothing was charged; raise max_credits or ask for fewer rows.

## Example

### cURL

```bash
curl -X POST "https://foundermcp.dev/api/v1/leads" \
  -H "Authorization: Bearer $FOUNDERMCP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "companies": [
      {
        "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
      }
    ],
    "filters": {
      "roles": [
        "CFO",
        "Head of Finance"
      ],
      "seniority": [
        "c_level",
        "vp"
      ],
      "countries": [
        "BE"
      ]
    },
    "limit": 3,
    "max_credits": 15
  }'
```

### JavaScript

```javascript
const response = await fetch('https://foundermcp.dev/api/v1/leads', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.FOUNDERMCP_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "companies": [
      {
        "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
      }
    ],
    "filters": {
      "roles": [
        "CFO",
        "Head of Finance"
      ],
      "seniority": [
        "c_level",
        "vp"
      ],
      "countries": [
        "BE"
      ]
    },
    "limit": 3,
    "max_credits": 15
  })
});
const body = await response.json();
```

### Python

```python
import json
import os
import urllib.request

payload = {
  "companies": [
    {
      "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
    }
  ],
  "filters": {
    "roles": [
      "CFO",
      "Head of Finance"
    ],
    "seniority": [
      "c_level",
      "vp"
    ],
    "countries": [
      "BE"
    ]
  },
  "limit": 3,
  "max_credits": 15
}

request = urllib.request.Request(
    "https://foundermcp.dev/api/v1/leads",
    headers={
    "Authorization": f"Bearer {os.environ['FOUNDERMCP_API_KEY']}",
    "Content-Type": "application/json"
    },
    data=json.dumps(payload).encode(),
    method="POST",
)
with urllib.request.urlopen(request) as response:
    body = json.load(response)
```

### Example response

```json
{
  "object": "list",
  "data": [
    {
      "id": "per_01J9Z6P8C8V0K3W6T2N8R5M1XK",
      "object": "person",
      "signal_type": null,
      "from_company_id": "cmp_01J9Z6P8C8V0K3W6T2N8R5M1XB",
      "credits_charged": 5,
      "person": {
        "full_name": "Jane Example",
        "title": "Chief Financial Officer",
        "linkedin_url": "https://www.linkedin.com/in/jane-example"
      }
    }
  ],
  "companies": [
    {
      "input": {
        "linkedin_url": "https://www.linkedin.com/company/acme-analytics"
      },
      "status": "matched",
      "rows": 1,
      "message": null
    }
  ],
  "next_cursor": null,
  "credits_used": 5,
  "truncated_by": null,
  "sources": [
    "linkedin"
  ],
  "notes": []
}
```
