Documentation

Documentation

Everything you need to send your first email — and your billionth.

Introduction

PostedApi is a transactional email service. You call our REST API — or relay through SMTP — and we deliver your receipts, password resets and notifications to the inbox, usually in under a second. This guide walks you from a brand-new account to a working integration in four short steps.

All API traffic goes to a single base URL, and every request is authenticated with your server token:

request.sh
# Base URL + auth header for every call
https://api.postedapi.org
X-PostedApi-Server-Token: your-server-token

For the full list of endpoints, request fields and response shapes, head over to the API reference.

Create a server

A server is an environment. Most teams create one for production and one for staging, so test traffic never shares credentials with the real thing. Each server gets its own token, its own sending domain and its own set of Message Streams.

  • One token per server — revoke it anytime without touching the others
  • Sandbox mode on every new server, so you can test before you send for real
  • A default outbound stream, ready for transactional traffic

The token is shown once, right after creation. Copy it somewhere safe — we store only a fingerprint, so it can't be recovered later.

Verify a domain

To send from [email protected], you first need to prove you control yourapp.com. Add two DNS records at your registrar or DNS provider:

dns-records.txt
# DKIM — signs every message you send
postedapi._domainkey.yourapp.com  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7..."

# SPF — authorizes PostedApi to send on your behalf
yourapp.com                          TXT  "v=spf1 include:postedapi.org ~all"

Once the records propagate, verification completes automatically — the dashboard flips to "Verified" and you're cleared for takeoff. No manual steps, no support tickets.

Until verification completes, you can keep testing with the shared sandbox domain included in every account. DNS changes usually propagate within minutes, but some providers can take up to 24 hours.

Send your first email

One POST to /email is all it takes. Pick your weapon:

# Send a single email
curl "https://api.postedapi.org/email" \
  -X POST \
  -H "Accept: application/json" \
  -H "X-PostedApi-Server-Token: your-server-token" \
  -d '{
    "From": "[email protected]",
    "To": "[email protected]",
    "Subject": "Welcome aboard",
    "TextBody": "Your account is ready — dive in!"
  }'
// npm install postedapi
const client = new PostedApi.ServerClient("your-server-token");

await client.sendEmail({
  From: "[email protected]",
  To: "[email protected]",
  Subject: "Welcome aboard",
  TextBody: "Your account is ready — dive in!"
});
// composer require postedapi/postedapi-php
$client = new PostedApiClient("your-server-token");

$client->sendEmail(
  "[email protected]",
  "[email protected]",
  "Welcome aboard",
  "Your account is ready — dive in!"
);

The response comes back with a MessageID you can trace in the dashboard or the Messages API. For every available field — CC, attachments, tracking, streams — see the full payload reference.

Message Streams

Every server ships with an outbound stream — the home for transactional traffic: receipts, resets, alerts. When you're ready to send newsletters or announcements, create a separate broadcast stream so bulk traffic never touches your critical mail.

Each stream keeps its own suppression list, stats and webhooks. If a promo campaign goes sideways, your password resets keep sailing — that's the whole point.

Inbound email

PostedApi doesn't just send — it receives. Point your domain's MX record at our inbound hosts, set a webhook URL on the stream, and every email that lands at your address shows up in your app as parsed JSON: headers, text and HTML bodies, attachments included.

Build support inboxes, reply-by-email features or intake forms without touching an IMAP server ever again.

Templates

Store your layouts in the dashboard and send with a TemplateId instead of inline HTML. Variables live between double braces, and we fill them in at send time:

template-send.json
{
  "From": "[email protected]",
  "To": "[email protected]",
  "TemplateId": 987654,
  "TemplateModel": {
    "name": "Ada",
    "plan": "Pro"
  }
}

In the template itself, write {{name}} and {{plan}} wherever the values should appear. Preview with sample data before anything goes live.

Webhooks

Don't poll for answers — we'll tell you. Subscribe to delivery events and PostedApi POSTs to your URL the moment something happens:

  • Delivery — the recipient's server accepted the message
  • Bounce — it was rejected; includes the provider's reason
  • Open — the recipient opened the message
  • Click — the recipient clicked a tracked link

Every payload is signed with a shared secret you configure on the stream.

Always verify the signature before acting on a webhook. If the signature doesn't match, the request didn't come from us — return a 401 and move on. Your future self will thank you.

Official libraries

Hand-maintained clients for the languages teams actually reach for. All open source, all covering the full API.

curl

Copy-paste HTTPS examples for every endpoint.

Library docs

Node.js

Promise-based client for Node 18 and up.

Library docs

PHP

Composer package with Laravel-friendly config.

Library docs

Python

Sync and async clients, fully type-hinted.

Library docs

Ruby

Idiomatic gem for Rails and Sinatra apps.

Library docs

C#

.NET Standard client with async/await built in.

Library docs

Go

Small, dependency-free module for the stdlib crowd.

Library docs

Java

Maven artifact with builders for every payload.

Library docs

Ready to send something?

Create your account, grab your server token, and have your first email out the door before your coffee cools.