Docs › Quickstart

Quickstart

Send your first transactional email

Use the public REST API from your server. You need an API key, a verified sending domain, and an idempotent POST /v1/emails request.

Before you start

  • Create an API key in your Constant Contact for Agents account.
  • Verify the domain used in the from address.
  • Store the API key in a server-side secret manager or environment variable.

Send a message

Send-creating requests require Idempotency-Key. Reuse the same key only when retrying the same logical request after a timeout or lost response.

curl -X POST "https://api.ctct.dev/v1/emails" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: quickstart-001" \
  -d '{
    "from": "noreply@constantcontact.com",
    "to": ["ada@example.com"],
    "subject": "Your receipt is ready",
    "html": "<p>Your receipt AB-1042 is ready.</p>",
    "message_class": "transactional"
  }'
const response = await fetch("https://api.ctct.dev/v1/emails", {
  method: "POST",
  headers: {
    Authorization: "Bearer <API_KEY>",
    "Content-Type": "application/json",
    "Idempotency-Key": "quickstart-001"
  },
  body: JSON.stringify({
    from: "noreply@constantcontact.com",
    to: ["ada@example.com"],
    subject: "Your receipt is ready",
    html: "<p>Your receipt AB-1042 is ready.</p>",
    message_class: "transactional"
  })
});

console.log(response.status, await response.json());
import requests

response = requests.post(
    "https://api.ctct.dev/v1/emails",
    headers={
        "Authorization": "Bearer <API_KEY>",
        "Content-Type": "application/json",
        "Idempotency-Key": "quickstart-001",
    },
    json={
        "from": "noreply@constantcontact.com",
        "to": ["ada@example.com"],
        "subject": "Your receipt is ready",
        "html": "<p>Your receipt AB-1042 is ready.</p>",
        "message_class": "transactional",
    },
)

print(response.status_code, response.json())

Expected response

The send is asynchronous. A 202 Accepted response means the request was accepted for processing and includes a send_id you can follow later.

{
  "email_id": "msg_...",
  "message_id": "msg_...",
  "send_id": "send_...",
  "status": "accepted",
  "subject": "Your receipt is ready",
  "from": "noreply@constantcontact.com",
  "recipients": {
    "to": ["ada@example.com"]
  },
  "message_class": "transactional",
  "created_at": "2026-05-18T12:00:00Z"
}

Request fields

NameTypeDescription
fromstringRequiredVerified sender address, usually on a domain you have added and verified.
tostring[]RequiredRecipient email addresses. First-copy examples use an array.
subjectstringRequiredEmail subject, 300 characters or fewer.
htmlstringOptionalHTML body. Either html or text is required.
textstringOptionalPlain-text body. Required only when html is omitted.
message_classstringOptionalDefaults to transactional. The current public send path rejects non-transactional classes.

Common errors

401 authentication_required — Missing Authorization: Bearer <API_KEY>.
400 missing_idempotency_key — Send-creating requests require Idempotency-Key.
400 invalid_request — A required field is missing or invalid.
429 rate_limited — Back off using Retry-After and the X-RateLimit-* headers.
Next: verify a sending domain before production sends, then use send status or webhooks to track outcomes.