Transactional Sends

Send one-off or batch emails programmatically using your existing templates. Order confirmations, shipping notifications, appointment reminders, and any other event-driven email you need to fire from your backend.

How Sends Differ from Campaigns

Campaigns are designed for marketing blasts to segments. Sends are designed for programmatic, API-driven delivery. They don't appear in the campaigns list, don't require manual review, and support custom personalizations beyond the standard contact fields.

CampaignsSends
TriggerManual or scheduled in the UIAPI call from your backend
RecipientsSegment or all contactsSingle email, batch, or segment
PersonalizationsContact fields onlyAny custom key-value pairs
TrackingCampaign analytics pageSends list + email events
VolumeOccasional, reviewedHigh-volume, automated

Quick Start

You need an API key and a template ID. Then make a POST request:

curl -X POST https://your-domain.com/api/v1/sends \
  -H "X-API-Key: pp_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "your-template-uuid",
    "to": "customer@example.com",
    "subject": "Your order has shipped!",
    "personalizations": {
      "order_id": "ORD-12345",
      "tracking_url": "https://track.example.com/abc"
    }
  }'

Custom Personalizations

The personalizations field accepts any key-value pairs. In your template, use {{key_name}} to insert them. Custom personalizations override contact fields, so if your template has{{first_name}} and you pass { "first_name": "Dr. Jane" }, the API value wins over the contact's stored first name.

Standard contact tokens ({{first_name}}, {{last_name}},{{email}}, {{company}}) are filled in automatically from the contact record for any tokens not overridden by personalizations.

Batch Sends

Send to multiple recipients in one API call (up to 1,000):

POST /api/v1/sends/batch
{
  "templateId": "template-uuid",
  "subject": "Your weekly summary",
  "recipients": [
    { "to": "user1@example.com", "personalizations": { "total": "$1,234" } },
    { "to": "user2@example.com", "personalizations": { "total": "$567" } }
  ]
}

Each recipient gets their own personalized email. The response includes abatchId that groups them together.

Scheduling

Add scheduledAt (ISO 8601 timestamp) to delay delivery:

{
  "templateId": "template-uuid",
  "to": "patient@example.com",
  "subject": "Appointment reminder",
  "scheduledAt": "2026-04-14T08:00:00Z"
}

Contact Auto-Creation

If you send to an email address that doesn't exist in your contacts, Pigeon Perch automatically creates a contact record with subscribed status. This ensures delivery tracking and unsubscribe links work correctly. You can also pass a contact UUID instead of an email address.

Delivery Tracking

Every send creates email events (sent, delivered, opened, clicked, bounced) that flow through the same tracking pipeline as campaign emails. View send status via:

  • GET /api/v1/sends — list sends with status filter
  • GET /api/v1/sends/:id — get a single send with status

Limits and Enforcement

  • Transactional sends count against your plan's monthly email limit
  • Sending reputation checks apply (auto-paused if bounce/complaint rates are high)
  • From email must be on a verified domain
  • Batch sends are capped at 1,000 recipients per request

API Reference

MethodPathDescription
POST/sendsSend to one recipient or a segment
POST/sends/batchSend to multiple recipients
GET/sendsList sends with pagination
GET/sends/:idGet send details
Transactional Sends — Pigeon Perch Docs