Skip to content

Documentation

Send your first email.

Verify a domain, create an API key, and send — through the typed Node SDK or straight over HTTP from any language.

Introduction

Sendridge is a transactional email platform for developers. You verify a sending domain, grab an API key, and send email through a simple HTTPS API — Sendridge handles queuing, delivery, retries, and tracking (opens, clicks, bounces, complaints).

There are two ways to integrate: the official Node.js SDK (recommended) or the REST API directly from any language.

Quickstart

  1. 1Create an account and confirm your email address using the link we send you. Your dashboard opens once you do — if the email doesn't arrive, check your spam folder or use Resend verification email on the verification page.
  2. 2Verify your sending domain (Dashboard → Domains). Sendridge gives you DNS records to add; verification usually completes in minutes.
  3. 3Create an API key (Dashboard → API Keys). Keys look like sr_… and are shown once — store yours securely.
  4. 4Install the SDK and send a test email to your registered address:
Shell
npm install sendridge
send.ts
import { Sendridge } from "sendridge";

const sendridge = new Sendridge(process.env.SENDRIDGE_API_KEY);

const { id } = await sendridge.emails.send({
  from: "Acme <you@yourdomain.com>",
  to: "your-registered-email@example.com",
  subject: "Welcome aboard!",
  html: "<h1>Hello 👋</h1><p>Thanks for signing up.</p>",
});

console.log(`Queued email ${id}`);

Sending is asynchronous: the API responds immediately with status: "queued", then Sendridge delivers in the background. Use emails.get(id) to follow the delivery status.

Sandbox and going live

Every new account starts in sandbox mode. You can send test emails from a verified domain to your own registered email address while setting up. Sends to other recipients become available after your account and sending domain are approved.

Before you can request live sending, confirm your account email, verify a domain's ownership and DKIM records, complete your organisation name and postal address in Settings, and send a test email from that verified domain to your registered address. Custom MAIL FROM is recommended but does not block your request.

The Sending access page shows your checklist and the Request live sending form. Tell us what you'll send, your business type, and your HTTPS website, then accept the sending rules. Reviews usually take a few minutes; you can keep testing with your own address while you wait.

If your request is rejected, we'll show the reason in your dashboard and email it to you. Fix the issue and resubmit the form. When your account is approved, the verified domains included in that approval can send to other recipients. A domain you verify later needs its own quick approval from the Domains page; your already approved domains keep working while it is reviewed.

Authentication

Every request is authenticated with your API key as a Bearer token. The SDK does this for you; for direct REST calls, send the header yourself:

Shell
Authorization: Bearer sr_xxxxxxxxxxxxxxxx

Best practice: keep the key in an environment variable. The SDK automatically reads SENDRIDGE_API_KEY when you don't pass a key to the constructor.

Keys can be scoped with permissions (read, write, send), restricted to IP allowlists, given expiry dates and per-minute rate caps, and rotated at any time — all from the dashboard. A rotated or revoked key stops working immediately.

SDK — Installation

Shell
npm install sendridge

Requires Node.js 18+, or any runtime with fetch — including the Next.js Edge runtime and Nuxt's edge presets. The package ships TypeScript types, works with both import (ESM) and require (CommonJS), and has zero runtime dependencies. Framework guides: Next.js and Nuxt.

TypeScript
// ESM / TypeScript
import { Sendridge } from "sendridge";

// CommonJS
const { Sendridge } = require("sendridge");

const sendridge = new Sendridge(); // reads SENDRIDGE_API_KEY

SDK — Send an email

TypeScript
const result = await sendridge.emails.send({
  from: "Acme Billing <billing@yourdomain.com>", // name shown in the inbox; domain must be verified
  to: ["a@example.com", "b@example.com"], // string or array, max 50
  subject: "Your invoice",
  html: "<p>Invoice attached below.</p>",
  text: "Invoice attached below.",        // plain-text alternative
  replyTo: "support@yourdomain.com",
  tags: { type: "invoice" },
  metadata: { invoiceId: "INV-2026-0042" },
});

// result:
// {
//   id: "665f1c2e9b1d2a0012345678",
//   status: "queued",
//   to: ["a@example.com", "b@example.com"],
//   from: "Acme Billing <billing@yourdomain.com>",
//   subject: "Your invoice",
//   createdAt: "2026-07-15T10:30:00.000Z"
// }
FieldTypeRequiredDescription
fromstringYesSender, as "Your Name <you@yourdomain.com>" or a bare address. Inboxes show the name as the sender; without one they show the part before the @ (e.g. "info"). The domain must be verified in your dashboard.
tostring | string[]YesOne recipient, or up to 50.
subjectstringYesSubject line (max 998 chars).
htmlstringOne of html/textHTML body.
textstringOne of html/textPlain-text body.
replyTostringNoReply-To address. Accepts the same "Name <address>" form.
tagsRecord<string, string>NoString tags for your own filtering.
metadataRecord<string, unknown>NoArbitrary JSON stored with the email.

SDK — Retrieve an email

TypeScript
const email = await sendridge.emails.get("665f1c2e9b1d2a0012345678");

// email.status is one of:
// "queued" | "sending" | "sent" | "delivered" | "bounced" | "failed" | "complained"

console.log(email.status, email.openCount, email.clickCount);

The returned object includes the full body (html/text), delivery status, open and click counts, your tags and metadata, and an errorMessage when delivery failed.

SDK — List emails

TypeScript
const { data, pagination } = await sendridge.emails.list({ page: 1, limit: 20 });

for (const email of data) {
  console.log(email.id, email.subject, email.status);
}
// pagination: { page: 1, limit: 20, total: 132 }

SDK — Error handling

Every failure throws a typed subclass of SendridgeError, so you can branch on the exact failure mode:

TypeScript
import {
  SendridgeError,
  ValidationError,     // 400 — bad payload; err.details has field errors
  AuthenticationError, // 401 — missing / invalid / revoked / expired key
  PermissionError,     // 403 — e.g. sandbox or domain approval restriction
  NotFoundError,       // 404 — unknown email id
  RateLimitError,      // 429 — rate limit or quota exceeded
  ServerError,         // 5xx — Sendridge-side problem
  TimeoutError,        // request exceeded the timeout
  NetworkError,        // DNS / connection failure
} from "sendridge";

try {
  await sendridge.emails.send({ /* ... */ });
} catch (err) {
  if (err instanceof RateLimitError) {
    // back off, then try again
  } else if (err instanceof ValidationError) {
    console.error(err.message, err.details);
  } else if (err instanceof SendridgeError) {
    console.error(err.statusCode, err.message);
  } else {
    throw err;
  }
}

Idempotent reads (get, list) automatically retry up to twice on network failures and 5xx/429 responses, with exponential backoff. Sends are never retried.

A send blocked by sandbox mode (sandbox_restricted) or a domain awaiting approval (domain_not_approved) throws PermissionError. Its messageexplains the restriction and where to request approval.

SDK — Configuration

TypeScript
const sendridge = new Sendridge("sr_...", {
  baseUrl: "https://api.sendridge.com", // override for local dev or staging
  timeoutMs: 30_000,                    // per-request timeout (default 30s)
  maxRetries: 2,                        // GET-only automatic retries (default 2)
});
FieldTypeRequiredDescription
SENDRIDGE_API_KEYenvNoUsed when no key is passed to the constructor.
SENDRIDGE_BASE_URLenvNoUsed when no baseUrl option is passed — point the SDK at a local or staging API.

Every request is sent with cache: "no-store", so framework fetch caches never serve a stale email status. The SDK refuses to start in a browser, where your API key would be visible to every visitor.

Next.js

Works in the App Router and the Pages Router, on the Node.js and Edge runtimes. Use it in server code — route handlers, server actions, getServerSideProps — never in a "use client" component. Add your key to .env.local:

Shell
SENDRIDGE_API_KEY=sr_xxxxxxxxxxxxxxxx

A route handler:

TypeScript
// app/api/send/route.ts
import { Sendridge } from "sendridge";

const sendridge = new Sendridge(); // reads SENDRIDGE_API_KEY

export async function POST(request: Request) {
  const { email } = await request.json();

  const { id } = await sendridge.emails.send({
    from: "Acme <hello@yourdomain.com>",
    to: email,
    subject: "Welcome to Acme",
    html: "<p>Thanks for signing up.</p>",
  });

  return Response.json({ id });
}

Or a server action:

TypeScript
// app/actions.ts
"use server";

import { Sendridge } from "sendridge";

const sendridge = new Sendridge();

export async function sendWelcome(formData: FormData) {
  const email = String(formData.get("email"));

  await sendridge.emails.send({
    from: "Acme <hello@yourdomain.com>",
    to: email,
    subject: "Welcome to Acme",
    html: "<p>Thanks for signing up.</p>",
  });
}

To run a route on the Edge runtime, add export const runtime = "edge"; to it. Nothing else changes. Creating the client at the top of a file is safe: a missing key is only reported when you send, so next build never fails because a build machine lacks SENDRIDGE_API_KEY.

Nuxt

Works with Nuxt 3 and Nuxt 4 in server routes, on Node and edge deployment presets. Keep the key in server-only runtime config:

TypeScript
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    // Server-only. Set it with the NUXT_SENDRIDGE_API_KEY environment variable.
    sendridgeApiKey: "",
  },
});
Shell
NUXT_SENDRIDGE_API_KEY=sr_xxxxxxxxxxxxxxxx

Then send from a server route:

TypeScript
// server/api/send.post.ts
import { Sendridge } from "sendridge";

export default defineEventHandler(async (event) => {
  const { email } = await readBody<{ email: string }>(event);
  const sendridge = new Sendridge(useRuntimeConfig(event).sendridgeApiKey);

  const { id } = await sendridge.emails.send({
    from: "Acme <hello@yourdomain.com>",
    to: email,
    subject: "Welcome to Acme",
    html: "<p>Thanks for signing up.</p>",
  });

  return { id };
});

REST API — Overview

Prefer another language? The REST API is the same surface the SDK wraps. All endpoints accept and return JSON.

Text
Base URL:  https://api.sendridge.com
Auth:      Authorization: Bearer sr_xxxxxxxxxxxxxxxx

Successful responses wrap the payload in a data field; errors return { error, message, code?, details? }.

POST /v1/emails/send

Queues an email for delivery. Responds 202 Accepted.

POST /v1/emails/send
curl -X POST https://api.sendridge.com/v1/emails/send \
  -H "Authorization: Bearer $SENDRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "you@yourdomain.com",
    "to": "customer@example.com",
    "subject": "Welcome!",
    "html": "<h1>Hello</h1>"
  }'
202 Accepted
{
  "data": {
    "id": "665f1c2e9b1d2a0012345678",
    "status": "queued",
    "to": ["customer@example.com"],
    "from": "you@yourdomain.com",
    "subject": "Welcome!",
    "createdAt": "2026-07-15T10:30:00.000Z"
  },
  "message": "Email queued for delivery"
}

GET /v1/emails/:id

Returns a single email you own, including delivery status and engagement counts.

GET /v1/emails/:id
curl https://api.sendridge.com/v1/emails/665f1c2e9b1d2a0012345678 \
  -H "Authorization: Bearer $SENDRIDGE_API_KEY"
200 OK
{
  "data": {
    "_id": "665f1c2e9b1d2a0012345678",
    "to": ["customer@example.com"],
    "from": "you@yourdomain.com",
    "subject": "Welcome!",
    "status": "delivered",
    "openCount": 2,
    "clickCount": 1,
    "createdAt": "2026-07-15T10:30:00.000Z",
    "updatedAt": "2026-07-15T10:30:04.000Z"
  }
}

GET /v1/emails

Paginated list of your emails, newest first. Query params: page (default 1) and limit (default 20).

GET /v1/emails
curl "https://api.sendridge.com/v1/emails?page=1&limit=20" \
  -H "Authorization: Bearer $SENDRIDGE_API_KEY"

REST API — Errors

StatusMeaningTypical causes
400Validation errorMissing/invalid fields; details lists per-field errors
401UnauthorizedMissing, invalid, revoked, or expired API key
403ForbiddenUnverified sending domain, key permissions, IP allowlist, plan restrictions
403 sandbox_restrictedAccount is not liveA send to another recipient is blocked; test sends to your registered address still work. Request live sending in the dashboard.
403 domain_not_approvedDomain is not approvedA live account sent to another recipient from an unapproved domain. Request approval on the Domains page.
404Not foundUnknown email id
429Too many requestsPer-minute/hour rate limit or monthly quota exceeded
5xxServer errorSendridge-side problem — safe to retry idempotent requests
Example error
{
  "error": "Validation Error",
  "message": "Invalid request data",
  "details": { "from": ["Invalid email"] }
}

For these two 403 responses, the code field identifies the restriction and message tells you how to resolve it. The SDK surfaces either response as a PermissionError.

Rate limits

Sending limits depend on your plan (per-minute, per-hour, and monthly quotas), and individual API keys can carry an extra per-minute cap set in the dashboard. When you hit a limit the API returns 429 with a message describing which limit was exceeded — back off and retry after a short delay.

Plan limits are listed on the pricing page.

Questions? Open a ticket from your dashboard, or start with the free plan.