Skip to main content

Political Operations

Transactional email

One-off system mail from your own apps: confirmations, password resets, invites, reminders, and form receipts. Campaign mail is a separate product. This mail does not add an unsubscribe footer, and a marketing unsubscribe does not block it.

Quickstart

  1. Sign in and open Account, then the Transactional tab.
  2. Turn it on. New organizations start on the sandbox tier: 200 recipients a day and 10 requests a minute. Only an administrator can set the production tier (50,000 a day and 120 a minute) or another cap.
  3. Enter a From address on a domain you control. Publish the DKIM, SPF, and DMARC records, then click Verify. Sending stays off until the domain is verified.
  4. The account owner creates an API key limited to transactional email and copies it once.
  5. Add funds. Each accepted recipient is charged at the rate shown on that page. The default is $1.00 per 1,000 recipients.

API

POST /api/v1/email/transactional and the alias POST /api/v1/emails. Scope email:transactional. Send Authorization: Bearer and an optional Idempotency-Key. A successful accept returns 202 { "id", "status": "queued" }. A response in the 200 range that has an id and no error is success.

curl -sS -X POST https://campaigncommanderapp.com/api/v1/emails \
  -H "Authorization: Bearer $CC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: signup-confirm-user-42" \
  -d '{
    "from": "Notifications <noreply@your-domain.org>",
    "to": ["new.member@example.com"],
    "subject": "Confirm your account",
    "html": "<p>Confirm your account: {{confirm_url}}</p>",
    "text": "Confirm your account: {{confirm_url}}",
    "variables": { "confirm_url": "https://example.org/confirm?token=example" }
  }'

to accepts one address or up to 50 across to, cc, and bcc. from is optional and must be a verified sender for your organization.tracking defaults to false. GET /api/v1/email/transactional lists recent messages. GET /api/v1/email/transactional/:id returns one, including per-recipient status, attempt count, and the next retry time. Status queued means the send is still waiting. The rendered body is not in that response. Templates live at /api/v1/email/transactional/templates and use {{variable}} placeholders.

Insufficient balance returns 402 and nothing is queued. A hard bounce or a spam complaint suppresses that address. A complaint still blocks this mail after the person unsubscribes from campaign mail. The same Idempotency-Key with the same body returns the original id for 24 hours and does not send twice. See the full API & MCP documentation for template endpoints, sending-domain verification, and MCP tools. Webhooks are POST /api/v1/email/transactional/webhooks with an https url. The secret is returned once. Events are delivered, bounced, and failed. Sign the raw body with X-Campaign-Commander-Signature as t=<unix>,v1=<hmac sha256 of t.rawBody> and reject a clock more than 5 minutes off.

Moving an existing integration

Point the same JSON body at Campaign Commander and send your API key as a bearer token. Fields match the usual transactional shape: from, to, subject, html, text, cc, bcc, reply_to, headers, tags, and attachments. There is no SMTP relay. Provider SMTP credentials would skip billing, the send log, and suppression.

const response = await fetch("https://campaigncommanderapp.com/api/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CC_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `password-reset-${userId}`,
  },
  body: JSON.stringify({
    from: "Notifications <noreply@your-domain.org>",
    to: [user.email],
    subject: "Reset your password",
    html: "<p>Reset your password.</p>",
    text: "Reset your password.",
  }),
})
const { id } = await response.json()

Pricing and limits

The price on your transactional email page is the price you are charged, per recipient, when the message is accepted. The platform default is $1.00 per 1,000, with a 1 cent minimum. A new organization starts on the sandbox tier: 200 recipients a day and 10 requests a minute. Only an administrator sets the production tier. If bounce or complaint rates cross the platform thresholds, sending pauses until an administrator turns it back on. Typo and syntax-invalid addresses are left out of that sample.

Create a free account