PlunkPlunk
API Reference

Send transactional email

Send a transactional email via the public API. Automatically creates or updates the recipient contact.

Required content: either a template ID, or both subject and body. Template fields can be overridden by explicit request fields.

Sender: from is required unless using a template that already has a from configured. The sender's domain must be verified.

Multiple recipients: when to is an array, each recipient is processed sequentially with its own contact upsert and rendered email — there is no batch-send semantics. Sending is always immediate; for scheduled sends, use a Campaign.

Attachments: up to 10 attachments per email and 10 MB total by default. The total message size cannot exceed 40 MB.

POST
/v1/send

Authorization

ApiKeyAuth

AuthorizationBearer <token>

API Key authentication. Secret keys (sk_*) are required for all endpoints except /v1/track. Public keys (pk_*) only work with the /v1/track endpoint for client-side event tracking. The project is automatically derived from the key.

In: header

Request Body

application/json

to*string||

Recipient email(s). Can be a string, an object with {name, email}, or an array of either.

subject?string

Email subject. Required if no template is provided. Cannot contain newline characters.

Length1 <= length <= 998
body?string

Email body (HTML). Required if no template is provided.

Length1 <= length
template?string

Template ID to use for this email. When provided, uses the template's subject, body, from, and reply-to settings. You can override these by explicitly providing subject, body, from, or reply fields in the request. Template variables are populated from the data field.

from?string|

Sender email address (requires verified domain). Required unless using a template that has a 'from' address configured. Can be a string (e.g., 'hello@example.com') or an object with {name, email} (e.g., {name: 'My App', email: 'hello@example.com'}).

name?string

Deprecated. Sender display name. Prefer from: { name, email }. Used only as a fallback when from is a string and no name is set there.

subscribed?boolean

Subscription state to apply to the recipient. For new contacts, defaults to false on /v1/send. For existing contacts, omitting this preserves their current state — pass true or false to explicitly change it. A change emits contact.subscribed or contact.unsubscribed.

data?

Variables for template rendering and contact data updates. Each value can be:

  • A primitive (string, number, boolean) — saved on the contact and available as a template variable.
  • null — deletes the field from the contact.
  • An empty string — skipped (does not overwrite existing data).
  • An object { value, persistent: false } — used for this send only, not stored on the contact (good for one-shot password reset codes, magic links).

Reserved keys (id, plunk_id, plunk_email, email, unsubscribeUrl, subscribeUrl, manageUrl) are silently filtered out.

headers?

Custom email headers. Header names cannot contain \r\n. Header values are limited to 998 characters and cannot contain \r\n (header injection is rejected).

reply?string

Reply-to address.

Formatemail
attachments?

Email attachments. Default cap: 10 attachments and 10 MB total. The full message size cannot exceed 40 MB.

Itemsitems <= 10

Response Body

application/json

application/json

application/json

curl -X POST "https://next-api.useplunk.com/v1/send" \  -H "Content-Type: application/json" \  -d '{    "to": "user@example.com",    "subject": "Password Reset Request",    "body": "<h1>Reset Your Password</h1><p>Click the link to reset: {{resetLink}}</p>",    "data": {      "resetLink": "https://example.com/reset/abc123"    }  }'
{
  "success": true,
  "data": {
    "emails": [
      {
        "contact": {
          "id": "cnt_abc123",
          "email": "user@example.com"
        },
        "email": "ac32f08e-c6b9-45d3-9824-a73dff1e3bbf"
      }
    ],
    "timestamp": "2025-01-15T10:30:00.000Z"
  }
}
{
  "code": 0,
  "error": "string",
  "message": "string",
  "time": 0
}
{
  "code": 0,
  "error": "string",
  "message": "string",
  "time": 0
}