cf-email — Cloudflare Email Sending

SkillCommunication

Send emails via the Cloudflare Email Sending REST API. Trigger this skill when the user wants to send an email using Cloudflare's email service. Use curl directly with credentials from environment variables.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the cf-email — Cloudflare Email Sending skill

What this skill tells your AI

The instructions your AI receives, as published by vaayne/agent-kit in skills/cf-email/SKILL.md and read by ahel’s review.

Sends transactional email via the Cloudflare Email Sending REST API using curl.

Environment Variables

VariableDescription
CLOUDFLARE_ACCOUNT_IDCloudflare account ID
CLOUDFLARE_API_TOKENCloudflare API token with email sending permission

Endpoint

POST https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/email/sending/send

Request Fields

FieldTypeRequiredDescription
tostring or string[]YesRecipient(s), max 50 combined with cc/bcc
fromstring or {address,name}YesSender — object form uses address, not email
subjectstringYesEmail subject line
htmlstringNo*HTML body
textstringNo*Plain text body
ccstring or string[]NoCC recipients
bccstring or string[]NoBCC recipients
reply_tostring or {address,name}NoSnake_case
attachmentsarrayNoFile attachments and inline images
headersobjectNoCustom email headers

*At least one of html or text required. Include both for best deliverability.

Usage

Plain text

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/email/sending/send" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "to": "user@example.com",
    "from": {"address": "you@yourdomain.com", "name": "Your Name"},
    "subject": "Hello",
    "text": "Hello from Cloudflare.",
    "html": "<p>Hello from Cloudflare.</p>"
  }'

Multiple recipients with CC/BCC

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/email/sending/send" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "to": ["user1@example.com", "user2@example.com"],
    "cc": ["manager@company.com"],
    "bcc": ["archive@company.com"],
    "from": {"address": "orders@yourdomain.com", "name": "Orders"},
    "reply_to": "support@yourdomain.com",
    "subject": "Order Confirmation",
    "html": "<h1>Your order is confirmed</h1>",
    "text": "Your order is confirmed"
  }'

With file attachment

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/email/sending/send" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "to": "customer@example.com",
    "from": {"address": "invoices@yourdomain.com", "name": "Invoices"},
    "subject": "Your Invoice",
    "html": "<h1>Invoice attached</h1>",
    "text": "Invoice attached.",
    "attachments": [
      {
        "content": "JVBERi0xLjQK...",
        "filename": "invoice.pdf",
        "type": "application/pdf",
        "disposition": "attachment"
      }
    ]
  }'

With inline image

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/email/sending/send" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "to": "user@example.com",
    "from": {"address": "newsletter@yourdomain.com", "name": "Newsletter"},
    "subject": "Check this out",
    "html": "<h1>Hello!</h1><img src=\"cid:logo\">",
    "attachments": [
      {
        "content": "iVBORw0KGgoAAAANSUhEUg...",
        "filename": "logo.png",
        "type": "image/png",
        "disposition": "inline",
        "content_id": "logo"
      }
    ]
  }'

With custom headers (e.g. unsubscribe)

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/email/sending/send" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "to": "user@example.com",
    "from": {"address": "notifications@yourdomain.com", "name": "Notifications"},
    "subject": "Weekly digest",
    "html": "<h1>Weekly Digest</h1>",
    "text": "Weekly Digest",
    "headers": {
      "List-Unsubscribe": "<https://yourdomain.com/unsubscribe?id=abc123>",
      "List-Unsubscribe-Post": "List-Unsubscribe=One-Click"
    }
  }'

Response

{
  "success": true,
  "errors": [],
  "messages": [],
  "result": {
    "delivered": ["recipient@example.com"],
    "permanent_bounces": [],
    "queued": []
  }
}

success: true with empty delivered/queued arrays is normal — Cloudflare accepted the message.

Error Handling

StatusMeaningRetry?
200SuccessN/A
400Validation errorNo — fix the request
401Invalid tokenNo — check your token
429Rate limitedYes — exponential backoff
500Server errorYes — exponential backoff

Workflow

  1. Confirm recipient, subject, and body with the user.
  2. Echo the JSON payload to confirm it looks right before sending.
  3. Send with curl and check success in the response.
  4. Report delivered, queued, or permanent_bounces from the result.

Signals

GitHub stars
53
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
cf-email
Source
github.com/vaayne/agent-kit