Home/Email API/TypeScript

Send email with TypeScript

The same one call as Node, fully typed: the compiler catches a missing from before your users do. Request and response types included in the SDK.

Verified By Kam Low, Co-founder · Updated

Types catch the bug before the bounce

Untyped email code fails at runtime, in production, on the send that mattered. A typed client moves those failures to the compiler: a missing from, a misnamed field, an html body passed as a number, all caught before deploy.

One POST, and the send is handled

TypeScriptPOST /v1/my/messages
import { Nitrosend } from "@nitrosend/sdk"
const ns = new Nitrosend(process.env.NITROSEND_API_KEY!)

const { id } = await ns.messages.send({
  from: "[email protected]",
  to: "[email protected]",
  subject: "Welcome",
  html: "<p>You're in.</p>",
})

The response is typed too: destructure the message ID and hand it to your logs or your tests. First sends require a ready sender: prepare and explicitly select the brand’s protected Nitrosend subdomain, or verify a customer-owned domain. The API never falls back to an unverified shared sender.

The key in that env var is a server-side credential. Our API keys exist for server-side integration of applications, so keep them out of browser bundles and client code. Key scopes bite in practice too. George, our CEO, hit this from the provider side: our own SendGrid connection test used to probe an endpoint that requires the Sender Authentication scope, so a valid least-privilege Mail-Send key 403'd and was reported invalid. He swapped the probe to GET /v3/scopes, which any valid key can read while an invalid key still 401s, and backed it with a regression test that runs 5 for 5 green.

Types are half the tooling story. The other half: there's a design.md file structured specifically for AI agents. Drop it into Claude, Cursor, or ChatGPT and it designs better emails based on what the best brands are doing. George uses it himself and calls the quality difference obvious.

And if you care about what a platform is made of: our MCP server, our CLI, and our AI SDK are all TypeScript. The agent surface of the product is written in the language you're reading this page for.

That AI SDK is @nitrosend/ai-sdk on npm, a TypeScript package built for Vercel AI SDK agents specifically. And the typed thinking runs through the API itself: upload an oversized CSV and you get a 422 with a validation_errors array you can act on, not an opaque 413 from some edge proxy. Errors are part of the type contract too.

Full parameters, responses, and error codes live in the REST API docs and the API reference.

Python Node.js PHP Go Rust +5
send.py requests · stdlib-adjacent
import requests

requests.post(
  "https://api.nitrosend.com/v1/messages",
  headers={"Authorization": f"Bearer {KEY}"},
  json={"to": to, "subject": subj,
        "html": body})
202 ACCEPTED
{ "id": "msg_9f2c",
  "status": "accepted" }

And the part no library gives you

The same account exposes an MCP server, so the agent writing your code can also run your email. Point Claude, Cursor, or Codex at api.nitrosend.com/mcp and it composes, previews, and stages sends, with a human approving every one. The API is for your code. The MCP is for your agent. One platform either way.

Every send comes back with a message ID, and delivery events follow on your webhook: delivered, opened, bounced. No dashboard required to know what happened. If you are staying on SMTP, how to set up SMTP is the setup to follow, and SPF, DKIM and DMARC authentication is what stops those sends landing in spam.

Either path lands on hardened infrastructure. On our relay, TCP 2525 is firewall-restricted to our API host, TLS and exact SMTP authentication are mandatory, and every one-recipient route snapshot is HMAC-signed. Arbitrary destinations, unsigned or replayed requests, and multiple forwarding hops are rejected outright.

The typing is nice. The zero dependencies are nice. Neither is the real change. The real change is that Claude, Cursor, or Codex can point at our MCP server, compose the send, and ask you to approve it before anything leaves, with no TypeScript in the loop at all. That's where email sending is actually heading, and it's why Nitrosend is a listed app in the ChatGPT app marketplace rather than just another well-typed SDK.

Go deeper

FAQ

How do I send email with TypeScript?

Use @nitrosend/sdk: new Nitrosend(key) then await ns.messages.send({ from, to, subject, html }). Fully typed request and response, message ID back.

What is the benefit over plain JavaScript?

The compiler catches malformed sends before runtime: missing fields, wrong types, typo'd properties. Email failures move from production logs to your editor.

First send in thirty seconds.

Simple pricing. Unlimited contacts.

Every plan includes full stack emailing: Flows, Newsletter Campaigns and Transactional Email, plus our NitroWheel LLM and all agent integrations (Claude, ChatGPT, Codex, Cursor and others). Pay for what you send, not who you store.

Daily allowances depend on your plan and sender standing. Strong list, domain and delivery evidence can raise standing, including on day one. Trusted receives the full plan allowance; available email credits, safety checks and delivery pacing still apply.

Free
$0
forever
  • Emails 8,000then 500/mo
  • Email types Transactional & Marketing
  • AI actions 20/mo
  • Contacts Free & Unlimited
  • Brands 3
  • Seats 1
  • Recipients / rolling 24h 100–5,000
  • Email validation Prepaid only
Start free
Ultra
$100
per month
  • Emails 125,000/month
  • AI actions 5,000/mo
  • Brands 10
  • Seats 10 · Domains 10
  • Frontier AI Included
  • Dedicated IP Available
  • Recipients / rolling 24h 1,000–625,000
  • Email validation Prepaid only
Get started
Enterprise
$300
per month
  • AI actions Unlimited
  • Unlimited brands & domains Included
  • SSO / SAML Included
  • 99.9% SLA Included
  • Recipients / rolling 24h Contracted
  • Email validation Prepaid only
Get started

Free forever. No credit card required. See full comparison →