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
- 1Create an account and verify your sending domain (Dashboard → Domains). Sendridge gives you DNS records to add; verification usually completes in minutes.
- 2Create an API key (Dashboard → API Keys). Keys look like
sr_…and are shown once — store yours securely. - 3Install the SDK and send your first email:
npm install sendridgeimport { Sendridge } from "sendridge";
const sendridge = new Sendridge(process.env.SENDRIDGE_API_KEY);
const { id } = await sendridge.emails.send({
from: "you@yourdomain.com",
to: "customer@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.
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:
Authorization: Bearer sr_xxxxxxxxxxxxxxxxBest 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
npm install sendridgeRequires Node.js 18+. The package ships TypeScript types, works with both import (ESM) and require (CommonJS), and has zero runtime dependencies.
// ESM / TypeScript
import { Sendridge } from "sendridge";
// CommonJS
const { Sendridge } = require("sendridge");
const sendridge = new Sendridge(); // reads SENDRIDGE_API_KEYSDK — Send an email
const result = await sendridge.emails.send({
from: "billing@yourdomain.com", // 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: "billing@yourdomain.com",
// subject: "Your invoice",
// createdAt: "2026-07-15T10:30:00.000Z"
// }| Field | Type | Required | Description |
|---|---|---|---|
| from | string | Yes | Sender address. Its domain must be verified in your dashboard. |
| to | string | string[] | Yes | One recipient, or up to 50. |
| subject | string | Yes | Subject line (max 998 chars). |
| html | string | One of html/text | HTML body. |
| text | string | One of html/text | Plain-text body. |
| replyTo | string | No | Reply-To address. |
| tags | Record<string, string> | No | String tags for your own filtering. |
| metadata | Record<string, unknown> | No | Arbitrary JSON stored with the email. |
SDK — Retrieve an email
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
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:
import {
SendridgeError,
ValidationError, // 400 — bad payload; err.details has field errors
AuthenticationError, // 401 — missing / invalid / revoked / expired key
PermissionError, // 403 — e.g. unverified domain, plan 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.
SDK — Configuration
const sendridge = new Sendridge("sr_...", {
baseUrl: "https://api.sendridge.com", // override for self-hosted / local dev
timeoutMs: 30_000, // per-request timeout (default 30s)
maxRetries: 2, // GET-only automatic retries (default 2)
});REST API — Overview
Prefer another language? The REST API is the same surface the SDK wraps. All endpoints accept and return JSON.
Base URL: https://api.sendridge.com
Auth: Authorization: Bearer sr_xxxxxxxxxxxxxxxxSuccessful responses wrap the payload in a data field; errors return { error, message, details? }.
POST /v1/emails/send
Queues an email for delivery. Responds 202 Accepted.
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>"
}'{
"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.
curl https://api.sendridge.com/v1/emails/665f1c2e9b1d2a0012345678 \
-H "Authorization: Bearer $SENDRIDGE_API_KEY"{
"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).
curl "https://api.sendridge.com/v1/emails?page=1&limit=20" \
-H "Authorization: Bearer $SENDRIDGE_API_KEY"REST API — Errors
| Status | Meaning | Typical causes |
|---|---|---|
| 400 | Validation error | Missing/invalid fields; details lists per-field errors |
| 401 | Unauthorized | Missing, invalid, revoked, or expired API key |
| 403 | Forbidden | Unverified sending domain, key permissions, IP allowlist, plan restrictions |
| 404 | Not found | Unknown email id |
| 429 | Too many requests | Per-minute/hour rate limit or monthly quota exceeded |
| 5xx | Server error | Sendridge-side problem — safe to retry idempotent requests |
{
"error": "Validation Error",
"message": "Invalid request data",
"details": { "from": ["Invalid email"] }
}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.