posta API documentation
posta is a mailbox API: programmable mailbox hosting. Connect a domain you control, then create real IMAP/SMTP mailboxes with one API call. It is built for developers and AI agents that need to both receive and send mail. Machine-readable: /openapi.json, /llms.txt, /llms-full.txt.
Quickstart (5 minutes)
- Create a free account and confirm your email. Free early access: 1 domain, 1 mailbox, 500 MB, up to 50 outgoing messages a day per mailbox.
- In the dashboard, create an API key (scopes:
domains:read,domains:write,mailboxes:read,mailboxes:write). The key (pk_live_…) is shown once. Keys can only be created in the dashboard, not with another key. - Add a domain, publish the DNS records it returns, verify, then create a mailbox:
# 1. Add a domain (needs a key with domains:write)
curl -s https://posta.preved.co/v1/domains \
-H "Authorization: Bearer $POSTA_KEY" -H "Content-Type: application/json" \
-d '{"name": "example.com"}'
# → 201 {"id": 7, "status": "pending", "dns": {"ownership_txt": ..., "mx": ..., "dkim": null}, ...} (DKIM key is generated at verification)
# 2. Publish the DNS records from the response, then ask posta to check them
curl -s -X POST https://posta.preved.co/v1/domains/7/verify -H "Authorization: Bearer $POSTA_KEY"
# → {"status": "verified", ...} once DNS has propagated. Then GET /v1/domains/7 returns the DKIM TXT record to publish.
# 3. Create a mailbox (needs mailboxes:write; you choose the password)
curl -s https://posta.preved.co/v1/mailboxes \
-H "Authorization: Bearer $POSTA_KEY" -H "Content-Type: application/json" \
-d '{"domain_id": 7, "local_part": "agent", "password": "a-long-random-passphrase"}'
# → 201 {"id": 12, "address": "agent@example.com", "quota_mb": 500, "status": ..., "created_at": ...}
Authentication
Send Authorization: Bearer pk_live_… on every request. Each endpoint requires a scope; a missing scope returns an error. Base URL: https://posta.preved.co/v1. Errors have one shape: {"error": {"code": "…", "message": "…"}}.
Endpoints
GET /v1/domains,POST /v1/domains{"name"} · scopes domains:read / domains:writeGET /v1/domains/{id},DELETE /v1/domains/{id}POST /v1/domains/{id}/verify: checks DNS and returns the domain with statusGET /v1/mailboxes,POST /v1/mailboxes{"domain_id","local_part","password"} · mailboxes:read / mailboxes:writeDELETE /v1/mailboxes/{id}GET /v1/usage: plan, limits and current usage · domains:read
Python
import os, requests
API = "https://posta.preved.co/v1"
H = {"Authorization": f"Bearer {os.environ['POSTA_KEY']}"}
domain = requests.post(f"{API}/domains", headers=H, json={"name": "example.com"}).json()
# publish domain["dns"] records at your DNS provider, then:
requests.post(f"{API}/domains/{domain['id']}/verify", headers=H).raise_for_status()
box = requests.post(f"{API}/mailboxes", headers=H, json={
"domain_id": domain["id"], "local_part": "agent", "password": "a-long-random-passphrase"}).json()
print(box["address"])
Node.js
const API = "https://posta.preved.co/v1";
const H = { Authorization: `Bearer ${process.env.POSTA_KEY}`, "Content-Type": "application/json" };
const domain = await (await fetch(`${API}/domains`, { method: "POST", headers: H, body: JSON.stringify({ name: "example.com" }) })).json();
// publish domain.dns records at your DNS provider, then:
await fetch(`${API}/domains/${domain.id}/verify`, { method: "POST", headers: H });
const box = await (await fetch(`${API}/mailboxes`, { method: "POST", headers: H,
body: JSON.stringify({ domain_id: domain.id, local_part: "agent", password: "a-long-random-passphrase" }) })).json();
console.log(box.address);
Use the mailbox (IMAP and SMTP)
Connect to mail.posta.preved.co. IMAP: port 993 (SSL). SMTP: port 587 (STARTTLS) or 465 (SSL). The username is the full address; the password is the one you set when creating the mailbox.
import imaplib, smtplib
from email.message import EmailMessage
# Receive
imap = imaplib.IMAP4_SSL("mail.posta.preved.co", 993)
imap.login("agent@example.com", PASSWORD)
imap.select("INBOX")
status, data = imap.search(None, "UNSEEN")
# Send
msg = EmailMessage(); msg["From"] = "agent@example.com"; msg["To"] = "you@example.net"
msg["Subject"] = "Hello"; msg.set_content("Sent from a posta mailbox.")
with smtplib.SMTP("mail.posta.preved.co", 587) as s:
s.starttls(); s.login("agent@example.com", PASSWORD); s.send_message(msg)
DNS records for a domain
Publish the records returned by the API. Required for verification: the ownership TXT (name _posta-verify.<domain>, value posta-verify=…) and MX 10 mail.posta.preved.co. Recommended for sending reputation: SPF include:spf.posta.preved.co, the DKIM TXT (returned in dns.dkim after verification), and a DMARC record (_dmarc TXT, e.g. v=DMARC1; p=none).
Errors
invalid_local_part(HTTP 400): Mailbox name not allowed (reserved names like postmaster, admin, abuse, noreply are blocked).weak_password(HTTP 400): Password rejected by the password policy.domain_not_verified(HTTP 403): Verify the domain before creating mailboxes.plan_limit(HTTP 403): Plan limit reached (free: 1 domain, 1 mailbox, 500 MB, up to 50 outgoing messages a day).mailbox_exists(HTTP 409): That address already exists.not_found(HTTP 404): Resource does not exist or is not yours.backend_error(HTTP 503): Mail backend temporarily unavailable; retry shortly.
Limits and rules
Free early access: 1 domain, 1 mailbox, 500 MB, up to 50 outgoing messages a day. Bulk and marketing mail is not allowed (acceptable use). Delivery to Outlook/Hotmail addresses may currently be rejected. Terms: /terms, privacy: /privacy.