Node
Install and use the Prawnwire Node and TypeScript SDK.
The prawnwire package on npm is the TypeScript client, built from the prawnwire-node repository. It has no runtime dependencies and uses the platform fetch implementation. Its README and source are the reference for the SDK API described below.
Send with Node
Create a server-side PRAWNWIRE_API_KEY environment variable, then use the Node tab. Never expose the key to a browser.
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."
}' import { Prawnwire } from 'prawnwire'
const client = new Prawnwire(process.env.PRAWNWIRE_API_KEY, {
baseUrl: 'https://api.prawnwire.com/v1',
})
const result = await client.emails.send({
"from": "hello@yourdomain.com",
"to": "ada@example.com",
"subject": "Welcome to your account",
"text": "Hi Ada, your account is ready."
})
console.log(result) 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) SDK API
Install the package with npm install prawnwire.
The SDK uses camelCase, unlike the PascalCase wire format. from, to, and text or html form a message; a send result includes messageId and submittedAt.
import { Prawnwire } from 'prawnwire'
const client = new Prawnwire(process.env.PRAWNWIRE_API_KEY, {
baseUrl: 'https://api.prawnwire.com/v1',
})
const { messageId } = await client.emails.send({
from: 'hello@yourdomain.com',
to: 'ada@example.com',
subject: 'Welcome',
text: 'Hi Ada, your account is ready.',
})
console.log(messageId) Other message fields include cc, bcc, replyTo, subject, html, tag, metadata, headers, attachments, and trackOpens (ignored by the server). Recipient inputs accept one string or an array. Attachments use filename, content (base64 or Uint8Array), contentType, and optional contentId.
Methods
| Method | Result | Scope |
|---|---|---|
emails.send(message) | Send result with messageId | email:send |
emails.sendBatch(messages) | Ordered results; check ok per entry | email:send |
emails.list(filters) | { totalCount, messages } | email:read |
emails.get(messageId) | Message details and events | email:read |
suppressions.list() | Suppression array | email:read |
suppressions.delete(addresses) | Per-address deletion results | email:send |
domains.list() | Domain array | domains:read |
members.list() | Member array | members:read |
me() | Organization and key | Any active key |
List filters use count, offset, status, recipient, fromEmail, tag, and subject. The current SDK does not expose the HTTP API’s fromdate and todate filters; use fetch for those. Batch refusals return { ok: false, errorCode, message } rather than throwing for each failed message.
Options and staging
The constructor is new Prawnwire(apiKey?, options?). If no key is passed, it reads PRAWNWIRE_API_KEY where process.env exists.
| Option | Default | Purpose |
|---|---|---|
baseUrl | https://api.prawnwire.com/v1 | Set to https://api.prawnwire.dev/v1 for staging. |
timeoutMs | 30000 | Request timeout in milliseconds. 0 disables it. |
fetch | Global fetch | Supply a compatible fetch implementation. |
The example above uses this docs environment’s base URL explicitly, so a staging build does not accidentally use the production SDK default.
Errors and retries
PrawnwireError carries status, code, message, retryAfter, and an optional underlying cause. status is 0 when no HTTP response arrived. Client codes include missing_api_key, network_error, timeout, invalid_response, and http_error.
The SDK does not retry automatically. Follow retry advice, and distinguish a known refusal from an ambiguous network timeout.