Endpoints
The supported SendSets agent-native REST contract.
All customer API paths use /v1 and bearer authentication. API keys begin
with ssk_. Run creation is asynchronous and returns 202 Accepted with the
durable state.
Runs
| Method | Path | Scope |
|---|---|---|
POST | /runs | WRITE_RUNS; launch intent also needs EXECUTE_RUNS |
GET | /runs | READ_RUNS |
GET | /runs/:id | READ_RUNS |
POST | /runs/:id/cancel | WRITE_RUNS |
POST /runs requires Idempotency-Key. Its body accepts an existing campaign
or campaign metadata, auto/explicit/tag sender selection, inline leads,
contact IDs, segment IDs, ordered steps and variants, a daily limit, schedule,
stop_on_reply, opt-out state, and draft or launch intent.
An accepted launch moves through queued, preflighting, and then one of
awaiting_approval, launching, active, failed, or denied. Later states
are paused, completed, and cancelled. GET /runs/:id includes its
append-only event stream.
Agent policies and approvals
| Method | Path | Caller |
|---|---|---|
GET | /agent-policies/effective | API key, OAuth, or JWT |
GET, POST | /agent-policies | JWT owner/settings manager only |
PUT, DELETE | /agent-policies/:id | JWT owner/settings manager only |
GET | /approvals | JWT send manager only |
POST | /approvals/:id/decision | JWT send manager only |
Policies bind to one API key or OAuth grant. Capabilities are campaign.launch,
email.compose, inbox.reply and mailbox.provision; the last is autonomous
only with a max_monthly_mailbox_spend_cents the order's monthly total fits
under. Autonomous grants require explicit
mailbox IDs, independent capabilities, recipient/run and daily limits, action
limits, and an expiry. Approval records expire after 30 minutes. Approving a run
causes preflight and all hard safety gates to run again immediately before the
campaign starts.
Direct sends
| Method | Path | Scope | Capability |
|---|---|---|---|
POST | /emails/:id/send | SEND_DIRECT_EMAIL | email.compose |
POST | /unibox/compose | SEND_DIRECT_EMAIL | email.compose |
POST | /unibox/reply | SEND_INBOX_REPLY | inbox.reply |
API-key and OAuth callers receive an executed or awaiting_approval result.
JWT browser sessions are already human-authorized. Suppressions, organization
limits, mailbox holds/authentication/health, and deliverability rules remain
authoritative regardless of policy.
App connections and product events
| Method | Path | Scope |
|---|---|---|
GET, POST | /app-connections | INTEGRATIONS |
GET, PATCH, DELETE | /app-connections/:id | INTEGRATIONS |
POST | /app-connections/:id/rotate-secret | INTEGRATIONS |
POST | /app-connections/:id/test | INTEGRATIONS |
POST | /events | WRITE_EVENTS; requires Idempotency-Key |
GET | /events | READ_CAMPAIGNS |
GET | /events/:id | READ_CAMPAIGNS |
An app connection is the base URL and signing secret an app_action step
calls. POST /app-connections/:id/test sends a signed app.ping and answers
200 with a checklist (dns, tls, connection, authentication, status,
latency_ms, error) whether or not the app accepted it. POST /events
records a product event for a contact and resumes every wait_for_event step
open for it; the 202 names each resumed step under matched_runs.
Mailboxes
| Method | Path | Scope |
|---|---|---|
GET | /emails | READ_EMAILS |
POST | /emails | WRITE_EMAILS (SMTP/IMAP only) |
GET | /emails/:id | READ_EMAILS |
PATCH, DELETE | /emails/:id | WRITE_EMAILS |
POST | /emails/:id/test | WRITE_EMAILS |
GET | /emails/:id/warmup | READ_EMAILS |
POST | /emails/:id/warmup/start, /pause, /resume, /stop | WRITE_EMAILS |
POST | /emails/onboarding/oauth/cli-start | WRITE_EMAILS |
GET | /emails/onboarding/oauth/session/:session | WRITE_EMAILS |
POST /emails connects an SMTP/IMAP mailbox after a worker has validated the
credential; Google and Microsoft mailboxes go through cli-start, which
returns a consent URL and a session to poll. POST /emails/:id/test dials the
stored credential again and answers 200 with a checklist even when it fails.
GET /emails/:id carries the campaigns the mailbox sends for and its recent
errors beside the mailbox itself.
Managed mailboxes
| Method | Path | Scope |
|---|---|---|
GET | /mailboxes/provision/providers | READ_EMAILS |
GET | /mailboxes/domains/renewals | READ_EMAILS |
POST | /mailboxes/provision/quote | MANAGE_MAILBOX_PROVISIONING |
POST | /mailboxes/provision | MANAGE_MAILBOX_PROVISIONING; requires Idempotency-Key |
GET | /mailbox-provisioning, /mailbox-provisioning/:id | READ_EMAILS |
POST | /mailbox-provisioning/:id/cancel | MANAGE_MAILBOX_PROVISIONING |
renewals lists every managed domain's renewal cycle: when it renews, what
was charged, and whether anything needs a person. Renewal is automatic and
priced at the provider's current renewal cost plus processing, read fresh each
cycle.
providers lists the mailbox platforms that can be ordered right now, with
the live per-mailbox monthly price of each. The catalog and its prices come
from the upstream provider, not from configuration, so it is the only accurate
source for a provider menu.
A quote prices an order from the upstream provider's live costs and checks
every domain; it is valid for fifteen minutes, after which those prices are no
longer guaranteed. Pass domain for one domain, or domains for several: the
mailboxes are spread across them as evenly as possible, and each domain is
priced on its own because registration cost varies by TLD. Provisioning turns a quote into an
order once the caller may spend: a session directly, a credential through an
agent policy that grants mailbox.provision with a
max_monthly_mailbox_spend_cents the order fits under, or a human approval
(the 202 awaiting_approval shape, re-submitted with the same quote_id).
The order then waits on a Stripe checkout link (awaiting_payment) and moves
through paid, queued, provisioning, configuring and ready, or failed
and cancelled. Offered on SendSets Cloud only; a self-hosted instance answers
503 mailbox_provisioning_unavailable.
Campaign checks
| Method | Path | Scope |
|---|---|---|
POST | /campaigns/:id/validate | READ_CAMPAIGNS |
POST | /campaigns/:id/preflight | SEND_CAMPAIGNS |
POST | /campaigns/:id/test | SEND_CAMPAIGNS (sends real mail) |
GET | /campaigns/:id/test-runs, /campaigns/:id/test-runs/:runId | READ_CAMPAIGNS |
POST | /campaigns/:id/test-runs/:runId/cancel | SEND_CAMPAIGNS |
GET | /system/readiness | any credential |
validate is the read-only twin of preflight: the same checks plus the
structural checks on the step graph, answered as problems with a fix each,
without storing a report. /system/readiness is what sendsets doctor reads:
the workflow sidecar, live workers, the scheduler, and whether inbound events
are accepted.
Other supported surfaces
The default contract also mounts authentication, campaigns and sequences, contacts/leads and segments, mailboxes and warmup, inbox, analytics and deliverability, suppressions, realtime/audit events, API keys/OAuth, and webhooks. The generated OpenAPI document is the field-level reference.
CRM, forms, automations, advisor, templates, integrations, and internal AI
engines remain compiled for later reuse but return 404 by default. Operators
can mount them explicitly with SENDSETS_ENABLE_EXTENDED_SURFACES=true; they
are outside this supported contract.