API Overview
The SendOps Public API lets you read events, manage configuration, and inspect account state programmatically. It is the same data plane your dashboard uses, exposed under https://api.sendops.dev and authenticated with an API key you create from your account settings.
This is not a message-relay API
SendOps never relays mail through infrastructure of its own. For per-message transactional email, call SES directly with your own AWS credentials. The SendOps API can trigger bulk sends — POST /v1/broadcasts and the broadcast test-send endpoint compose a message and dispatch it through SES in your own AWS account, on your identities and your reputation. There is no single-message send endpoint.
What the API gives you
- Message-level observability — list, search, and trace individual messages and the SES events they emit.
- Reporting — deliverability and engagement aggregates, plus per-template performance.
- Suppressions — read the account-level suppression list and look up individual recipients.
- Configuration introspection — channels (SES configuration sets), templates, tracking domains, and SES identities.
- Contacts & subscriptions — read your SES contact list, subscription topics, and contacts (attributes and per-topic preferences), and write them too: create, replace, patch, delete, upsert by external id, and bulk-import up to 5000 contacts per call.
- Lists & Segments — read static Lists and dynamic, SendQL-defined Segments with their members, and preview a predicate before saving it. List definitions are writable; Segments are read-only bar the preview dry-run.
- Attributes — read and write the custom-attribute registry (the schema Segment predicates compile against), with a dry-run that reports an edit’s impact on dependent Segments.
- Activities — read contact activity, and ingest free-form behavioral signals with
POST /v1/activities(single or batch). - Broadcasts — read broadcast definitions and delivery state, and create, send/schedule, test, and delete one-off bulk sends to a List or Segment.
- Workflows — read drip-workflow definitions, runs, exit/funnel analytics, and per-contact timelines, plus a dry-run simulation against a sample contact.
- Tags — read the org’s tag vocabulary (Gmail-style folders across Lists, Segments, and Templates).
- Assets — read your git-sourced image asset library: the images promoted to your Edge CDN, with their source paths, CDN URLs, and dimensions.
- Domain Auth (DMARC) — read what is sending as your domains from DMARC aggregate reports, the policy ladder with every criterion beside its measured value, what publishing a stricter policy would cost, and the history of what changed on a domain — plus write source decisions, cost acknowledgements and timeline notes. No endpoint publishes DNS.
- Account state — the calling org’s onboarding state, AWS connection status, plan, send quota, and SES production-access state.
Every endpoint is documented in the sidebar, grouped by resource. The catalogue is generated from the live OpenAPI spec.
What the API does not do (in v1)
- No per-message send endpoint. There is no “send this one email” call: transactional mail is sent by your application against SES directly. Bulk sends are the exception — Broadcasts can be created, sent, scheduled, and test-sent through the API, and every one of them fires through your own SES account rather than through SendOps infrastructure.
- No browser-origin API calls. CORS is closed on
api.sendops.dev; API requests are server-to-server. The authorization server is the one exception —auth.sendops.devaccepts cross-origin requests so a browser-based public OAuth client can exchange its own tokens. - No infrastructure writes. The audience surface (contacts, topics, Lists, attributes, Broadcasts) is writable, but AWS-facing configuration — channels, SES identities, tracking domains, and suppressions — stays read-only here and is changed in the dashboard.
- No git-owned writes. Definitions that originate from a connected git repo (git-backed Lists, Segments, and attributes) are read-only through the API and return
409 conflict— edit them in the repository. Segment membership is computed, never written; the/v1/segments/previewPOSTis a non-mutating dry-run that evaluates a predicate without saving anything.
Authentication at a glance
Every request carries an Authorization: Bearer sk_<env>_<...> header. Keys are scoped to a single organization and granted a subset of permissions (scopes) chosen when the key was created. Live and test keys share the same scope vocabulary; requests are unthrottled until a per-org rate limit is configured, and when one is, test keys run at 10% of the live ceiling.
See Authentication for the full key lifecycle.
Conventions
- All endpoints are versioned under
/v1/and use JSON request/response bodies. There is no XML or form-encoded alternative. - Timestamps are ISO 8601 in UTC (
2026-05-17T19:00:00Z). - IDs are UUIDs in canonical hyphenated form.
- Errors follow RFC 7807
application/problem+json. - Lists are cursor-paginated; offsets and totals are not exposed.
- Rate-limit headers (both
RateLimit-*and legacyX-RateLimit-*) appear on every response once a per-org limit is configured; until then requests are unthrottled. See Rate Limiting.
Getting your first response
You’ll need: a SendOps account, an API key with at least one scope (e.g., api.reports.view), and a terminal. Head to the Quickstart for a five-minute walk-through.