---
title: "Set up a sender, draft, approve, launch or stop an email campaign (emails:write)."
method: POST
path: "/v1/email-campaigns"
---

# Set up a sender, draft, approve, launch or stop an email campaign (emails:write).

`POST /v1/email-campaigns`

## Request

- Base URL: `https://www.kaicalls.com/api`
- URL: `https://www.kaicalls.com/api/v1/email-campaigns`
- Auth: HTTP bearer

The only way to send email through the API. Email goes out as a campaign from the business's own verified sending domain, only to customers with recorded email consent who are not on the do-not-email list, and only after the business owner approves the exact revision. The same actions, checks and role rules as the dashboard campaign page. action 'request_sender' (domain, from, reply_to) creates the sending domain (a subdomain the business controls) and returns the DNS records to add; it turns ready on its own once they verify. action 'check_sender' (sender_id) re-checks the records now. action 'record_consent' (lead_id and email, or emails, plus evidence_ref saying where the permission came from, optional expires_at) records email permission for existing customers; 'revoke_consent' takes it back. action 'draft' (sender_id, subject, text, lead_ids, optional daily_limit, default the most the sender and the Kai level allow) saves a campaign for review and returns id and fingerprint; nothing is sent. action 'approve' (campaign_id, fingerprint) approves that exact revision. action 'launch' (campaign_id) queues an approved campaign. action 'cancel' (campaign_id, fingerprint) stops it. Sending from a KaiCalls-managed domain also needs a Kai level that includes email, and is capped at what the level allows per day (see /dashboard/level). check_sender needs any member; request_sender, record_consent, revoke_consent and draft need an admin of the business; approve, launch and cancel need the business owner; all are checked against the API key's own user. A refusal from the campaign checks (unverified sender, missing consent, changed audience, no owner approval, Kai level, sending turned off) is 409 email_campaign_refused with the reason in message.

## Request body

- object
  - `action` 'request_sender' | 'check_sender' | 'record_consent' | 'revoke_consent' | 'draft' | 'approve' | 'launch' | 'cancel', required
  - `business_id` string, required
  - `lead_id` string: record_consent, revoke_consent: one customer (with email).
  - `email` string: record_consent, revoke_consent: that customer's address.
  - `emails` string[]: record_consent, revoke_consent: addresses of existing customers (up to 200).
  - `evidence_ref` string: record_consent, revoke_consent: where the permission came from, e.g. web form opt-in.
  - `expires_at` string: record_consent, optional: when the permission ends.
  - `domain` string: request_sender: the sending domain.
  - `from` string: request_sender: the From address.
  - `reply_to` string: request_sender: where replies go.
  - `sender_id` string: draft: the verified sender. check_sender: the sender to re-check.
  - `subject` string: draft: the subject line.
  - `text` string: draft: the plain-text body.
  - `lead_ids` string[]: draft: the customers to email; each needs email consent.
  - `daily_limit` integer: draft: most emails sent per day (default: the most the sender and the Kai level allow).
  - `campaign_id` string: approve, launch, cancel.
  - `fingerprint` string: approve, cancel: the exact revision, from draft or GET.

## Response `200`

request_sender: { success, senderId, status, provisioned, setupComplete, records (DNS), detail }. check_sender: { verified, status, readiness }. record_consent, revoke_consent: { changed, skipped }. draft: { id, fingerprint, packet, readiness, sendable: false }. approve, launch, cancel: the campaign result.

## Other responses

- `400`: invalid_request: bad JSON, unknown action, missing business_id, or a missing campaign_id / fingerprint.
- `403`: Missing emails:write scope, no access to business_id, or the role the action needs (admin for request_sender, record_consent, revoke_consent and draft, owner for approve, launch, cancel).
- `409`: email_campaign_refused: the campaign checks refused the action.

---

[API](https://skmtc.dev/kaicalls/apis/kaicalls-public-api.md) · [All operations](https://skmtc.dev/kaicalls/apis/kaicalls-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kaicalls/apis/kaicalls-public-api/revisions/e607fc6cf36e?raw)
