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.
| Campaigns | Sends | |
|---|---|---|
| Trigger | Manual or scheduled in the UI | API call from your backend |
| Recipients | Segment or all contacts | Single email, batch, or segment |
| Personalizations | Contact fields only | Any custom key-value pairs |
| Tracking | Campaign analytics page | Sends list + email events |
| Volume | Occasional, reviewed | High-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 filterGET /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
| Method | Path | Description |
|---|---|---|
| POST | /sends | Send to one recipient or a segment |
| POST | /sends/batch | Send to multiple recipients |
| GET | /sends | List sends with pagination |
| GET | /sends/:id | Get send details |