Getting started · Quick start

Send your first transactional email

From a sender domain to your first transactional email: add and verify the domain, create an API key, send with curl, Node or SMTP.

postfly is invite-only, so you need an account first. Everything below can be done in the dashboard; the API calls are shown for when you want to automate it.

1 · Add a sender domain

Mail goes out from your own domain, so start by adding it: Domains → Add domain in the dashboard, or POST /v1/domains with a key that has domains:write. The domain starts as pending. A key reaches up to 50 sender domains, and a domain belongs to one group only.

2 · Publish the DNS records

The domain page lists the records to publish at your DNS provider, with the exact values for your domain (the DKIM key is generated for it). They look like this:

TypeNameValuePurpose
TXTyourdomain.comv=spf1 include:_spf.postfly.app ~allSPF
TXTpostfly._domainkey.yourdomain.comv=DKIM1;h=sha256;k=rsa;p=MIIBIjANBg…DKIM
TXT_dmarc.yourdomain.comv=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; …DMARC
MXyourdomain.com10 mail.postfly.appOptional

If the domain already has an SPF record, don't add a second one: postfly shows your current record with its include: merged in, to publish in place of the old one. The MX record is optional and not checked; leave it out on a domain whose mail you receive elsewhere. Sender domains & DNS explains each record.

3 · Verify

Click Re-check now on the domain page, or call POST /v1/domains/{domain}/verify. When SPF, DKIM and DMARC all pass, the domain becomes verified and can send. DNS changes can take a while to show up; for its first 30 days postfly also re-checks a pending domain itself — every 10 minutes on the day you add it or once any of its records has passed, otherwise once a day — and emails you when it passes. To look yourself:

shell
dig +short TXT postfly._domainkey.yourdomain.com
dig +short TXT _dmarc.yourdomain.com

4 · Create an API key

On a domain's Keys & SMTP → Create key, pick Sending only (the emails:send scope) for an app that only sends, and optionally restrict the key to the domain you just verified. The key (pf_live_… or pf_test_…) is shown once; keep it in your secret store and pass it as POSTFLY_API_KEY.

5 · Send an email

One request per recipient. from must be an address on a verified domain of the key may send from; html, text or both make the body.

POST /v1/emails
curl -X POST https://api.postfly.app/v1/emails \
  -H "Authorization: Bearer $POSTFLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "noreply@yourdomain.com",
    "to": "user@example.com",
    "subject": "Welcome aboard",
    "html": "<p>Thanks for signing up.</p>",
    "tag": "welcome"
  }'

The API answers right away; delivery happens in the background:

202 Acceptedapplication/json
{
  "id": "m_3kTq9ZbW2xYv",
  "status": "queued",
  "createdAt": "2026-09-11T10:00:00.000Z"
}

SMTP takes the same key as the password, with the key's username for the domain (smtp-…@yourdomain.com, beside the key on the Keys & SMTP tab; apikey is still accepted), on smtp.postfly.app:587 with STARTTLS — see SMTP.

6 · Track delivery

GET /v1/emails/{id} returns the message and its status: queued → sending → sent (accepted by our mail server) → delivered (accepted by the recipient's server), or bounced, complained, failed. The dashboard's Activity shows the same timeline, and a webhook pushes each change to your endpoint.

Next: Concepts for how domains, keys and suppressions fit together, the API reference for every endpoint, and Errors & rate limits before you go live.