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 and a project 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: DomainsAdd domain in the dashboard, or POST /v1/domains with a key that has domains:write. The domain starts as pending. A project can have up to 50 sender domains, and a domain belongs to one project 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:[email protected]; …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; postfly also re-checks pending domains once a day for their first 30 days and emails you when one passes. To look yourself:

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

4 · Create an API key

In API tokensCreate token, 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 project; 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": "[email protected]",
    "to": "[email protected]",
    "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 (user apikey) on smtp.postfly.app:587 with STARTTLS — see SMTP.

6 · Track delivery

GET /v1/emails/{id} returns the message and its status: queued sendingsent (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.