# Unitpost > Unitpost is an email platform for developers: send transactional and marketing email, manage contacts, segments, topics, templates, sending domains, inbound email, webhooks, and suppressions — over a REST API, official SDKs (Node.js, Python, Ruby, PHP, Laravel, Go, Java, Rust, .NET), an SMTP relay, or the Unitpost MCP server for AI agents. It also ships an email design suite: the @unitpost/email component library on npm (works standalone, no account needed — https://unitpost.com/email), a hybrid visual + code template builder, a free template gallery, and a browser playground. ## AI & agents - [UnitAI](https://www.unitpost.com/ai/unit): Unit, the AI assistant built into the Unitpost dashboard — design templates, launch campaigns, build segments, and explain deliverability, with approval before every send. ([Markdown](https://www.unitpost.com/ai/unit.md)) - [MCP server](https://www.unitpost.com/ai/mcp): Connect any MCP client (Cursor, Claude Code, Claude Desktop, Codex, Copilot, Gemini, Windsurf) to Unitpost. Streamable HTTP at https://mcp.unitpost.com/mcp, OAuth 2.1 browser approval (recommended) or a workspace API key from www.unitpost.com (legacy backup). One tool per API operation. ([Markdown](https://www.unitpost.com/ai/mcp.md)) - [MCP discovery](https://www.unitpost.com/.well-known/mcp.json): Well-known MCP server discovery document. - [MCP server card](https://www.unitpost.com/.well-known/mcp/server-card.json): Structured server card — identity, transport, capabilities, auth. - [API catalog](https://www.unitpost.com/.well-known/api-catalog): RFC 9727 linkset of the REST API + MCP server. - [Agent auth guide](https://www.unitpost.com/auth.md): How agents authenticate — OAuth 2.1 for MCP (recommended), API keys and capabilities for REST and legacy MCP. - [Design guidance](https://www.unitpost.com/design.md): How to build on-brand Unitpost UI — tokens, the shared component kit, page patterns, and the failure modes we reject. Load it when generating pages, dashboards, or reports that should look like Unitpost. - [MCP setup — Cursor](https://www.unitpost.com/guides/mcp/cursor): Connect Cursor to Unitpost with OAuth — approve in the browser, or a key block. - [MCP setup — Claude Code](https://www.unitpost.com/guides/mcp/claude-code): Connect Claude Code to Unitpost with OAuth — add the URL, authenticate from /mcp, approve in the browser. - [MCP setup — Claude Desktop](https://www.unitpost.com/guides/mcp/claude-desktop): Connect with OAuth via Add custom connector — approve in the browser. API-key bridge as fallback. - [MCP setup — Codex](https://www.unitpost.com/guides/mcp/codex): Connect ChatGPT/Codex with OAuth in the browser. Codex CLI takes a static key instead. - [MCP setup — GitHub Copilot](https://www.unitpost.com/guides/mcp/copilot): Connect VS Code agent mode to Unitpost with OAuth — approve in the browser. API key as fallback. - [MCP setup — Gemini CLI](https://www.unitpost.com/guides/mcp/gemini): Connect the Gemini CLI to Unitpost — OAuth in the browser, or a key block. - [MCP setup — Windsurf](https://www.unitpost.com/guides/mcp/windsurf): Connect Windsurf (Cascade) to Unitpost — OAuth in the browser, or a key block. - [MCP setup — OpenCode](https://www.unitpost.com/guides/mcp/opencode): Connect OpenCode with OAuth — add the remote URL, approve in the browser. - [MCP setup — Grok](https://www.unitpost.com/guides/mcp/grok): Point Grok at the Unitpost MCP URL. Marketplace listing is a separate catalog PR. - [MCP setup — Generic / custom client](https://www.unitpost.com/guides/mcp/custom): Connect any MCP-compatible client or your own agent to Unitpost. - [MCP setup — Headless / API key](https://www.unitpost.com/guides/mcp/headless): No browser on this machine? CI, SSH, containers, or paste-a-key-only clients — use a key. - [MCP setup index (Markdown)](https://www.unitpost.com/guides/mcp.md): Flat list of every MCP client guide. - [Skill](https://www.unitpost.com/ai/skills): Install the Unitpost skill into your coding agent with `npx skills add unitpostcom/skills --skill unitpost`. ([Markdown](https://www.unitpost.com/ai/skills.md)) - [@unitpost/email Skill](https://www.unitpost.com/email): Teach an agent the email component library — no account. `npx skills add unitpostcom/email`. ([Markdown](https://www.unitpost.com/email.md)) - [Skills discovery](https://www.unitpost.com/.well-known/agent-skills/index.json): Well-known Agent Skills index. - [llms-full.txt](https://www.unitpost.com/llms-full.txt): The full text of every guide below, inlined for one-shot ingestion. ## Pricing - [Pricing (Markdown)](https://www.unitpost.com/pricing.md): Machine-readable plans, commit ladder, rates, and FAQ — derived from the same billing contracts the product enforces. Prefer this over the interactive HTML slider. - [Pricing (HTML)](https://www.unitpost.com/pricing): Human pricing page with volume slider. ## Product - [Transactional email](https://www.unitpost.com/transactional): Deliver receipts, password resets, and alerts your users actually receive. A fast REST API and SMTP relay, idempotent sends, signed webhooks, and per-message tracking — on infrastructure built for deliverability. ([Markdown](https://www.unitpost.com/transactional.md)) - [Marketing email](https://www.unitpost.com/marketing-emails): Newsletters, announcements, and campaigns on the same infrastructure as your transactional mail. Unlimited contacts, priced per send — never per contact — with opt-out handling and per-message analytics. ([Markdown](https://www.unitpost.com/marketing-emails.md)) - [SMTP relay](https://www.unitpost.com/smtp): Send email over standard SMTP with Unitpost. Point any app — WordPress, Supabase, Nodemailer, Rails, Laravel, Django — at smtp.unitpost.com and it flows through the same pipeline as our API. ([Markdown](https://www.unitpost.com/smtp.md)) - [Webhooks](https://www.unitpost.com/webhooks): Stream every email event to your own endpoints in real time — delivered, opened, clicked, bounced, complained, and inbound. Signed with HMAC, retried with backoff, and logged per delivery. ([Markdown](https://www.unitpost.com/webhooks.md)) - [Inbound email](https://www.unitpost.com/inbound): Point MX at Unitpost and turn any address on your verified domain into a structured email.received webhook — parse, thread, and reply on the same pipeline you already send with. ([Markdown](https://www.unitpost.com/inbound.md)) - [Contacts](https://www.unitpost.com/contacts): Your audience, in one place. Store contacts with custom fields, build static and dynamic segments, personalize with variables, and honor topic-level and global opt-outs automatically. ([Markdown](https://www.unitpost.com/contacts.md)) - [Automations](https://www.unitpost.com/automations): Trigger emails and campaigns automatically from events and contact activity, with branching and delays — on the templates and deliverability you already use. Coming soon. ([Markdown](https://www.unitpost.com/automations.md)) - [Integrations](https://www.unitpost.com/integrations): Connect Unitpost to the tools you already use — no-code platforms, data warehouses, and app frameworks — reusing your existing domain and keys. Coming soon. ([Markdown](https://www.unitpost.com/integrations.md)) - [Dedicated IPs](https://www.unitpost.com/dedicated-ips): Isolate your sending reputation on dedicated IP addresses with guided warm-up and per-stream pooling for high-volume senders. Coming soon. ([Markdown](https://www.unitpost.com/dedicated-ips.md)) - [Unitpost for Startups](https://www.unitpost.com/startups): Six or twelve months on Starter or Growth — 50k to 250k emails a month, no card. Apply with your workspace. ([Markdown](https://www.unitpost.com/startups.md)) - [Migrate to Unitpost](https://www.unitpost.com/migration): Move from Resend, SendGrid, Mailgun, Postmark, Brevo, or Loops in about 4 minutes. Paste a read-only API key, preview everything that carries over, then accept. Nothing is written until you do. ([Markdown](https://www.unitpost.com/migration.md)) - [UnitAI](https://www.unitpost.com/ai/unit): Unit is your AI teammate inside Unitpost. Import Brand Kit so agents generate on-brand emails, keep prefs in Memory, then ask it to build templates, launch campaigns, and explain deliverability — always asks before it sends. ([Markdown](https://www.unitpost.com/ai/unit.md)) - [MCP server](https://www.unitpost.com/ai/mcp): Point any MCP client — Cursor, Claude, Codex, Copilot, Gemini, Windsurf — at Unitpost and it gets native tools to send email, run campaigns, and manage contacts. Hosted, gated by a scoped API key. ([Markdown](https://www.unitpost.com/ai/mcp.md)) - [Agent Skills](https://www.unitpost.com/ai/skills): The Unitpost skill teaches coding agents how to send and manage email correctly. Install with one command; works with Claude Code, Cursor, Codex, and many other agents. ([Markdown](https://www.unitpost.com/ai/skills.md)) ## SMTP relay - [SMTP relay](https://www.unitpost.com/smtp): Send through smtp.unitpost.com from any SMTP client — username `unitpost`, password = an API key with emails:send. STARTTLS on 587/2587, implicit TLS on 465/2465. ([Markdown](https://www.unitpost.com/smtp.md)) - [SMTP setup index (Markdown)](https://www.unitpost.com/guides/smtp.md): Flat list of every framework SMTP guide. - [SMTP setup — Send email with Nodemailer over SMTP](https://www.unitpost.com/guides/smtp/nodemailer): createTransport pointed at Unitpost — Node, Next.js, or NestJS. - [SMTP setup — Send Supabase auth email over SMTP](https://www.unitpost.com/guides/smtp/supabase): Magic links and confirmations from your verified domain. - [SMTP setup — Send WordPress email over SMTP](https://www.unitpost.com/guides/smtp/wordpress): WP Mail SMTP pointed at Unitpost instead of PHP mail(). - [SMTP setup — Send Auth0 email over SMTP](https://www.unitpost.com/guides/smtp/auth0): Verification, welcome, and reset mail from your domain. - [SMTP setup — Send email from Rails over SMTP](https://www.unitpost.com/guides/smtp/rails): Action Mailer pointed at Unitpost. - [SMTP setup — Send email from Laravel over SMTP](https://www.unitpost.com/guides/smtp/laravel): MAIL_HOST in .env pointed at Unitpost. - [SMTP setup — Send email from Django over SMTP](https://www.unitpost.com/guides/smtp/django): Django EMAIL_BACKEND pointed at Unitpost. - [SMTP setup — Send email with PHPMailer over SMTP](https://www.unitpost.com/guides/smtp/php): PHPMailer SMTP mode pointed at Unitpost. - [SMTP setup — Send email from Next.js over SMTP](https://www.unitpost.com/guides/smtp/nextjs): Nodemailer in an App Router Route Handler. - [SMTP setup — Send email from NestJS over SMTP](https://www.unitpost.com/guides/smtp/nestjs): Nodemailer inside a NestJS provider. - [SMTP setup — Send email from Express over SMTP](https://www.unitpost.com/guides/smtp/express): Nodemailer from an Express route. - [SMTP setup — Send email from Python over SMTP](https://www.unitpost.com/guides/smtp/python): stdlib smtplib — no framework required. - [SMTP setup — Send email from Flask over SMTP](https://www.unitpost.com/guides/smtp/flask): Flask-Mail pointed at Unitpost. - [SMTP setup — Send email from FastAPI over SMTP](https://www.unitpost.com/guides/smtp/fastapi): smtplib from a FastAPI dependency. - [SMTP setup — Send email from Go over SMTP](https://www.unitpost.com/guides/smtp/go): net/smtp with STARTTLS. - [SMTP setup — Send email from Spring Boot over SMTP](https://www.unitpost.com/guides/smtp/spring): JavaMailSender properties pointed at Unitpost. - [SMTP setup — Send email from .NET over SMTP](https://www.unitpost.com/guides/smtp/dotnet): MailKit pointed at Unitpost. ## Getting started - [Install the SDK](https://www.unitpost.com/docs/install): Add the official SDK for your language — or call the API directly. - [Quickstart](https://www.unitpost.com/docs/quickstart): Create a key, verify a domain, and send your first email. - [How it all fits together](https://www.unitpost.com/guides/overview): The contacts → segments → campaigns flow and the rules that keep it safe. ## API reference guides - [Templates & variables](https://www.unitpost.com/docs/templates): Reference a saved template and pass per-recipient data. - [Subscription topics](https://www.unitpost.com/docs/topics): Let contacts opt out of one kind of mail without leaving your list. - [Sending domains](https://www.unitpost.com/docs/domains): Add SPF, DKIM, and DMARC so mail sends from your domain. - [Open & click tracking](https://www.unitpost.com/docs/tracking): Control engagement tracking per send, template, or category. - [Batch sending](https://www.unitpost.com/docs/batch): Send up to 100 distinct messages — schedule and cancel as a unit. - [Scheduling & canceling sends](https://www.unitpost.com/docs/canceling): Schedule for later and recall a send before it leaves. - [Idempotency & retries](https://www.unitpost.com/docs/idempotency): Safely retry sends without duplicating mail. - [Bounces, complaints & suppression](https://www.unitpost.com/docs/deliverability): How bad addresses are handled and where to review them. - [Webhooks](https://www.unitpost.com/docs/webhooks): Receive signed event notifications at your own endpoint. - [Inbound routing](https://www.unitpost.com/docs/inbound): Receive emails at your domain and get clean JSON POSTed to your webhook. ## Product guides - [Dashboard](https://www.unitpost.com/guides/dashboard): Your account at a glance — sending health, recent activity, and what needs attention. - [Domains](https://www.unitpost.com/guides/domains): Verify sending domains so your mail authenticates and lands in the inbox. - [Templates](https://www.unitpost.com/guides/templates): Author reusable email content for campaigns and the API. - [Library](https://www.unitpost.com/guides/library): Store and manage images and assets your templates reference. - [Contacts](https://www.unitpost.com/guides/contacts): The people you can email — subscription state, custom fields, and imports. - [Suppressions](https://www.unitpost.com/guides/suppressions): Addresses blocked from receiving mail — protecting your sending reputation. - [Segments](https://www.unitpost.com/guides/segments): Named groups of contacts that campaigns send to. - [Subscription topics](https://www.unitpost.com/guides/topics): Let contacts opt out of one kind of mail without leaving your list. - [Campaigns](https://www.unitpost.com/guides/campaigns): Send a template to a segment — now or on a schedule — with server-enforced safety gates. - [Emails](https://www.unitpost.com/guides/emails): Every individual message sent — delivery status, opens, clicks, and bounces. - [Activity](https://www.unitpost.com/guides/activity): A chronological audit log of account events across every resource. - [API Keys](https://www.unitpost.com/guides/api-keys): Authenticate the API with scoped, least-privilege keys. - [Webhooks](https://www.unitpost.com/guides/webhooks): Receive signed, real-time event notifications at your own endpoint. - [Migration Assistant](https://www.unitpost.com/guides/migration): Move from Resend, SendGrid, Mailgun, Postmark, Brevo, or Loops with one read-only API key. ## Email design suite - [Email component library](https://www.unitpost.com/email): Email component library that works in Outlook, Gmail, and Apple Mail. MIT. Skill: `npx skills add unitpostcom/email`. npm: `npm install @unitpost/email zod`. No account. ([Markdown](https://www.unitpost.com/email.md)) - [Component library — Introduction](https://www.unitpost.com/components#introduction): Email component library that works in Outlook, Gmail, and Apple Mail. - [Component library — Installation](https://www.unitpost.com/components#installation): Add the package and render your first email in a few minutes. - [Component reference](https://www.unitpost.com/components#components): Every @unitpost/email building block (Section, Row, Column, Heading, Text, Button, Link, Image, Divider, Spacer, Markdown, Code, Html) with live previews and props tables. - [Pre-built layouts](https://www.unitpost.com/components#layouts): Ready-made section bands — headers, heroes, content cards, split columns, CTAs, footers — with copyable TSX. - [Email builder](https://www.unitpost.com/templates): Visual + code template builder — drag blocks or write TSX; both edit the same document. In your app, import React components from @unitpost/email/react. - [Template gallery](https://www.unitpost.com/templates/gallery): Free, ready-to-send transactional and marketing templates — preview and copy the code without an account, or clone into a workspace. - [Playground](https://www.unitpost.com/playground): Write email code in the browser and see the exact HTML the Unitpost engine produces — no account or install needed. - npm: `npm install @unitpost/email zod` — the MIT-licensed document model + cross-client HTML renderer. Works fully offline/standalone; no Unitpost account required to render email HTML. Source: https://github.com/unitpostcom/email ## API endpoints - `GET /api/v1/email`: List sent emails Retrieve a list of emails your workspace has sent or scheduled. Results are newest-first and cursor-paginated, and each row is a reference to a single email (status and lifecycle timestamps, not the rendered body). Narrow the list with the `status`, `campaign_id`, `batch_id`, and `created_after`/`created_before` filters. Use an email's `id` with [Retrieve an email](https://www.unitpost.com/docs#get-email-id) to read its full record, or [Cancel or reschedule an email](https://www.unitpost.com/docs#patch-email-id) to change a scheduled send. For aggregate deliverability numbers over a window, see [Email deliverability stats](https://www.unitpost.com/docs#get-email-stats). Requires the `emails:read` capability. - `POST /api/v1/email`: Send or schedule an email Send a single transactional email — now, or at a future time by passing `scheduled_at`. Provide the content inline as `html`/`text`, or reference a saved template with `template` (create one with [Create a template](https://www.unitpost.com/docs#post-email-templates)). Pass an `Idempotency-Key` header to make retries safe: the same key replays the original result instead of sending twice. The response returns the new email's `id` — read its delivery status back with [Retrieve an email](https://www.unitpost.com/docs#get-email-id), change a scheduled send with [Cancel or reschedule an email](https://www.unitpost.com/docs#patch-email-id), or send many at once with [Send a batch of emails](https://www.unitpost.com/docs#post-email-batch). Requires the `emails:send` capability. - `POST /api/v1/email/batch`: Send a batch of emails Send up to 100 transactional emails in a single request. Validation is all-or-nothing: if any item is invalid the whole batch is rejected and nothing is queued, so you never end up with a partial send. Pass an `Idempotency-Key` header to make retries safe — the same key replays the original result instead of re-sending. The response returns a `batch_id`; track the batch's per-status rollup with [Retrieve a batch](https://www.unitpost.com/docs#get-email-batches-id) and stop the rest of it with [Cancel a batch](https://www.unitpost.com/docs#post-email-batches-id-cancel). To send one email, use [Send or schedule an email](https://www.unitpost.com/docs#post-email). Requires the `emails:send` capability. - `GET /api/v1/email/batches/{id}`: Retrieve a batch Retrieve a batch and its live, per-status rollup (how many of its messages are queued, sent, delivered, bounced, and so on). The counts update as the batch progresses. Create a batch with [Send a batch of emails](https://www.unitpost.com/docs#post-email-batch), or stop its remaining messages with [Cancel a batch](https://www.unitpost.com/docs#post-email-batches-id-cancel). Requires the `emails:read` capability. - `POST /api/v1/email/batches/{id}/cancel`: Cancel a batch Cancel every still-cancelable message in a batch in one call. Messages that have already been sent are left untouched — only queued or scheduled ones are stopped. Check what remains cancelable first with [Retrieve a batch](https://www.unitpost.com/docs#get-email-batches-id). Requires the `emails:send` capability. - `GET /api/v1/email/{id}`: Retrieve an email Retrieve a single email by `id`, including its current send status and lifecycle timestamps (created, scheduled, sent, delivered, and so on). Find an `id` by browsing [List sent emails](https://www.unitpost.com/docs#get-email). To change a scheduled or queued email, use [Cancel or reschedule an email](https://www.unitpost.com/docs#patch-email-id). Requires the `emails:read` capability. - `PATCH /api/v1/email/{id}`: Cancel or reschedule an email Cancel a scheduled or queued email, or move it to a new send time. Only emails that haven't been handed off for delivery yet can be changed — once an email is sent this returns `409`. Look up the email's current state first with [Retrieve an email](https://www.unitpost.com/docs#get-email-id). Requires the `emails:send` capability. - `GET /api/v1/email/stats`: Email deliverability stats Retrieve aggregate deliverability and engagement metrics for your workspace over a rolling window. You get totals (sent, delivered, opened, clicked, bounced, complained, failed) alongside the rates that matter — delivery, open, click, bounce, and complaint. Open and click rates count only emails where that tracking was enabled, so turning tracking off for transactional mail won't skew them. Control the window with the `days` parameter (1–365, default 30). For the individual emails behind these numbers, see [List sent emails](https://www.unitpost.com/docs#get-email). Requires the `emails:read` capability. - `GET /api/v1/email/received`: List received emails Retrieve a list of inbound emails received on your receiving-enabled domains, newest-first and cursor-paginated. Rows are summaries (sender, subject, timestamps) without bodies — use a message's `id` with [Retrieve a received email](https://www.unitpost.com/docs#get-email-received-id) to read the full content and attachment metadata. Requires the `emails:read` capability. - `GET /api/v1/email/received/{id}`: Retrieve a received email Retrieve a full inbound message by `id`, including its HTML and text bodies plus metadata for every attachment. Attachment bytes aren't inlined — download each one via [Get an attachment download URL](https://www.unitpost.com/docs#get-email-received-id-attachments-attachmentid). Browse your inbound mail with [List received emails](https://www.unitpost.com/docs#get-email-received). Requires the `emails:read` capability. - `GET /api/v1/email/received/{id}/attachments/{attachmentId}`: Get an attachment download URL Get a short-lived, signed URL for downloading one inbound attachment's bytes. Fetch the URL and download promptly — it expires quickly (the expiry is included in the response). Find attachment ids on the message via [Retrieve a received email](https://www.unitpost.com/docs#get-email-received-id). Requires the `emails:read` capability. - `GET /api/v1/contacts`: List contacts Retrieve a list of the contacts in your workspace, newest-first and cursor-paginated. Each row includes the contact's core fields and any custom field values. Use a contact's `id` (or email) with [Retrieve a contact](https://www.unitpost.com/docs#get-contacts-id) for the full record, add contacts with [Create a contact](https://www.unitpost.com/docs#post-contacts), or bring a list in bulk with [Start an async contact import](https://www.unitpost.com/docs#post-contacts-imports). Requires the `contacts:read` capability. - `POST /api/v1/contacts`: Create a contact Add a single contact to your workspace. Set an `email` plus any standard or custom field values; custom fields must already exist (define them with [Create a custom contact field](https://www.unitpost.com/docs#post-contact-fields)). Emails are unique per workspace, so creating one that already exists returns `409` — use [Update a contact](https://www.unitpost.com/docs#patch-contacts-id) to change an existing contact, or [Start an async contact import](https://www.unitpost.com/docs#post-contacts-imports) to add many at once. Requires the `contacts:write` capability. - `GET /api/v1/contacts/{id}`: Retrieve a contact Retrieve a single contact and all of its field values. The `{id}` path segment accepts either the contact's id or its email address, so you can look a contact up without storing our id. Change it with [Update a contact](https://www.unitpost.com/docs#patch-contacts-id), or see which subscription topics it's opted into with [List a contact's topic subscriptions](https://www.unitpost.com/docs#get-contacts-id-topics). Requires the `contacts:read` capability. - `PATCH /api/v1/contacts/{id}`: Update a contact Update a contact's standard or custom field values. Only the fields you send are changed; omitted fields are left as-is. The `{id}` accepts a contact id or email. To manage a contact's subscription preferences instead, use [Set a contact's topic preference](https://www.unitpost.com/docs#post-contacts-id-topics). Requires the `contacts:write` capability. - `DELETE /api/v1/contacts/{id}`: Delete a contact Permanently delete a contact and its field values. This also removes the contact from every segment it belonged to. To stop mailing someone without deleting them, unsubscribe them from a topic with [Set a contact's topic preference](https://www.unitpost.com/docs#post-contacts-id-topics) or add them to your [suppression list](https://www.unitpost.com/docs#post-suppressions) instead. Requires the `contacts:write` capability. - `GET /api/v1/contacts/imports`: List contact imports Retrieve a list of your bulk contact-import jobs, newest-first and cursor-paginated. Each row is a reference to one import and its current progress. Start a new one with [Start an async contact import](https://www.unitpost.com/docs#post-contacts-imports), or drill into a single job with [Retrieve a contact import](https://www.unitpost.com/docs#get-contacts-imports-id). Requires the `contacts:read` capability. - `POST /api/v1/contacts/imports`: Start an async contact import Import a batch of contacts (up to 5,000 per request) in the background. The call returns immediately with an import job you poll for progress and per-row results — new contacts are created and existing ones (matched by email) are updated. Track it with [Retrieve a contact import](https://www.unitpost.com/docs#get-contacts-imports-id), or see all your imports via [List contact imports](https://www.unitpost.com/docs#get-contacts-imports). To add a single contact synchronously, use [Create a contact](https://www.unitpost.com/docs#post-contacts). Requires the `contacts:write` capability. - `GET /api/v1/contacts/imports/{id}`: Retrieve a contact import Retrieve a bulk import job by `id` to check its status and per-row results — how many contacts were created, updated, or skipped, and why any rows failed. Poll this while an import runs. Start one with [Start an async contact import](https://www.unitpost.com/docs#post-contacts-imports). Requires the `contacts:read` capability. - `GET /api/v1/contact-fields`: List custom contact fields Retrieve a list of the custom contact fields defined in your workspace, cursor-paginated. These are the typed attributes (text, number, date, boolean, and so on) you can set on any contact and reference as template variables. Define a new one with [Create a custom contact field](https://www.unitpost.com/docs#post-contact-fields). Requires the `contacts:read` capability. - `POST /api/v1/contact-fields`: Create a custom contact field Define a new typed custom field that can then be set on any contact and used as a template variable (e.g. `plan`, `signup_date`). The `key` and `type` are fixed once created — rename the key later with [Rename a custom field's key](https://www.unitpost.com/docs#post-contact-fields-id-rename), or change the label with [Update a custom contact field](https://www.unitpost.com/docs#patch-contact-fields-id). See existing fields via [List custom contact fields](https://www.unitpost.com/docs#get-contact-fields). Requires the `contacts:write` capability. - `GET /api/v1/contact-fields/{id}`: Retrieve a custom contact field Retrieve a single custom contact field by `id`, including its key, type, and label. Update its label with [Update a custom contact field](https://www.unitpost.com/docs#patch-contact-fields-id), or rename the key with [Rename a custom field's key](https://www.unitpost.com/docs#post-contact-fields-id-rename). Requires the `contacts:read` capability. - `PATCH /api/v1/contact-fields/{id}`: Update a custom contact field Update a custom field's editable metadata, such as its display label. The `key` and `type` are immutable here — to change the key (and migrate every contact's stored value) use [Rename a custom field's key](https://www.unitpost.com/docs#post-contact-fields-id-rename) instead. Requires the `contacts:write` capability. - `DELETE /api/v1/contact-fields/{id}`: Delete a custom contact field Permanently delete a custom field definition and strip its stored value from every contact. Any template variable that referenced it will resolve to empty. This can't be undone — recreate the field with [Create a custom contact field](https://www.unitpost.com/docs#post-contact-fields) if you need it back. Requires the `contacts:write` capability. - `POST /api/v1/contact-fields/{id}/rename`: Rename a custom field's key Change a custom field's `key`, migrating the stored value on every contact so no data is lost. Because the key is how templates and the API reference the field, update any template variables that used the old key. To change only the display label, use [Update a custom contact field](https://www.unitpost.com/docs#patch-contact-fields-id). Requires the `contacts:write` capability. - `GET /api/v1/segments`: List segments Retrieve a list of the segments in your workspace, cursor-paginated. A segment is a saved group of contacts you can target when sending a campaign. Create one with [Create a segment](https://www.unitpost.com/docs#post-segments), or list a segment's members with [List segment members](https://www.unitpost.com/docs#get-segments-id-contacts). Requires the `segments:read` capability. - `POST /api/v1/segments`: Create a segment Create a segment — a named group of contacts you can target when sending a campaign. Once created, add contacts with [Add a member](https://www.unitpost.com/docs#post-segments-id-contacts) and target it from [Create a campaign](https://www.unitpost.com/docs#post-email-campaigns). To let recipients opt out of a category of mail instead, see [Create a topic](https://www.unitpost.com/docs#post-email-topics). Requires the `segments:write` capability. - `GET /api/v1/segments/{id}`: Retrieve a segment Retrieve a single segment by `id`, including its name and member count. To page through the contacts inside it, use [List segment members](https://www.unitpost.com/docs#get-segments-id-contacts). Requires the `segments:read` capability. - `PATCH /api/v1/segments/{id}`: Update a segment Update a segment's editable metadata, such as its name. To change who's in the segment, add or remove members with [Add a member](https://www.unitpost.com/docs#post-segments-id-contacts) and [Remove a member](https://www.unitpost.com/docs#delete-segments-id-contacts-contact). Requires the `segments:write` capability. - `DELETE /api/v1/segments/{id}`: Delete a segment Delete a segment. The contacts themselves are untouched — only the grouping is removed. This is blocked with `409` while an active campaign still targets the segment; cancel or finish that campaign first (see [List campaigns](https://www.unitpost.com/docs#get-email-campaigns)). Requires the `segments:write` capability. - `GET /api/v1/segments/{id}/contacts`: List segment members Retrieve the contacts in a segment, cursor-paginated. Add a contact with [Add a member](https://www.unitpost.com/docs#post-segments-id-contacts) or take one out with [Remove a member](https://www.unitpost.com/docs#delete-segments-id-contacts-contact). Requires the `segments:read` capability. - `POST /api/v1/segments/{id}/contacts`: Add a member Add a contact to a segment, referenced by contact id or email. The operation is idempotent — adding a contact that's already a member is a no-op and still succeeds. See the current members with [List segment members](https://www.unitpost.com/docs#get-segments-id-contacts). Requires the `segments:write` capability. - `DELETE /api/v1/segments/{id}/contacts/{contact}`: Remove a member Remove a contact from a segment, referenced by contact id or email. The contact itself is not deleted — only its membership. Add it back any time with [Add a member](https://www.unitpost.com/docs#post-segments-id-contacts). Requires the `segments:write` capability. - `GET /api/v1/email/topics`: List topics Retrieve a list of your subscription topics, cursor-paginated. A topic is a category of email (e.g. Product updates, Promotions) that recipients can opt out of without leaving your list entirely. Pass `?archived=true` to list archived topics instead. Create one with [Create a topic](https://www.unitpost.com/docs#post-email-topics), or check a contact's preferences with [List a contact's topic subscriptions](https://www.unitpost.com/docs#get-contacts-id-topics). Requires the `topics:read` capability. - `POST /api/v1/email/topics`: Create a topic Create a subscription topic — a category recipients can opt out of on their own (e.g. Promotions) while staying on your list. `default_opt_in` decides whether contacts with no explicit preference are treated as subscribed. Scope a campaign to a topic so opted-out contacts are skipped automatically via [Create a campaign](https://www.unitpost.com/docs#post-email-campaigns), and set an individual contact's preference with [Set a contact's topic preference](https://www.unitpost.com/docs#post-contacts-id-topics). Topics differ from segments: a [segment](https://www.unitpost.com/docs#post-segments) decides who a campaign targets, a topic lets recipients opt out. Requires the `topics:write` capability. - `GET /api/v1/email/topics/{id}`: Retrieve a topic Retrieve a single topic by `id`, including its name and `default_opt_in` setting. Change it with [Update a topic](https://www.unitpost.com/docs#patch-email-topics-id), or list every topic with [List topics](https://www.unitpost.com/docs#get-email-topics). Requires the `topics:read` capability. - `PATCH /api/v1/email/topics/{id}`: Update a topic Update a topic's name or `default_opt_in` behavior, or pass `{ "archived": true | false }` to archive or restore it. Archiving a topic hides it and stops it from being targeted, but is blocked with `409` while an active campaign still targets it. To manage a single contact's preference, use [Set a contact's topic preference](https://www.unitpost.com/docs#post-contacts-id-topics). Requires the `topics:write` capability. - `DELETE /api/v1/email/topics/{id}`: Delete a topic Archive a topic (a soft delete — existing subscription records are preserved so you can restore it later). It's blocked with `409` while an active campaign still targets it. Restore an archived topic by sending `{ "archived": false }` to [Update a topic](https://www.unitpost.com/docs#patch-email-topics-id). Requires the `topics:write` capability. - `GET /api/v1/contacts/{id}/topics`: List a contact's topic subscriptions Retrieve a contact's effective subscription state for every active topic, cursor-paginated. Each row resolves the contact's explicit preference against the topic's `default_opt_in`, so `subscribed` is always the answer to "would this contact receive a campaign scoped to this topic?". Change a preference with [Set a contact's topic preference](https://www.unitpost.com/docs#post-contacts-id-topics). Requires the `topics:read` capability. - `POST /api/v1/contacts/{id}/topics`: Set a contact's topic preference Subscribe or unsubscribe a contact for one topic. This records an explicit preference that overrides the topic's `default_opt_in`, and it's idempotent — setting the same preference twice succeeds. `PUT` behaves identically. Read the contact's current state with [List a contact's topic subscriptions](https://www.unitpost.com/docs#get-contacts-id-topics). Requires the `topics:write` capability. - `PUT /api/v1/contacts/{id}/topics`: Set a contact's topic preference (alias of POST) Identical to [Set a contact's topic preference](https://www.unitpost.com/docs#post-contacts-id-topics) — provided so clients that prefer `PUT` semantics for an upsert can use it interchangeably. Requires the `topics:write` capability. - `GET /api/v1/email/campaigns`: List campaigns Retrieve a list of your campaigns, cursor-paginated. Each row is a reference to one campaign and its current status (`draft`, `scheduled`, `sending`, `sent`, …). Use a campaign's `id` with [Retrieve a campaign](https://www.unitpost.com/docs#get-email-campaigns-id) for the full record, or with [List sent emails](https://www.unitpost.com/docs#get-email) (`?campaign_id=`) to see the individual emails it produced. Requires the `campaigns:read` capability. - `POST /api/v1/email/campaigns`: Create a campaign Create a campaign in `draft`. Target either a saved segment (`segment_id`, see [Create a segment](https://www.unitpost.com/docs#post-segments)) or an inline `recipients` list, and optionally scope it to a subscription topic (`topic_id`) so contacts who opted out of that topic are skipped automatically. Content comes from a published `template_id` (campaigns have no inline `html`/`text`). Nothing is sent yet — edit the draft with [Update a campaign](https://www.unitpost.com/docs#patch-email-campaigns-id), check it with [Validate a campaign](https://www.unitpost.com/docs#get-email-campaigns-id-validate), then launch it with [Send a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-send). Requires the `campaigns:write` capability. - `GET /api/v1/email/campaigns/{id}`: Retrieve a campaign Retrieve a single campaign by `id`, including its status, targeting, content references, and schedule. To see the individual emails a sent campaign produced, filter [List sent emails](https://www.unitpost.com/docs#get-email) by `campaign_id`; for a pre-send readiness report, use [Validate a campaign](https://www.unitpost.com/docs#get-email-campaigns-id-validate). Requires the `campaigns:read` capability. - `PATCH /api/v1/email/campaigns/{id}`: Update a campaign Edit a campaign while it's still in `draft` (content edits after that return `409`). Beyond content and targeting, you can: send `archived` to archive/restore it; set `variable_fallbacks` (fill-only per-variable defaults) and/or `excluded_contact_ids` to resolve a send blocked by missing variables — the API equivalent of the dashboard's pre-send fix; set `topic_id` to scope it to a subscription topic (or `null` to clear); and set `open_tracking`/`click_tracking` (tri-state; `null` inherits the template/domain default). See what's blocking a send with [Validate a campaign](https://www.unitpost.com/docs#get-email-campaigns-id-validate). Requires the `campaigns:write` capability. - `DELETE /api/v1/email/campaigns/{id}`: Delete a campaign Permanently delete a campaign that's in `draft` or a terminal state (sent, canceled, failed). A campaign that's mid-flight can't be deleted — stop it first with [Cancel a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-cancel). Requires the `campaigns:write` capability. - `POST /api/v1/email/campaigns/{id}/send`: Send a campaign Validate a campaign and then send it — immediately, or at its `scheduled_at` if one is set. If anything blocks the send (unverified domain, missing template variables, empty audience, …) you get a `409` with each blocking reason itemized in `error.details[]`. To see the full pre-send report without attempting a send, use [Validate a campaign](https://www.unitpost.com/docs#get-email-campaigns-id-validate); fix variable issues via [Update a campaign](https://www.unitpost.com/docs#patch-email-campaigns-id). A launched campaign can be [paused](https://www.unitpost.com/docs#post-email-campaigns-id-pause) or [canceled](https://www.unitpost.com/docs#post-email-campaigns-id-cancel). Requires the `campaigns:send` capability. - `POST /api/v1/email/campaigns/{id}/cancel`: Cancel a campaign Cancel a `draft`, `scheduled`, or `sending` campaign. Cancelation is terminal — the campaign can't be restarted afterwards. Messages already sent to recipients are not recalled. If you only want to stop temporarily, use [Pause a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-pause) instead. Requires the `campaigns:send` capability. - `POST /api/v1/email/campaigns/{id}/pause`: Pause a campaign Pause a `scheduled` or `sending` campaign. A paused send stops cleanly between recipients — already-sent messages are untouched, and no partial email is ever produced. Continue where it left off with [Resume a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-resume), or stop it for good with [Cancel a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-cancel). Requires the `campaigns:send` capability. - `POST /api/v1/email/campaigns/{id}/resume`: Resume a campaign Resume a `paused` campaign. Sending continues with the recipients that hadn't been reached yet; anyone already delivered to is skipped idempotently, so nobody receives the campaign twice. Pause a send with [Pause a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-pause). Requires the `campaigns:send` capability. - `POST /api/v1/email/campaigns/{id}/reschedule`: Reschedule a campaign Move a `scheduled` campaign to a new send time. Only campaigns that haven't started sending can be rescheduled — once a send is in flight, [pause](https://www.unitpost.com/docs#post-email-campaigns-id-pause) or [cancel](https://www.unitpost.com/docs#post-email-campaigns-id-cancel) it instead. Requires the `campaigns:send` capability. - `GET /api/v1/email/campaigns/{id}/validate`: Validate a campaign Run a non-mutating pre-send check and get the full readiness report: how many contacts will receive the campaign, how many are suppressed or excluded, which contacts are missing template variables, and a final `can_send` verdict. Nothing is sent or changed. Fix reported variable gaps with [Update a campaign](https://www.unitpost.com/docs#patch-email-campaigns-id) (`variable_fallbacks` / `excluded_contact_ids`), then launch with [Send a campaign](https://www.unitpost.com/docs#post-email-campaigns-id-send). Requires the `campaigns:read` capability. - `GET /api/v1/email/templates`: List templates Retrieve a list of your email templates, cursor-paginated. List rows omit `html` to keep responses small — fetch a single template with [Retrieve a template](https://www.unitpost.com/docs#get-email-templates-id) to get it. Reference a template's `id` when sending with [Send or schedule an email](https://www.unitpost.com/docs#post-email) or when creating a campaign. Requires the `templates:read` capability. - `POST /api/v1/email/templates`: Create a template Create a reusable email template from `html` (and optional `subject`). `{{variables}}` in the HTML fill per-recipient at send time. The body is stored in code mode so you can open it in the dashboard. Once created, send with it via [Send or schedule an email](https://www.unitpost.com/docs#post-email), and iterate with [Update a template](https://www.unitpost.com/docs#patch-email-templates-id). Requires the `templates:write` capability. - `GET /api/v1/email/templates/{id}`: Retrieve a template Retrieve a single template by `id`, including `html` (which [List templates](https://www.unitpost.com/docs#get-email-templates) omits). Use this to read the body, then save changes with [Update a template](https://www.unitpost.com/docs#patch-email-templates-id). Requires the `templates:read` capability. - `PATCH /api/v1/email/templates/{id}`: Update a template Update a template's metadata and/or `html`. Changes take effect for future sends only — emails already sent or queued keep the body they were rendered with. Writing `html` switches the template to code mode. Read the current body first with [Retrieve a template](https://www.unitpost.com/docs#get-email-templates-id). Requires the `templates:write` capability. - `DELETE /api/v1/email/templates/{id}`: Delete a template Permanently delete a template. Emails already sent with it are unaffected, but future sends that reference its id will fail — update any code or campaigns that still point at it first (see [List campaigns](https://www.unitpost.com/docs#get-email-campaigns)). Requires the `templates:write` capability. - `GET /api/v1/brand-kits`: List brand kits Retrieve every Brand Kit profile in the workspace (up to five named profiles). Each profile holds tone, about, voice notes, labeled colors, pinned logo/background library images, and core pages — the primary brand context for on-brand template authoring. Pass `?name=` to filter to one profile by display name (case-insensitive). The response includes `default_id` for the Default profile. Fetch one by id with [Retrieve a brand kit](https://www.unitpost.com/docs#get-brand-kits-id). Writes and URL import stay in the dashboard (Settings → Brand). Requires the `templates:read` capability. - `GET /api/v1/brand-kits/{id}`: Retrieve a brand kit Retrieve one Brand Kit profile by `id` (`bk_…`), including voice, labeled colors, pinned graphics (`library_image_id` for `/img/{id}` in design TSX), and core pages. List every profile with [List brand kits](https://www.unitpost.com/docs#get-brand-kits). Requires the `templates:read` capability. - `GET /api/v1/email/domains`: List domains Retrieve a list of your sending domains, cursor-paginated, with each domain's verification status. Add a new one with [Add a domain](https://www.unitpost.com/docs#post-email-domains), or fetch a single domain (including its DNS records) with [Retrieve a domain](https://www.unitpost.com/docs#get-email-domains-id). Requires the `domains:read` capability. - `POST /api/v1/email/domains`: Add a domain Add a domain you'll send email from. The response includes the DNS `records` (SPF, DKIM, and so on) to publish with your DNS provider. Once they're published, trigger a check with [Verify a domain](https://www.unitpost.com/docs#post-email-domains-id-verify) — sending from the domain is blocked until it verifies. Requires the `domains:write` capability. - `GET /api/v1/email/domains/{id}`: Retrieve a domain Retrieve a single sending domain by `id`, including its current verification status and the DNS `records` you need to publish. Re-run the DNS check with [Verify a domain](https://www.unitpost.com/docs#post-email-domains-id-verify), or change its tracking/TLS settings with [Update a domain](https://www.unitpost.com/docs#patch-email-domains-id). Requires the `domains:read` capability. - `DELETE /api/v1/email/domains/{id}`: Delete a domain Remove a sending domain from your workspace. Sends that reference an address on this domain will be rejected afterwards, so update your `from` addresses first. Re-add it any time with [Add a domain](https://www.unitpost.com/docs#post-email-domains) (you'll need to verify it again). Requires the `domains:write` capability. - `PATCH /api/v1/email/domains/{id}`: Update a domain Update a domain's sending options: open/click tracking defaults, TLS enforcement, and the tracking subdomain. These act as the domain-level defaults that individual emails and campaigns can override (see [Update a campaign](https://www.unitpost.com/docs#patch-email-campaigns-id)). Requires the `domains:write` capability. - `POST /api/v1/email/domains/{id}/verify`: Verify a domain Run an on-demand DNS check and advance the domain's verification status. The response includes per-record `checks` so you can see exactly which DNS records are still missing or wrong. Get the records to publish from [Retrieve a domain](https://www.unitpost.com/docs#get-email-domains-id). Verification also re-runs periodically in the background. Requires the `domains:write` capability. - `GET /api/v1/webhooks`: List webhook endpoints Retrieve a list of your webhook endpoints, cursor-paginated, with each endpoint's URL, subscribed events, and status. Signing secrets are never returned here — they're shown exactly once by [Create a webhook endpoint](https://www.unitpost.com/docs#post-webhooks). Check an endpoint's wiring end-to-end with [Send a test event](https://www.unitpost.com/docs#post-webhooks-id-test). Requires the `webhooks:read` capability. - `POST /api/v1/webhooks`: Create a webhook endpoint Register an `https` URL to receive event notifications (deliveries, bounces, opens, clicks, and more) and choose which events it subscribes to. The response includes the `signing_secret` exactly once — store it now, as it can never be retrieved again; use it to verify each delivery's signature. Confirm the endpoint works with [Send a test event](https://www.unitpost.com/docs#post-webhooks-id-test), and adjust its URL or events later with [Update a webhook endpoint](https://www.unitpost.com/docs#patch-webhooks-id). Requires the `webhooks:manage` capability. - `GET /api/v1/webhooks/{id}`: Retrieve a webhook endpoint Retrieve a single webhook endpoint by `id` — its URL, subscribed events, and status. The signing secret is never included; it's returned exactly once when the endpoint is [created](https://www.unitpost.com/docs#post-webhooks). Requires the `webhooks:read` capability. - `PATCH /api/v1/webhooks/{id}`: Update a webhook endpoint Update a webhook endpoint's `url`, subscribed `events`, `name`, and/or `status` (use `status` to pause and re-enable deliveries without deleting the endpoint). The signing secret is never changed by an update. Verify your changes with [Send a test event](https://www.unitpost.com/docs#post-webhooks-id-test). Requires the `webhooks:manage` capability. - `DELETE /api/v1/webhooks/{id}`: Delete a webhook endpoint Permanently delete a webhook endpoint and its delivery log. Deliveries stop immediately. The operation is idempotent — deleting an already-deleted endpoint still returns `204`. To stop deliveries temporarily instead, set `status` via [Update a webhook endpoint](https://www.unitpost.com/docs#patch-webhooks-id). Requires the `webhooks:manage` capability. - `POST /api/v1/webhooks/{id}/test`: Send a test event Fire a sample event at the endpoint synchronously and return the receiver's response so you can debug your handler end-to-end. The probe is signed exactly like a real delivery (verify it the same way) but is not persisted to the delivery log. Configure the endpoint itself with [Update a webhook endpoint](https://www.unitpost.com/docs#patch-webhooks-id). Requires the `webhooks:manage` capability. - `GET /api/v1/sms`: List SMS messages Retrieve your workspace's SMS messages (outbound and inbound), newest-first and cursor-paginated. Use a message's `id` with [Retrieve an SMS message](https://www.unitpost.com/docs#get-sms-id) to read its delivery state. Requires the `sms:read` capability. - `POST /api/v1/sms`: Send an SMS message Send a single SMS — now, or at a future time by passing `scheduled_at`. The recipient must be a valid E.164 number; marketing sends additionally require the recipient's prior express consent on record and honor recipient-local quiet hours (they are deferred to the next allowed window, never dropped). Billing is per segment. Read delivery state back with [Retrieve an SMS message](https://www.unitpost.com/docs#get-sms-id). Requires the `sms:send` capability. - `GET /api/v1/sms/{id}`: Retrieve an SMS message Retrieve one SMS message's current status, delivery state, and segment count by `id`. Requires the `sms:read` capability. - `GET /api/v1/api-keys`: List API keys Retrieve a list of your workspace's API keys — the key prefix and metadata only, never the secret. Create a new key with [Create an API key](https://www.unitpost.com/docs#post-api-keys) or revoke one with [Revoke an API key](https://www.unitpost.com/docs#delete-api-keys-id). This endpoint is session-gated: it requires a dashboard session and cannot be called with a Bearer API key. - `POST /api/v1/api-keys`: Create an API key Create an API key scoped to the capabilities you choose. The response includes the plaintext `key` exactly once — store it securely now, because it can never be retrieved again (only [revoked](https://www.unitpost.com/docs#delete-api-keys-id)). This endpoint is session-gated: it requires a dashboard session and cannot be called with a Bearer API key. - `DELETE /api/v1/api-keys/{id}`: Revoke an API key Permanently revoke an API key. Requests made with it start failing with `401` immediately, and revocation cannot be undone — create a replacement first with [Create an API key](https://www.unitpost.com/docs#post-api-keys) if you're rotating. This endpoint is session-gated: it requires a dashboard session and cannot be called with a Bearer API key. - `GET /api/v1/suppressions`: List suppressed addresses Retrieve a list of email addresses that are blocked from receiving your mail, newest-first and cursor-paginated. The list includes your workspace's own suppressions AND the read-only Unitpost-wide (`platform`) entries that would block a send — so it's the complete answer to "why isn't this address getting mail?". Pass `?scope=workspace` to hide platform rows. Add an address with [Suppress an address](https://www.unitpost.com/docs#post-suppressions) or lift a block with [Un-suppress an address](https://www.unitpost.com/docs#delete-suppressions-id). Requires the `suppressions:read` capability. - `POST /api/v1/suppressions`: Suppress an address Block one address (`{ email }`) or up to 1,000 at once (`{ emails: [...] }`) from receiving any future sends from your workspace. The operation is idempotent — re-suppressing an existing address returns `200` rather than a conflict. The bulk form returns an `{ object: "list", added, skipped, total }` summary. Suppression is the hard stop; to let recipients opt out of just one kind of email, use topics (see [Create a topic](https://www.unitpost.com/docs#post-email-topics)). Undo with [Un-suppress an address](https://www.unitpost.com/docs#delete-suppressions-id). Requires the `suppressions:write` capability. - `GET /api/v1/suppressions/{id}`: Retrieve a suppressed address Retrieve one suppression by id (`supp_…`) or by the email address itself. Returns your own workspace row, or a read-only `platform` row when the address is blocked Unitpost-wide. Lift a workspace block with [Un-suppress an address](https://www.unitpost.com/docs#delete-suppressions-id). Requires the `suppressions:read` capability. - `DELETE /api/v1/suppressions/{id}`: Un-suppress an address Remove a workspace suppression by id or email so the address can receive your mail again. The email form is idempotent — removing an address that isn't suppressed still returns `204`. Unitpost-wide (`platform`) entries can't be removed here (`403`) — contact support. Check what's blocking an address first with [Retrieve a suppressed address](https://www.unitpost.com/docs#get-suppressions-id). Requires the `suppressions:write` capability. - `GET /api/v1/usage`: Retrieve usage Retrieve your workspace's current billing-period usage snapshot: the plan, the period window, and the email counter. On paid plans the response also carries the dollar sending `wallet` — the monthly allowance included with the plan, spend so far, any upgrade carryover, the non-expiring purchased-credit balance, and billable overage — all as integer USD cents. On the free plan `wallet` is null and the `emails` object carries the monthly quota and daily cap instead. Amounts are read from the same meters that gate sending, so this matches the dashboard exactly. Requires the `emails:read` capability. ## OpenAPI - [OpenAPI 3.1 spec](https://www.unitpost.com/api/v1/openapi.json) ## Email engineering guides - [Why domain verification should never be a one-time check](https://www.unitpost.com/blog/concepts/continuous-domain-verification): DNS changes after you verify a domain. How continuous re-verification with a grace period catches regressions without turning a transient blip into an outage. - [Why DKIM verification fails (and how to fix each cause)](https://www.unitpost.com/blog/troubleshooting/dkim-verification-failing): The concrete reasons a DKIM check fails after you've published the key: selector mismatch, a truncated public key, DNS flattening, and message modification in transit. - [Why your transactional email goes to spam](https://www.unitpost.com/blog/deliverability/email-going-to-spam): A diagnostic order of operations for transactional mail landing in spam: authentication, reputation, content, and the engagement signals you can't see. - [What is an email MCP server?](https://www.unitpost.com/blog/agents/email-mcp-server): How Model Context Protocol exposes email sending as agent tools, what a well-designed email MCP surface looks like, and how authentication and scopes work. - [How email webhooks work (they're POST)](https://www.unitpost.com/blog/concepts/how-email-webhooks-work): An email webhook is an HTTP POST to your URL when a message is delivered, bounced, opened, or clicked — not polling, not IMAP. - [Move off SendGrid SMTP after the free plan ended](https://www.unitpost.com/blog/concepts/move-off-sendgrid-smtp): SendGrid retired its free plan. Point the same SMTP client at Unitpost — host, username unitpost, API key as password — without rewriting your app. - [How to let an AI agent send email safely](https://www.unitpost.com/blog/agents/send-email-from-ai-agent): The concrete controls that make agent-initiated email safe: scoped credentials, a verified-domain gate, idempotency, approval before send, and an audit trail. - [How to fix an SPF record that isn't found](https://www.unitpost.com/blog/troubleshooting/spf-record-not-found): Why an SPF lookup returns nothing even after you've added the record, and how to diagnose it: propagation, wrong host, quoting, and the one-SPF-record rule. - [Transactional vs marketing email: what's the difference?](https://www.unitpost.com/blog/concepts/transactional-vs-marketing-email): The practical distinction between transactional and marketing email — consent, unsubscribe obligations, reputation risk — and when one tool for both is the right call. - [What is an idempotency key, and when do you need one?](https://www.unitpost.com/blog/concepts/what-is-an-idempotency-key): How idempotency keys prevent duplicate sends when a request is retried, how to choose one, and the failure modes they don't cover. ## Comparisons - [Unitpost vs Resend](https://www.unitpost.com/alternatives/resend): A developer-first transactional email API, known for the cleanest DX in the category and for React Email. Includes where Resend is the better choice, and a one-key migration path. - [Unitpost vs SendGrid](https://www.unitpost.com/alternatives/sendgrid): The Twilio-owned incumbent, processing billions of emails a month across transactional and marketing with deep enterprise tooling. Includes where SendGrid is the better choice, and a one-key migration path. - [Unitpost vs Postmark](https://www.unitpost.com/alternatives/postmark): A transactional-only specialist with the strongest deliverability and time-to-inbox reputation in the category. Includes where Postmark is the better choice, and a one-key migration path. - [Unitpost vs Mailgun](https://www.unitpost.com/alternatives/mailgun): Sinch-owned email infrastructure aimed at developers, with strong validation and deliverability tooling. Includes where Mailgun is the better choice, and a one-key migration path. - [Unitpost vs Brevo](https://www.unitpost.com/alternatives/brevo): An all-in-one marketing platform (formerly Sendinblue) covering email, SMS, chat, and CRM, with a transactional API alongside. Includes where Brevo is the better choice, and a one-key migration path. - [Unitpost vs Loops](https://www.unitpost.com/alternatives/loops): A modern, design-led email platform aimed at SaaS companies, focused on marketing sequences and lifecycle email. Includes where Loops is the better choice, and a one-key migration path.