Send emails with Node.js
Install the Node SDK from npm and call emails.send.
What you'll build
A Node.js script that sends a receipt email with the postshiba client and logs the queued message.
Before you start
- An API key with Send only access. Full access also works. See Create an API key. Support keys cannot send.
- A verified sending domain. See Add and verify a domain.
frommust be an address on it. - A cluster that is ready to send (
sending_readyistrue). See Clusters. - Node.js 18 or later.
Install
npm install postshiba is an alias for the same package.
Send your first email
Pass your API key to PostShiba, then call emails.send. teamId is only needed for team-scoped calls such as listing clusters, which need a Full access key kept out of your deployed app. It is on the API keys page.
The file uses import and top-level await, so set "type": "module" in package.json, then run node send.js. emails.send resolves to the JSON body of the 201 response. The message then shows under Events in the dashboard.
Pin a cluster
Without a pin, PostShiba uses your first cluster that is ready to send. Pass clusterId to choose one.
Attachments and templates
Attach a file
Add attachments with filename, content_type, and base64 content. Up to 10 files, 18 MB in total. See Attachments for allowed types.
Send a published template
Pass template with the alias or public id and its variables. Leave out html and text.
Keep the key safe
Use a Send only key in your app. It can send email and call GET /api/v1/users/me. Every other request returns 403 forbidden.
| If this key leaks | Send only | Full access |
|---|---|---|
| Send mail from your verified domains | Yes | Yes |
| Read events, recipients, templates, and sent messages | No | Yes |
| See SMTP passwords and webhook secrets | No | Yes |
| Change clusters, domains, credentials, webhooks, and suppressions | No | Yes |
- Keep Full access keys for setup scripts, the CLI, and MCP. Don't deploy one with your app.
- Read the key from an environment variable, such as
new PostShiba(process.env.POSTSHIBA_API_KEY). Don't commit it, log it, or put it in a URL. - Send from your server. Never put a key, even a Send only key, in browser or mobile code, including client bundles from Next.js, Vite, or React Native.
- Create one key per app and environment. If a key leaks, delete it on API keys and create a new one. Deleting stops it straight away.
Troubleshooting
A response outside 2xx throws PostShibaError with error, field, and message from the JSON body.
| Status | error |
What to do |
|---|---|---|
401 |
Invalid token or no user signed in |
The API key is missing, mistyped, or deleted. Copy it again from API keys. |
403 |
forbidden |
Support keys cannot send. Use a Send only or Full access key. A Send only key gets this on any call other than sending. |
403 |
domain_unverified |
from is not on a verified domain. |
403 |
kyc_required |
Your team is pending production approval. Until then, send only to team members, live inbox addresses, and inbox forward-to addresses. |
422 |
invalid |
field names the problem, such as a missing to, an unpublished template, or a rejected attachment. |
429 |
throttled |
The cluster hit its hourly throttle or 24-hour cap. The client does not retry, and retrying right away hits the same cap. See What happens at your cap. |
429 |
rate_limited |
More than 300 send requests in one minute on one API key. Slow down. |
Every other status is on Errors.
Next steps
- Send emails with NestJS, Convex, Inngest, or Trigger.dev if you use one of them.
- Unique args to get your own ids back on delivery webhooks.
- Verify webhook requests with
postshiba.webhooks.verify. - SDKs for every language client.