Documentation Index
Fetch the complete documentation index at: https://yanhgming.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
@marlin/sdk works in Node.js 18 and above. Install it with your package manager of choice, then pass your secret API key to the Marlin constructor to get started.
Installation
Initialize the client
import { Marlin } from "@marlin/sdk";
const marlin = new Marlin({ apiKey: process.env.MARLIN_API_KEY! });
Store your API key in an environment variable rather than hardcoding it. Use a library like dotenv locally and your platform’s secret manager in production.
Resource methods
marlin.invoices
| Method | Signature | Description |
|---|
create | (input: CreateInvoiceInput) => Promise<Invoice> | Creates a new invoice. Returns the invoice object including the hosted paymentUrl. |
retrieve | (id: string) => Promise<Invoice> | Fetches a single invoice by its ID. |
list | (opts?: ListInvoicesOptions) => Promise<PaginatedList<Invoice>> | Returns a paginated list of invoices. Filter by customerId, subscriptionId, or status. |
void | (id: string) => Promise<Invoice> | Voids an open invoice. The invoice status changes to void. |
send | (id: string) => Promise<Invoice> | Sends the invoice to the customer via email. |
// Create
const invoice = await marlin.invoices.create({
customerId: "cus_abc123",
lineItems: [
{ description: "Pro Plan — May 2025", quantity: 1, unitAmount: 4900 },
],
});
// Retrieve
const inv = await marlin.invoices.retrieve("inv_abc123");
// List
const page = await marlin.invoices.list({ status: "open", limit: 20 });
// Void
const voided = await marlin.invoices.void("inv_abc123");
// Send
const sent = await marlin.invoices.send("inv_abc123");
marlin.plans
| Method | Signature | Description |
|---|
create | (input: CreatePlanInput) => Promise<SubscriptionPlan> | Creates a new subscription plan. |
retrieve | (id: string) => Promise<SubscriptionPlan> | Fetches a single plan by its ID. |
list | (opts?: ListPlansOptions) => Promise<PaginatedList<SubscriptionPlan>> | Returns a paginated list of plans. Filter by active. |
update | (id: string, input: UpdatePlanInput) => Promise<SubscriptionPlan> | Updates a plan’s name, description, active flag, or metadata. |
// Create
const plan = await marlin.plans.create({
name: "Pro Monthly",
amount: 4900,
interval: "month",
currency: "USDC",
});
// Retrieve
const p = await marlin.plans.retrieve("plan_abc123");
// List active plans
const active = await marlin.plans.list({ active: true });
// Update
const updated = await marlin.plans.update("plan_abc123", { active: false });
marlin.subscriptions
| Method | Signature | Description |
|---|
list | (opts?: ListSubscriptionsOptions) => Promise<PaginatedList<Subscription>> | Returns a paginated list of subscriptions. Filter by customerId, planId, or status. |
retrieve | (id: string) => Promise<Subscription> | Fetches a single subscription by its ID. |
pause | (id: string) => Promise<Subscription> | Pauses an active subscription. Billing stops until resumed. |
resume | (id: string) => Promise<Subscription> | Resumes a paused subscription. Billing restarts at the next cycle. |
cancel | (id: string) => Promise<Subscription> | Cancels a subscription. The subscription transitions to canceled. |
// List
const subs = await marlin.subscriptions.list({ customerId: "cus_abc123" });
// Retrieve
const sub = await marlin.subscriptions.retrieve("sub_abc123");
// Pause / Resume
await marlin.subscriptions.pause("sub_abc123");
await marlin.subscriptions.resume("sub_abc123");
// Cancel
await marlin.subscriptions.cancel("sub_abc123");
marlin.customers
| Method | Signature | Description |
|---|
create | (input: CreateCustomerInput) => Promise<Customer> | Creates a new customer. email is required. |
retrieve | (id: string) => Promise<Customer> | Fetches a single customer by ID. |
list | (opts?: ListCustomersOptions) => Promise<PaginatedList<Customer>> | Returns a paginated list of customers. Filter by email. |
update | (id: string, input: UpdateCustomerInput) => Promise<Customer> | Updates a customer’s email, name, walletAddress, or metadata. |
// Create
const customer = await marlin.customers.create({
email: "ada@example.com",
name: "Ada Lovelace",
walletAddress: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
});
// Retrieve
const cus = await marlin.customers.retrieve("cus_abc123");
// List
const page = await marlin.customers.list({ limit: 20 });
// Update
const updated = await marlin.customers.update("cus_abc123", {
name: "Ada Lovelace (updated)",
});
Error handling
Wrap any SDK call in a try/catch block and check for MarlinAPIError to handle API-level errors.
import { Marlin, MarlinAPIError } from "@marlin/sdk";
const marlin = new Marlin({ apiKey: process.env.MARLIN_API_KEY! });
try {
await marlin.invoices.retrieve("inv_nonexistent");
} catch (err) {
if (err instanceof MarlinAPIError) {
console.error(err.statusCode, err.code, err.message);
// e.g. 404 "not_found" "Invoice not found"
}
}
MarlinAPIError exposes three properties:
| Property | Type | Description |
|---|
statusCode | number | HTTP status code returned by the API. |
code | string | Machine-readable error code (e.g. not_found, invalid_request). |
details | Record<string, unknown> | null | Additional structured error detail when available. |
All list methods return a PaginatedList<T> with a data array and a nextCursor string. Pass nextCursor as cursor in your next request to fetch the following page.
const first = await marlin.customers.list({ limit: 20 });
for (const customer of first.data) {
console.log(customer.email);
}
if (first.nextCursor) {
const second = await marlin.customers.list({
limit: 20,
cursor: first.nextCursor,
});
}
nextCursor is null when you have reached the last page.