by Wenli

Typed Node.js SDK for the Courier REST API, enabling server-side TypeScript and JavaScript apps to send notifications, manage user profiles, track message status, and issue JWT tokens.
This block delivers the full source of the @trycourier/courier Node.js SDK (v7.10.2), providing typed TypeScript access to the Courier REST API. It covers sending notifications, managing user profiles and tenants, issuing auth tokens, querying message status, and running automations. Typical buyers are backend engineers embedding Courier into an Express, Fastify, or serverless Node.js application.
client.ts — Main Courier client class; instantiate this to access all resourcesindex.ts — Root barrel export; re-exports the client, error types, and utilitiesresource.ts — Base class for all resource objects (internal)resources.ts — Aggregates all resource sub-clients onto the top-level clienterror.ts — Re-exports all typed error classes from core/api-promise.ts — Re-exports APIPromise from core/uploads.ts — Re-exports toFile / Uploadable helpersversion.ts — SDK version constantcore/ — Low-level HTTP machinery: APIPromise, error classes, resource base, upload helpersinternal/ — Utilities: query-string serialisation (qs/), header handling, platform detection, UUID, base64, env helpersresources/ — One file or subdirectory per Courier API domain (send, profiles, messages, automations, brands, bulk, tenants, users, lists, audiences, auth, etc.)npm install @trycourier/courier
The SDK ships its own HTTP layer with no external runtime dependencies. No native build steps, no pod install, no Android linking required. Node.js 20 LTS or later is the minimum supported runtime; Deno 1.28+, Bun 1.0+, Cloudflare Workers, and Vercel Edge Runtime are also supported.
Copy source: place the contents of source/ at src/courier-sdk/ (or any path you prefer) inside your project.
TypeScript config — ensure compilerOptions in tsconfig.json includes:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ES2020",
"strict": true,
"esModuleInterop": true
}
}
Spin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This TypeScript cli / script completed archive review with strong static results. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 307b69d3b741121a…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
Path alias (optional) — to import as @courier-sdk/... rather than by relative path, add:
{
"compilerOptions": {
"paths": {
"@courier-sdk": ["./src/courier-sdk/index.ts"],
"@courier-sdk/*": ["./src/courier-sdk/*"]
}
}
}
Environment variable — set COURIER_API_KEY in your environment or .env file:
COURIER_API_KEY=pk_prod_...
The client reads this automatically; no explicit argument required unless you manage multiple keys.
Instantiate — import and construct once at application startup, then pass the instance around:
import Courier from './src/courier-sdk/index';
export const courier = new Courier(); // reads COURIER_API_KEY from env
Courier (client class)import Courier, { type ClientOptions } from './src/courier-sdk/index';
const client = new Courier(options?: ClientOptions);
Central entrypoint. ClientOptions accepts apiKey, baseURL, timeout, maxRetries, defaultHeaders, and defaultQuery. Every Courier API resource is exposed as a property (client.send, client.messages, client.profiles, client.auth, client.automations, etc.). Construct once and reuse across requests.
APIPromiseimport { APIPromise } from './src/courier-sdk/index';
The return type of every SDK method. It extends a native Promise but also exposes .withResponse() (returns { data, response }) and .asResponse() (returns the raw Response object). Use .withResponse() when you need HTTP status codes or headers alongside the parsed body.
CourierError / APIError (and subtypes)import {
CourierError,
APIError,
NotFoundError,
RateLimitError,
AuthenticationError,
BadRequestError,
InternalServerError,
} from './src/courier-sdk/index';
Typed error hierarchy thrown on non-2xx responses. Catch APIError to handle all API errors generically, or catch specific subtypes for fine-grained handling. Each instance exposes .status, .headers, and .error (parsed body). Use AuthenticationError to detect invalid API keys and RateLimitError to implement back-off logic.
toFile / Uploadableimport { toFile, type Uploadable } from './src/courier-sdk/index';
Utility to wrap a Buffer, Blob, ReadableStream, or file path into an Uploadable object accepted by multipart endpoints. Use when uploading binary assets to Courier API methods that accept file parameters.
Send a transactional message to a single recipient by email, using inline content.
import Courier from './src/courier-sdk/index';
const client = new Courier(); // COURIER_API_KEY from env
async function sendWelcomeEmail(userEmail: string) {
const response = await client.send.message({
message: {
to: { email: userEmail },
content: {
title: 'Welcome aboard',
body: 'Thanks for signing up. Here is everything you need to get started.',
},
},
});
console.log('Request ID:', response.requestId);
return response.requestId;
}
sendWelcomeEmail('alice@example.com');
Create or update a user profile, then issue a scoped JWT so the browser SDK can read that user's inbox.
import Courier, { APIError, AuthenticationError } from './src/courier-sdk/index';
const client = new Courier();
async function provisionUser(userId: string, email: string) {
try {
await client.profiles.create(userId, {
profile: { email, name: 'Alice Example' },
});
const { token } = await client.auth.issueToken({
scope: `user_id:${userId} inbox:read:messages inbox:write:events`,
expires_in: '2 days',
});
return token;
} catch (err) {
if (err instanceof AuthenticationError) {
throw new Error('Invalid Courier API key — check COURIER_API_KEY');
}
if (err instanceof APIError) {
console.error('API error', err.status, err.error);
}
throw err;
}
}
Retrieve a message and inspect the HTTP status code alongside the parsed body.
import Courier, { RateLimitError } from './src/courier-sdk/index';
const client = new Courier({ maxRetries: 3, timeout: 10_000 });
async function checkMessage(messageId: string) {
try {
const { data, response } = await client.messages
.retrieve(messageId)
.withResponse();
console.log('HTTP status:', response.status);
console.log('Delivery status:', data.status);
return data;
} catch (err) {
if (err instanceof RateLimitError) {
console.warn('Rate limited — retry after:', err.headers?.['retry-after']);
}
throw err;
}
}
Trigger a pre-built automation workflow by template ID.
import Courier from './src/courier-sdk/index';
const client = new Courier();
async function triggerOnboarding(userId: string) {
const result = await client.automations.invoke.invokeByTemplate(
'onboarding-sequence',
{
data: { userId },
recipient: userId,
},
);
console.log('Automation run ID:', result.runId);
}
index.ts — Root barrel; re-exports Courier, error classes, APIPromise, toFile, and ClientOptions. Import everything from here.client.ts — Defines the Courier class and attaches all resource sub-clients as properties.resource.ts — Abstract base class providing the HTTP client reference shared by every resource.resources.ts — Imports and re-exports every resource class so client.ts can compose them.error.ts — Thin re-export of core/error.ts for backwards compatibility.api-promise.ts — Thin re-export of core/api-promise.ts.uploads.ts — Thin re-export of core/uploads.ts.version.ts — Single exported constant VERSION = '7.10.2'.core/ — Self-contained HTTP layer: APIPromise (chainable promise wrapper), typed APIError hierarchy, APIResource base, and multipart upload helpers.internal/ — Pure utility modules: qs/ (query-string stringify/parse), headers.ts, parse.ts, detect-platform.ts, to-file.ts, utils/ (base64, env, UUID, sleep, path, bytes, log).resources/send.ts — Send resource; exposes message() for the core send endpoint.resources/messages.ts — Messages resource; retrieve(), list(), cancel(), etc.resources/profiles.ts — Profiles resource; CRUD operations for user profiles.resources/auth.ts — Auth resource; issueToken() for JWT generation.resources/automations/ — Automations parent resource + Invoke child for ad-hoc and template-based automation runs.resources/lists/ — Lists parent + Subscriptions child for managing subscriber lists.resources/brands.ts — Brand management (create, update, list).resources/bulk.ts — Bulk job creation and user ingestion.resources/tenants.ts — Multi-tenant configuration resources.resources/users.ts — User-level token and preference management.resources/audiences.ts — Audience segment CRUD and membership queries.resources/audit-events.ts — Audit log retrieval.resources/notifications.ts — Notification template management.resources/shared.ts — Shared TypeScript types used across multiple resources.COURIER_API_KEY not set — the client throws AuthenticationError on the first request; always verify the env var is exported in the process that runs your server, not just in .env for a different process.require() of the built output fails, set "module": "NodeNext" and "moduleResolution": "NodeNext" in tsconfig.json; mixed module modes are the most common source of ERR_REQUIRE_ESM.T | undefined; always guard with if (result.field) before use rather than assuming presence.timeout is 60 s; override with new Courier({ timeout: 120_000 }) for bulk ingestion calls that process thousands of records.toFile required for binary uploads — passing a raw Buffer directly to a multipart parameter will fail; wrap it with await toFile(buffer, 'filename.png', { type: 'image/png' }) first.maxRetries defaults to 2; for send endpoints where duplicate delivery is unacceptable, set maxRetries: 0 and handle retries yourself with an idempotency key in defaultHeaders.I have dropped the Courier Node.js SDK source into `src/courier-sdk/` in my project.
The integration guide is in `src/courier-sdk/USAGE.md`.
The upstream npm package is `@trycourier/courier` v7.10.2.
Please help me integrate this SDK into my project step by step:
1. Read `src/courier-sdk/USAGE.md` for the real export names, signatures, and working examples.
2. Create a singleton client module at `src/lib/courier.ts` that instantiates `Courier` from
`src/courier-sdk/index.ts` using the `COURIER_API_KEY` environment variable.
3. Add a `sendNotification(userId, email, subject, body)` helper that calls `client.send.message()`.
4. Add a `issueInboxToken(userId)` helper that calls `client.auth.issueToken()` with a 2-day expiry.
5. Wrap all calls in try/catch using the typed error classes (`AuthenticationError`, `RateLimitError`,
`APIError`) exported from `src/courier-sdk/index.ts`.
6. Show me where to wire these helpers into my existing Express routes.
Do not install the npm package; import only from `src/courier-sdk/index.ts`.
Only use exports that appear in `src/courier-sdk/index.ts` or `src/courier-sdk/resources/index.ts`.
The SDK source is generated from Courier's OpenAPI specification via Stainless. See source/LICENSE if present for the exact license terms. Upstream package: @trycourier/courier on npm. Full API documentation: courier.com/docs/sdk-libraries/node.
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
Automation, Utilities & Developer Tools
Free