Send your first email
Use a verified domain and an API key to send an email from your application.
/v1/emailYou need a domain verified on your Prawnwire organization and an API key with the email:send scope. If you are not an organization admin, ask one to do steps 1 and 2 for you.
Verify a domain
An organization admin opens the console, chooses the organization, and opens Domains. They add the domain and publish the ownership verification record, then configure the MX, SPF, DKIM and DMARC records shown there.
Your From address must use a verified domain on your organization that is hosted on the Prawnwire mail server. Prawnwire signs outgoing mail with DKIM.
Create an API key
An organization admin creates a key with the email:send scope in Developers > API keys. Ask your admin for a key if you do not have console access. Store it as a server-side environment variable.
export PRAWNWIRE_API_KEY="pw_test_replace_with_your_key" Start with a test key (pw_test_). It checks your request, domain, current allowance and suppressions, but queues nothing and uses no allowance. The returned MessageID will not appear in activity.
When you are ready to send, replace it with a live key (pw_live_) and use a recipient address you control. Keys apply to the organization and can be revoked.
Send an email
Send a JSON body to https://api.prawnwire.com/v1/email. Replace hello@yourdomain.com with an address on your verified domain and ada@example.com with your test recipient. Provide TextBody, HtmlBody, or both.
curl 'https://api.prawnwire.com/v1/email' \
-H "Authorization: Bearer $PRAWNWIRE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"From": "hello@yourdomain.com",
"To": "ada@example.com",
"Subject": "Welcome to your account",
"TextBody": "Hi Ada, your account is ready."
}' const response = await fetch(
'https://api.prawnwire.com/v1/email',
{
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.PRAWNWIRE_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"From": "hello@yourdomain.com",
"To": "ada@example.com",
"Subject": "Welcome to your account",
"TextBody": "Hi Ada, your account is ready."
}),
},
)
const result = await response.json()
if (!response.ok) throw new Error(JSON.stringify(result))
console.log(result) The prawnwire SDK is publishing soon. This example uses built-in fetch in Node 18 or newer.
import postmark from 'postmark'
const client = new postmark.ServerClient(
process.env.PRAWNWIRE_API_KEY,
{ requestHost: 'api.prawnwire.com/v1' },
)
const result = await client.sendEmail({
"From": "hello@yourdomain.com",
"To": "ada@example.com",
"Subject": "Welcome to your account",
"TextBody": "Hi Ada, your account is ready."
})
console.log(result) The Node tab uses built-in fetch while the Prawnwire SDK is publishing soon. You can also use curl or the verified Postmark client.
Read the answer
With a live key, a successful request returns this shape. Keep the MessageID to look up the message later.
{
"To": "ada@example.com",
"SubmittedAt": "2026-10-11T11:18:00.377Z",
"MessageID": "d0706314-5a78-4583-a3f7-121dbf982b56",
"ErrorCode": 0,
"Message": "OK"
} ErrorCode: 0 means accepted, not delivered. A test key instead returns Message: "Test job accepted", with no stored message.
With a live key:
- Accepted: the API checked and queued the message.
- Sent: Prawnwire’s mail server accepted the submission for delivery.
- Delivered: a recipient’s mail server reported delivery. This does not prove inbox placement or that a person read it.
If some recipients are suppressed, Message says OK. Not sent to suppressed recipients: .... The others are queued. If all are suppressed, the API returns ErrorCode 406.
Next steps
- Explore the send endpoint: every field and its limits.
- Find your message: look up activity and delivery events.
- Check your allowance: monthly recipients and daily caps.
- Use a Postmark library: configure the host.