POST /api/v1/send/email · GET /api/v1/send/logs

Send — Transactional Email

Send transactional emails through waypoints' own Postal SMTP infrastructure. Supports custom sending domains, HTML and plain-text bodies, file attachments, delivery tracking, and full log access via API.

/api/v1/send/email

Send a single transactional email. The from address must use a verified sending domain. See the Custom Domains section below to set one up.

ParameterTypeRequiredDescription
stringyesSender address — must use a verified domain, e.g. hello@yourapp.com
stringyesRecipient email address
stringyesEmail subject line
stringone ofHTML body of the email
stringone ofPlain-text body of the email (recommended as fallback)
stringnoReply-to address if different from from
object[]noArray of { filename: string, content: string (base64) }
string[]noArray of tag strings for log filtering, e.g. ["transactional", "welcome"]

cURL

curl -X POST https://api.waypoints.tech/v1/send/email \
  -H "x-api-key: wp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "hello@yourapp.com",
    "to": "user@example.com",
    "subject": "Welcome to yourapp!",
    "html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    "text": "Welcome! Thanks for signing up.",
    "tags": ["transactional", "welcome"]
  }'

SDK (@waypoints/sdk)

import waypoints from "@waypoints/sdk";

const wp = new waypoints({ apiKey: process.env.WAYPOINTS_API_KEY });

const result = await wp.send.email({
  from: "hello@yourapp.com",
  to: "user@example.com",
  subject: "Welcome to yourapp!",
  html: "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
  text: "Welcome! Thanks for signing up.",
  tags: ["transactional", "welcome"],
});

console.log(result.id);     // "msg_01jx..."
console.log(result.status); // "queued"

SDK — with attachment

import { readFileSync } from "fs";

const pdfBuffer = readFileSync("./invoice.pdf");
const base64 = pdfBuffer.toString("base64");

const result = await wp.send.email({
  from: "billing@yourapp.com",
  to: "client@example.com",
  subject: "Your invoice #1042",
  html: "<p>Please find your invoice attached.</p>",
  attachments: [
    { filename: "invoice-1042.pdf", content: base64 },
  ],
});

Response

{
  "id": "msg_01jx9k2m3n4p5q6r7s8t9u0v",
  "status": "queued",
  "credits_used": 1,
  "request_id": "req_01jx9k2m3n4p5q6r7s8t9u0v"
}
StatusMeaning
Email accepted by Postal and queued for delivery
Email confirmed delivered to recipient mail server
Delivery failed — recipient address does not exist or rejected
Recipient marked the email as spam
GET/api/v1/send/logs

Retrieve paginated email delivery logs for your account. Filter by status, date range, and recipient to monitor delivery health.

Query paramTypeDescription
stringFilter by delivery status: queued, delivered, bounced, complained
stringISO date string — only return logs on or after this date
stringISO date string — only return logs on or before this date
numberNumber of results per page (default: 50, max: 200)
stringPagination cursor from previous response

cURL

curl "https://api.waypoints.tech/v1/send/logs?status=bounced&limit=20" \
  -H "x-api-key: wp_live_your_key_here"

Response

{
  "logs": [
    {
      "id": "msg_01jx...",
      "from": "hello@yourapp.com",
      "to": "user@example.com",
      "subject": "Welcome to yourapp!",
      "status": "delivered",
      "delivered_at": "2026-03-21T14:32:00Z",
      "opened_at": "2026-03-21T14:35:22Z",
      "created_at": "2026-03-21T14:31:58Z"
    }
  ],
  "next_cursor": "cursor_01jx...",
  "has_more": true
}

Custom Domain Setup

To send emails from your own domain (e.g. hello@yourapp.com), you must verify the domain by adding DNS records. This protects deliverability and prevents spoofing.

Register your domain

curl -X POST https://api.waypoints.tech/v1/send/domains \
  -H "x-api-key: wp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "yourapp.com" }'

waypoints returns the required DNS records (SPF, DKIM, DMARC) for you to add at your DNS provider.

Add DNS records

TypeNameValuePurpose
@v=spf1 include:postal.waypoints.tech ~allSPF — authorises waypoints to send on your behalf
postal._domainkeyv=DKIM1; k=rsa; p=<provided>DKIM — cryptographic signature
_dmarcv=DMARC1; p=quarantine; rua=...DMARC — policy for unauthenticated mail

DNS propagation typically takes 5–30 minutes, but can take up to 48 hours in some regions.

Verify in the dashboard

Open the waypoints dashboard → Sending Domains → click Verify. Once SPF, DKIM, and DMARC all show green, you can send from that domain immediately.

Notes

Postal webhook

Delivery status updates (delivered, bounced, complained) are pushed to waypoints via a Postal webhook and stored in your email logs in Convex in real time. No polling required.

Attachment limits

Maximum total attachment size is 10 MB per email. Attachments are base64-encoded in the request body. For larger files, upload to storage first and link to the download URL in the email body.

Sandbox keys

Emails sent using wp_test_ keys are accepted and logged but NOT actually delivered. Use sandbox keys during development to avoid sending real emails and wasting credits.

Unsubscribe compliance

waypoints is a transactional email service. Marketing emails (newsletters, promotions) sent through waypoints violate the terms of service. Use a dedicated marketing platform for bulk campaigns.