# People Search

## Use case

Use People Search to build a list of people from a natural-language description of your target audience. Search by professional criteria such as role, seniority, industry, company, and location, then retrieve matching profiles for your sales, recruiting, or research workflow.

- **Build prospect lists for outbound sales.** Find heads of marketing at SaaS companies in London or procurement leaders at US manufacturers. Use their role and company details to organize leads before enriching contact information or preparing outreach.
- **Create candidate pools for recruiting.** Source software engineers in Toronto, finance directors in New York, or product managers at fintech companies. Start with the professional profile you need and review the matches for your open role.
- **Discover experts and professional communities.** Find renewable-energy executives for an industry interview series, healthcare operations leaders for customer discovery, or design leaders for an event. Search for the roles and sectors relevant to your project.

When you need more people, continue a completed search with `search_id` to retrieve another non-overlapping page of results.

## Endpoint

```http
POST https://api-public.clodo.ai/api/public/v1/search/
```

Send your API key in the `x-api-key` header. See [Authentication](https://docs.clodo.ai/api-reference/authentication).

> This endpoint returns `202 Accepted`. Create a [webhook signing secret](https://docs.clodo.ai/guides/webhook-secrets) and supply a public HTTPS `webhook_url` before making your first request. See [Async Polling](https://docs.clodo.ai/guides/async-polling) for retrieving results.

## Pricing

See [Credits & Pricing](https://docs.clodo.ai/guides/credits-and-pricing) for credit costs and charging behavior.

## Errors

For error responses and retry guidance, see [Handling Errors](https://docs.clodo.ai/api-reference/errors).

`POST /api/public/v1/search/` — async (returns `202 Accepted`). 1 credit per lead returned.

Light people search. Evaluates a natural-language query and returns matching leads. Wall time ~1 minute. Results delivered via signed webhook POST. Polling fallback at `GET /api/public/v1/search/{job_id}/`. To fetch more non-overlapping leads for the same prompt, pass a completed job `id` back as `search_id`.

## Request

| Field | Type | Required | Notes |
|---|---|---|---|
| `query` | string | yes for new searches | Natural-language sourcing prompt. ≤500 chars. Omit when continuing with `search_id`. |
| `search_id` | string | no | `dj_...` id from a previous completed People Search. Continues that search and returns the next non-overlapping page. |
| `max_results` | int | yes | min 25 and max 100. Upper bound on lead count. |
| `webhook_url` | string | yes | HTTPS URL. Must resolve to a public IP. |

Pre-condition: an active webhook signing secret. See [Webhook Signing Secrets](https://docs.clodo.ai/guides/webhook-secrets).

`Idempotency-Key` header is supported. Same key returns the same job's current state.

## Response (202)

```json
{
  "id": "dj_a1b2c3d4...",
  "status": "pending",
  "created_at": "2026-05-01T12:00:00Z"
}
```

Use the returned `id` as `search_id` to continue pagination after the job completes.

## Webhook events

`search.completed`:

```json
{
  "id": "dj_a1b2c3d4...",
  "event_type": "search.completed",
  "results": [
    {
      "first_name": "Patrick",
      "last_name": "Collison",
      "full_name": "Patrick Collison",
      "current_job_title": "CEO",
      "headline": "CEO at Stripe",
      "location": "San Francisco, California, United States",
      "professional_url": "linkedin.com/in/patrickcollison",
      "company": {
        "name": "Stripe",
        "domain": "stripe.com",
        "professional_url": "linkedin.com/company/stripe",
        "industry": "Financial Services",
        "employee_count": 8000
      }
    }
  ],
  "total_returned": 1
}
```

Person and company `professional_url` values come back in bare-host form (no scheme, no `www.`, no trailing slash). Company `professional_url` is optional and may be `null`.

`search.failed`:

```json
{
  "id": "dj_a1b2c3d4...",
  "event_type": "search.failed",
  "error": {"code": "error", "message": "People search failed; please retry."}
}
```

| `error.code` | `error.message` |
|---|---|
| `invalid_input` | `Invalid search query.` |
| `error` | `People search failed; please retry.` |

A 0-result outcome ships as `search.completed` with `total_returned: 0`.

## Billing

Charged per lead returned. `max_results` is the upper bound on credits. `total_returned` is the actual charge. A 0-result run charges nothing.

## Example

```bash
curl -X POST https://api-public.clodo.ai/api/public/v1/search/ \
  -H "x-api-key: ck_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "query": "VPs of Engineering at Series B SaaS in NYC",
    "max_results": 50,
    "webhook_url": "https://yourapp.com/webhooks/clodo"
  }'
```

Continue the same search:

```bash
curl -X POST https://api-public.clodo.ai/api/public/v1/search/ \
  -H "x-api-key: ck_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "search_id": "dj_a1b2c3d4...",
    "max_results": 100,
    "webhook_url": "https://yourapp.com/webhooks/clodo"
  }'
```

## Rate limit

`POST /api/public/v1/search/`:

| Limit | Value |
|---|---|
| Sustained rate | 6 requests / minute |
| Burst | 2 requests |

Polling `GET /api/public/v1/search/{job_id}/`:

| Limit | Value |
|---|---|
| Sustained rate | 3,600 requests / minute |
| Burst | 100 requests |

Exceeding any returns `429`.

## See also

- [GTM Lead Generation](https://docs.clodo.ai/guides/gtm-lead-generation)
- [Recruiting & Candidate Sourcing](https://docs.clodo.ai/guides/recruiting-candidate-sourcing)
- [Expert Discovery](https://docs.clodo.ai/guides/expert-discovery)

- [Webhook Signing Secrets](https://docs.clodo.ai/guides/webhook-secrets)
- [Webhook Signature Verification](https://docs.clodo.ai/guides/webhook-signing)
- [Async Polling](https://docs.clodo.ai/guides/async-polling)
- [Idempotency](https://docs.clodo.ai/guides/idempotency)