> ## Documentation Index
> Fetch the complete documentation index at: https://docs.growthxai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# The Public API

> A REST API for moving leads in, getting replies out, and reading the same numbers the app shows.

Every API call runs the **same database function the app runs** for that action. The API adds nothing on top and skips nothing.

```text theme={null}
Base URL   https://ktwqkvjuzsunssudqnrt.supabase.co/functions/v1/outreach-api/v1
Auth       Authorization: Bearer ok_live_…
Format     JSON in, JSON out. UTF-8. Timestamps are ISO 8601 in UTC.
           Report dates are YYYY-MM-DD in the workspace timezone.
```

<Info>
  Daily caps, schedules, warm-up, sender health, reply-stop and blacklists are enforced in the database. **The API cannot send more than the app can**, and there is no flag to turn a cap off. Nothing is deleted through the API either: suppressing a lead or exiting an enrollment keeps the lead, its timeline and its chats.
</Info>

## Keys

Create them under **Settings → API & webhooks → API keys** (Managers). A key is shown **once** — we store only its hash, so a lost key cannot be recovered. Revoke it and make a new one. A workspace can have 25 active keys.

```bash theme={null}
curl "$BASE/me" -H "Authorization: Bearer ok_live_3f9c…"
```

`X-API-Key: ok_live_…` works too, for tools that can't set an `Authorization` header.

| Property         | Meaning                                                                                                   |
| ---------------- | --------------------------------------------------------------------------------------------------------- |
| **Workspace**    | A key belongs to one workspace. The workspace never appears in a URL.                                     |
| **Role**         | `manager`, `member` or `client_viewer`. Never `owner`, and never more than the person who created it has. |
| **Client scope** | Optional. A scoped key sees and changes only those clients' leads, sequences, senders and threads.        |
| **Expiry**       | Optional. Leave it empty for a key that works until revoked.                                              |

A key **acts as the member who created it**, and audit entries name that member. If they leave the workspace or their role is lowered, the key loses the same rights immediately.

| Role            | Can                                                                                                                                                                              |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `client_viewer` | Every `GET` except webhooks. Read only.                                                                                                                                          |
| `member`        | Plus: create and update leads, tags, stage, list, suppress, enrich, preview and commit enrollments, pause / resume / exit / recover, set intent, assign threads, complete tasks. |
| `manager`       | Plus: activate and pause sequences, blacklists, webhooks.                                                                                                                        |

`GET /v1/me` returns the key's role and scope, plus the ids you need elsewhere: clients, stages, tags and lists.

## Routes

| Resource        | Routes                                                                                                                                                                                                                                                                                                                            |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Meta**        | `GET /me` · `GET /metrics/definitions`                                                                                                                                                                                                                                                                                            |
| **Leads**       | `GET /leads` · `POST /leads` · `GET /leads/{id}` · `PATCH /leads/{id}` · `POST /leads/{id}/tags` · `DELETE /leads/{id}/tags/{tag_id}` · `PUT /leads/{id}/stage` · `PUT /leads/{id}/list` · `POST /leads/{id}/suppress` · `DELETE /leads/{id}/suppress` · `GET /leads/{id}/timeline` · `POST /leads/enrich` · `POST /suppressions` |
| **Enrollments** | `POST /enrollments/preview` · `POST /enrollments` · `GET /enrollments` · `POST /enrollments/{id}/pause` · `…/resume` · `…/exit` · `POST /enrollments/recover`                                                                                                                                                                     |
| **Sequences**   | `GET /sequences` · `GET /sequences/{id}` · `GET /sequences/{id}/stats` · `POST /sequences/{id}/activate` · `POST /sequences/{id}/pause` · `GET /sequences/{id}/failed` · `GET /sequences/{id}/why-not-sending`                                                                                                                    |
| **Inbox**       | `GET /threads` · `GET /threads/{id}` · `POST /threads/{id}/reply` · `PUT /threads/{id}/intent` · `PUT /threads/{id}/assignee`                                                                                                                                                                                                     |
| **Senders**     | `GET /senders` · `GET /senders/{id}` · `…/health` · `…/budgets` · `…/capacity`                                                                                                                                                                                                                                                    |
| **Reports**     | `GET /reports/overview` · `/funnel` · `/intents` · `/reply-threads` · `/cost` · `/sequences` · `/senders` · `/clients` · `/sequences/{id}` · `/senders/{id}` · `/clients/{id}`                                                                                                                                                    |
| **Webhooks**    | `GET /webhooks` · `POST /webhooks` · `DELETE /webhooks/{id}` · `GET /webhooks/deliveries` · `POST /webhooks/deliveries/{id}/replay`                                                                                                                                                                                               |
| **Tasks**       | `POST /tasks/{id}/complete`                                                                                                                                                                                                                                                                                                       |

Building and publishing sequences, connecting senders and changing caps are **not** in the API. Do those in the app or through [Claude](/integrations-api/mcp-connect-claude).

## Rate limits

Per key, per hour:

| Class     | Limit | Which calls                                                                                                                          |
| --------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------ |
| **read**  | 600   | Every `GET`, plus `POST /enrollments/preview` (it changes nothing)                                                                   |
| **write** | 300   | Every `POST`, `PUT`, `PATCH`, `DELETE`                                                                                               |
| **spend** | 60    | Calls that start spending a sender's budget: enrol, recover, enrich, activate a sequence, send a reply. These also count as a write. |

Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. A 429 carries `Retry-After`.

These protect the API — they are not your sending limits. For bulk work, send many ids in **one** call (`lead_ids` takes up to 10,000 on enrollments, 5,000 on enrich) rather than one call per lead.

## Idempotency

Send an `Idempotency-Key` header on any write:

* Same key, same request → the first answer again, with `Idempotent-Replayed: true`. Nothing runs twice.
* Same key, different request → `409 E_IDEMPOTENCY_MISMATCH`.
* Same key while the first is still running → `409 E_IN_PROGRESS`.
* Answers below 500 are stored, including 4xx. A 5xx is not, because a failed call changed nothing — retry with the same key.

Zapier, Make and n8n retry on timeouts, so set this header on every write in a recipe.

## Partial updates

`POST /v1/leads` and `PATCH /v1/leads/{id}` change **only the fields you send**.

* A field you leave out is never blanked. An empty string or `null` counts as left out.
* `custom` merges key by key.
* `email_work`, `email_personal`, `public_identifier` and `client_id` are filled **only when empty** and never overwritten. Send a different value and the call succeeds, the old value stays, and the field appears in `unchanged_fields`.
* Unknown fields are rejected with 422, so a typo can't be silently dropped.

`POST /v1/leads` matches on LinkedIn id, then provider id, then work email, then personal email. No match creates the lead (`201`), a match updates it (`200`).

## Preview, then commit

Enrolling takes two steps, the same as in the app:

1. `POST /v1/enrollments/preview` — changes nothing. Returns `eligible_ids`, who is excluded and why, which sender each lead would get, warnings and a duration estimate.
2. `POST /v1/enrollments` with the same sequence, the `lead_ids` you want and `"confirm": true`.

The commit re-checks every rule at that moment. It can enrol **fewer** leads than the preview showed, never a lead the rules exclude, and never a lead you did not list.

## Errors

```json theme={null}
{ "error": { "code": "E_RATE_LIMITED", "message": "…", "remedy": "…" } }
```

Follow the `remedy`. The full reference, with every route and schema, is in the OpenAPI file — import it into Postman, Insomnia or Swagger UI.

## Related articles

* [Automation Recipes: Zapier, Make, n8n and Clay](/integrations-api/automation-recipes)
* [Outbound Webhooks](/integrations-api/outbound-webhooks)
* [CRM Sync](/integrations-api/crm-sync)
