Introduction

The Send & Retain REST API — send email, sync contacts, and emit events over HTTPS.

The Send & Retain API is a small REST API for sending transactional and marketing email. You send to one recipient per request — there are no bulk campaigns. Contacts and events flow through the same API to drive automations.

All requests go to:

https://sendandretain.com/api/v1

Every request is authenticated with a per-project API key and every response is JSON.

Quick start

Send an email with a published template. Replace aem_… with a key from Settings → API keys and welcome with one of your template slugs.

Send an email
curl https://sendandretain.com/api/v1/emails \
  -H "Authorization: Bearer aem_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: welcome-jane-1" \
  -d '{
    "to": "[email protected]",
    "template": "welcome",
    "props": { "firstName": "Jane" }
  }'

A send is accepted with 202 and the message id:

{ "id": "msg_3aF9c1", "status": "queued" }

status is queued, or scheduled when you passed scheduled_at. Delivery happens in the background; follow it with GET /api/v1/emails/{id} or, better, a webhook.

SDKs

npm install @sendandretain/sdk
pip install sendandretain
import { SendAndRetain } from "@sendandretain/sdk";

const sendandretain = new SendAndRetain(); // reads SENDANDRETAIN_API_KEY
const { data, error } = await sendandretain.emails.send({
  to: "[email protected]",
  template: "welcome",
  props: { firstName: "Jane" },
});
from sendandretain import SendAndRetain

client = SendAndRetain()  # reads SENDANDRETAIN_API_KEY
email = client.emails.send(to="[email protected]", template="welcome", props={"firstName": "Jane"})

Both retry rate limits and server errors with backoff, attach an Idempotency-Key to every create so those retries are safe, page lists for you, and verify webhook signatures. The OpenAPI spec is the source of truth for both, and for anything else you generate from it.

Conventions

  • Request ids. Every response carries X-Request-Id; errors repeat it as request_id. Quote it when you contact support.
  • Errors are { error: { code, message, request_id } } — branch on code. See Errors.
  • Lists are { object: "list", data, has_more, next_cursor }. See Pagination.
  • Retries are safe with an Idempotency-Key. See Idempotency.

Endpoints

MethodEndpoint
POST/api/v1/emailsSend an email
GET/api/v1/emailsList sent emails
GET/api/v1/emails/{id}Get message status
PATCH/api/v1/emails/{id}Reschedule an email
DELETE/api/v1/emails/{id}Cancel an email
POST/api/v1/contactsUpsert a contact
GET/api/v1/contactsList contacts
GET/api/v1/contacts/{id}Get a contact
DELETE/api/v1/contacts/{id}Delete a contact
POST/api/v1/eventsEmit a contact event
GET/api/v1/suppressionsList suppressions
POST/api/v1/suppressionsAdd a suppression
DELETE/api/v1/suppressionsRemove a suppression

Each endpoint page has an interactive playground — fill in your key, hit Send, and see the real response.

Concepts

On this page