TypeScript SDK

The official shipmail package provides type-safe access to the full API. Works in Node.js 18+, Bun, Deno, and edge runtimes.

Installation

npm install shipmailbun add shipmail

Quick start

import ShipMail from "shipmail"; const shipmail = new ShipMail(process.env.SHIPMAIL_API_KEY); // Send an email const message = await shipmail.messages.send({ from: "hello@yourdomain.com", to: ["recipient@example.com"], subject: "Hello from shipmail", text: "It works.", }); console.log(message.id); // msg_...

Configuration

Pass a string for the API key alone, or an object for full control:

const shipmail = new ShipMail({ apiKey: process.env.SHIPMAIL_API_KEY, baseUrl: "https://shipmail.to/api/v1", // default maxRetries: 2, // default timeout: 30_000, // ms, default defaultHeaders: { "X-Custom": "value" }, });
OptionDefaultDescription
apiKeyrequiredYour sm_live_... key.
baseUrlhttps://shipmail.to/api/v1API base URL.
maxRetries2Retry count for 429 and 5xx responses.
timeout30000Request timeout in ms.
defaultHeaders{}Headers sent with every request.
fetchglobalThis.fetchCustom fetch implementation for testing or proxying.

Resources

The client exposes each API resource as a property:

PropertyMethods
shipmail.domainscreate, list, get, update, delete, verify, search, register
shipmail.mailboxescreate, list, get, update, delete, updateAutoReply
shipmail.messagessend, get
shipmail.threadslist, get, reply
shipmail.webhookscreate, list, get, update, delete, rotateSecret, test, listDeliveries
shipmail.suppressionslist, remove
shipmail.statusget

Error handling

API errors throw typed subclasses of ShipMailError. Each error exposes status, type, requestId, and retryable.

import ShipMail, { ValidationError, RateLimitError, ShipMailError, } from "shipmail"; try { await shipmail.messages.send({ ... }); } catch (err) { if (err instanceof ValidationError) { console.log(err.details); // per-field errors } else if (err instanceof RateLimitError) { console.log(err.retryAfter); // seconds to wait } else if (err instanceof ShipMailError) { console.log(err.status, err.requestId); } }
ClassStatus
AuthenticationError401
AuthorizationError403
ValidationError422
NotFoundError404
ConflictError409
RateLimitError429
InternalServerError500
ConnectionErrorNetwork failure

Pagination

List methods return a Page object that implements AsyncIterable. Iterate with for await to automatically fetch all pages:

const domains = shipmail.domains.list(); for await (const domain of domains) { console.log(domain.name); }

Pass limit and cursor for manual control:

const page = shipmail.domains.list({ limit: 10 });

Webhook verification

The SDK exports a standalone verifyWebhook function. It is async because it dynamically imports the crypto module for portability.

import { verifyWebhook } from "shipmail"; const event = await verifyWebhook( rawBody, request.headers, process.env.WEBHOOK_SECRET, ); console.log(event.event_type); // "message.received"

Throws WebhookVerificationError if the signature is invalid or the timestamp is outside the 5-minute tolerance window. Pass { toleranceInSeconds: 600 } to customize.

Per-request options

Every method accepts an optional last argument for request-level overrides:

await shipmail.domains.create( { name: "example.com" }, { idempotencyKey: "550e8400-...", timeout: 10_000, signal: AbortSignal.timeout(5000), }, );

Links