Kraiter
API Reference

Send

Send transactional emails to individual recipients using templates and dynamic variables.

The Send endpoint delivers a single transactional email immediately. Use this for password resets, order confirmations, welcome emails, and other one-off messages that are triggered by user actions.

For bulk or automated sending, use Sequences instead.

Send transactional email

POST /api/send

Sends a single email to a recipient using a pre-defined template. The template is rendered with the provided variables and delivered via your verified domain.

Request body

FieldTypeRequiredDescription
tostringYesRecipient email address. Must match an existing contact.
templatestringYesThe ID of the template to use.
variablesobjectNoKey-value pairs to inject into the template's Liquid variables.
fromstringNoOverride the from address. Must be on a verified domain. Defaults to the tenant's default from address.
ignoreUnsubscribebooleanNoIf true, sends even if the contact has unsubscribed. Use only for legally required messages (e.g. receipts, security alerts). Defaults to false.

Response

On success returns 200 OK with the SES message ID, a fixed status of "sent", and the internal send record ID. There is no success flag — a failure is returned as an error response, not a body with status.

{
  "messageId": "0100018f...-a1b2c3d4-...",
  "status": "sent",
  "sendId": "snd_01H9..."
}

Delivery outcomes after hand-off to SES (delivered, bounced, complained) are tracked on the send record and surfaced via the Sends API and webhooks, not in this response.

Errors

Suppression and unsubscribe are re-checked at send time. If the contact has unsubscribed or is suppressed (bounce/complaint) and ignoreUnsubscribe is false, the send is refused.

CodeDescription
VALIDATION_ERRORMissing to or template, invalid email format, template disabled, or the contact is unsubscribed/suppressed and ignoreUnsubscribe is false.
CONTACT_NOT_FOUNDNo contact exists for the to address.
TEMPLATE_NOT_FOUNDThe specified template does not exist.
DOMAIN_NOT_FOUNDThe sending domain is not registered.
DOMAIN_NOT_VERIFIEDThe sending domain is not verified.
FORBIDDENTenant sending is paused, or the recipient is not on the sandbox whitelist.

Examples

curl -X POST https://api.kraiter.com/api/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "alice@example.com",
    "template": "password-reset",
    "variables": {
      "resetUrl": "https://app.example.com/reset?token=abc123",
      "expiresIn": "24 hours"
    }
  }'
const send = await kraiter.send({
  to: "alice@example.com",
  template: "password-reset",
  variables: {
    resetUrl: "https://app.example.com/reset?token=abc123",
    expiresIn: "24 hours",
  },
});

Sending to suppressed contacts

By default, the API rejects sends to contacts who have unsubscribed or been suppressed. For legally required messages (receipts, security alerts, account notifications), set ignoreUnsubscribe to true:

curl -X POST https://api.kraiter.com/api/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "alice@example.com",
    "template": "security-alert",
    "variables": { "action": "Password changed" },
    "ignoreUnsubscribe": true
  }'
const send = await kraiter.send({
  to: "alice@example.com",
  template: "security-alert",
  variables: { action: "Password changed" },
  ignoreUnsubscribe: true,
});

Use ignoreUnsubscribe sparingly. Sending marketing content to suppressed contacts violates anti-spam regulations and can damage your sender reputation.

Template variables

Variables are injected into the template using Liquid syntax. For example, a template with {{ resetUrl }} will be replaced with the value of variables.resetUrl. If a required variable is missing, the template renders with an empty string for that placeholder.

See the Templates reference for details on template creation and variable declaration.