API Documentation
Pull your campaigns, replies, interested replies, booked meetings and infrastructure health straight into your CRM, your reporting stack, or your own agents. Every request is scoped to a single workspace and requires an active subscription.
Introduction
The Ever Outbound API gives you programmatic access to the same data shown in your dashboard. Pull your campaigns, replies, interested replies, booked meetings and infrastructure health into your CRM, your reporting stack or your own agents.
Every request is scoped to a single workspace and requires an active subscription. All responses are JSON.
All response examples below use fictional placeholder data.
https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1Authentication
Authenticate with an API key sent in the x-api-key header. Keys are created inside your dashboard under Settings, and are shown once at creation. Store the key somewhere safe. If it leaks, revoke it and issue a new one.
curl https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/me \
-H "x-api-key: eo_live_xxxxxxxxxxxxxxxx"Free sandbox key
Want to try the API before subscribing? Create a free test key, no account or payment needed. It starts with eo_test_, lasts 30 days and works on every endpoint with sample data. Pausing or resuming a campaign is simulated, so nothing real changes. You can create up to 5 per day.
curl -X POST https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/sandbox/keysKeys are bound to the workspace they were created in and stop working the moment the subscription lapses or the key is revoked. Never expose a key in browser code.
Quickstart
- Sign in to your dashboard and open Settings.
- Under API keys, create a key for the workspace you want to read.
- Copy the key. It is displayed only once.
- Call the API with the key in the
x-api-keyheader.
const res = await fetch("https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/campaigns", {
headers: { "x-api-key": process.env.EVEROUTBOUND_API_KEY },
});
const data = await res.json();
console.log(data);Errors and rate limits
Errors return a JSON body with an error field and a matching HTTP status code.
| Status | Meaning |
|---|---|
| 400 | Invalid or missing parameters. |
| 401 | Missing, invalid or revoked API key. |
| 402 | The workspace does not have an active subscription. |
| 404 | Unknown endpoint or workspace. |
| 409 | Workspace is not fully provisioned yet. |
| 429 | Rate limit exceeded. Wait for the Retry-After header, then retry. |
| 502 | Upstream sending platform error. Retry shortly. |
Each key may make 120 requests per 60 seconds. Every response includes the standard RateLimit, RateLimit-Policy, RateLimit-Remaining and RateLimit-Reset headers, and a 429 response adds Retry-After in seconds. Campaign and infrastructure data refreshes on the order of minutes, so polling once every five minutes is plenty.
Versioning and deprecation
The Ever Outbound API is versioned in the URL path (/v1) and every response carries an API-Version header. Within v1 we only add fields and endpoints, never remove or rename them. Before any endpoint is retired, its responses carry a Deprecation header and a Sunset header (RFC 8594) at least 90 days ahead, and the change is listed here. No endpoint is currently deprecated.
Command-line tool
The official Ever Outbound CLI wraps every endpoint so you can script your workspace from a terminal. It needs Node 18 or newer and has no other dependencies. Output is a readable table in a terminal and JSON when piped or with --json.
npm install -g everoutbound-cli
# or from the hosted tarball:
npm install -g https://everoutbound.io/cli/everoutbound-cli-latest.tgz
export EO_API_KEY=eo_live_your_key
eo me
eo campaigns
eo replies --interested --since 2026-10-01T00:00:00Z
eo meetings --json
eo infrastructure
eo pause <campaign-id> # needs a write-scope key
eo --helpGet workspace
Returns the workspace the key belongs to. Useful as a health check.
curl https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/me -H "x-api-key: $EVEROUTBOUND_API_KEY"{
"workspace": {
"id": "00000000-0000-4000-8000-000000000000",
"name": "Example Workspace",
"company": "Example Company",
"email": "api-user@example.invalid",
"status": "Active",
"launch_date": "2026-06-02"
}
}List campaigns
Returns your campaigns, the same list shown in your dashboard. Optional query parameter status filters by campaign status. Results are not paginated.
Add optional since and until (ISO 8601) to make prospects_reached count only prospects first contacted in that period. Dates are applied as whole UTC days, both inclusive. Without them, the value is all-time. If a campaign's count can't be retrieved, its value is null.
curl "https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/campaigns?status=active" \
-H "x-api-key: $EVEROUTBOUND_API_KEY"
curl "https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/campaigns?since=2026-09-01T00:00:00Z&until=2026-09-30T23:59:59Z" \
-H "x-api-key: $EVEROUTBOUND_API_KEY"{
"data": [
{
"id": 1234,
"name": "Example campaign",
"status": "active",
"created_at": "2026-05-29T17:02:35Z",
"updated_at": "2026-09-24T00:08:26Z",
"total_prospects": 5000,
"prospects_reached": 3200
}
]
}List replies
Returns the genuine prospect replies shown in your dashboard, newest first. Out of office, auto replies, bounces and warmup mail are excluded. Each reply has a stable id and an interested flag. Interested replies are always a subset of all replies.
| status | Omit for all replies, or interested for interested replies only. Other values return 400. |
| since | ISO 8601. Replies received at or after this time (UTC). |
| until | ISO 8601. Replies received before this time (UTC). |
| page | Page number, starting at 1. |
| per_page | 1 to 100, default 50. |
Dates filter on when the reply was received. Every response includes a pagination object with total, total_pages and has_more. To collect everything without gaps, fix a since/until window, page until has_more is false, and dedupe on id.
curl "https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/replies?status=interested&since=2026-09-01T00:00:00Z&until=2026-10-01T00:00:00Z&page=1" \
-H "x-api-key: $EVEROUTBOUND_API_KEY"{
"data": [
{
"id": "1001",
"lead_id": 5678,
"campaign_id": 1234,
"prospect_name": "Sample Prospect",
"prospect_email": "prospect@example.invalid",
"company": "Sample Company",
"replied_at": "2026-09-23T20:56:20Z",
"interested": true,
"crm_status": null
}
],
"pagination": { "page": 1, "per_page": 50, "total": 1, "total_pages": 1, "has_more": false }
}List booked meetings
Returns the booked calls shown in your dashboard. Accepts since, until, page and per_page, filtered on when the call was booked.
curl https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/meetings -H "x-api-key: $EVEROUTBOUND_API_KEY"Infrastructure health
Returns the same infrastructure health shown in your dashboard: overall health, its label, and the status of each sending domain.
curl https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/infrastructure -H "x-api-key: $EVEROUTBOUND_API_KEY"{
"health_pct": 100,
"label": "Excellent",
"totals": { "domains": 2, "healthy": 2, "replace": 0, "reconnecting": 0 },
"domains": [{ "domain": "example.info", "health": "healthy" }]
}Recipes
Sync interested replies into your CRM
Poll /v1/replies?status=interested every few minutes with a since timestamp of your last successful run, then upsert by reply id.
const since = (await store.get("last_sync")) ?? new Date(Date.now() - 864e5).toISOString();
const until = new Date().toISOString();
for (let page = 1; ; page++) {
const res = await fetch(
`https://tviccnbeurbqkeeiykbs.supabase.co/functions/v1/api/v1/replies?status=interested&since=${since}&until=${until}&page=${page}`,
{ headers: { "x-api-key": process.env.EVEROUTBOUND_API_KEY } },
);
const { data, pagination } = await res.json();
for (const reply of data) {
await crm.upsertContact({ id: reply.id, email: reply.prospect_email, name: reply.prospect_name });
}
if (!pagination.has_more) break;
}
await store.set("last_sync", until);Support
Need an endpoint that is not here? Email Team@EverOutbound.io and tell us what you are building. We add endpoints based on what clients actually ask for.