Node.js SDK
Updated 6 October 20263 min read
On this page
The official Node.js SDK wraps the Ledgerline API with typed methods, automatic retries and webhook helpers. It is written in TypeScript and ships its own type definitions. The current release is 4.2.0.
Requirements and installation
The SDK supports Node.js 18 and newer. It has no runtime dependencies and uses the built-in fetch.
npm install @ledgerline/node
# or
pnpm add @ledgerline/node
Create a client
import Ledgerline from "@ledgerline/node";
const ll = new Ledgerline(process.env.LEDGERLINE_API_KEY!, {
apiVersion: "2026-09-01",
maxRetries: 2,
timeout: 30_000,
});
If you omit the key, the client reads LEDGERLINE_API_KEY from the environment. The key prefix decides the environment: a ll_test_ key talks to the sandbox and a ll_live_ key to production, so you never set the base URL by hand.
| Option | Default | Description |
|---|---|---|
apiVersion |
Your account's pinned version | Sent as Ledgerline-Version. |
maxRetries |
2 |
Automatic retries for network errors, 408, 429, 500, 502, 503 and 504. |
timeout |
30000 |
Request timeout in milliseconds. |
baseUrl |
Derived from the key | Override for a regional pin such as https://eu.api.ledgerline.dev/v1. |
appInfo |
none | A name and version added to the User-Agent for your own tracing. |
Make requests
Method names mirror the REST resources, and fields use camelCase. Amounts are integers in minor units.
const payout = await ll.payouts.create(
{
sourceAccountId: "acc_01J9QK5M2A",
counterpartyBankAccountId: "cba_01JA6C8W4N",
amount: 1_250_000,
currency: "USD",
rail: "ach",
},
{ idempotencyKey: `payout:${invoice.id}` },
);
console.log(payout.status); // "scheduled"
Idempotency
Every create call accepts idempotencyKey in its options. When you do not provide one, the SDK generates a UUID and reuses it across its automatic retries, so an SDK-level retry can never duplicate a payout. Supply your own when the operation could also be retried from your code. See Idempotency keys.
Pagination
List methods return a page that you can also iterate to fetch every item. The iterator requests further pages with limit set to 100.
for await (const payout of ll.payouts.list({ status: "paid", createdAfter: "2026-09-01" })) {
console.log(payout.id, payout.amount);
}
const page = await ll.payouts.list({ limit: 25 });
if (page.hasMore) {
const next = await ll.payouts.list({ limit: 25, cursor: page.nextCursor });
}
Errors
All failures throw a subclass of LedgerlineError. Switch on code, as described in Error format and codes.
import { LedgerlineError, RateLimitError } from "@ledgerline/node";
try {
await ll.transactions.create(params);
} catch (error) {
if (error instanceof RateLimitError) {
await sleep(error.retryAfterSeconds * 1000);
} else if (error instanceof LedgerlineError) {
console.error(error.code, error.requestId);
}
throw error;
}
| Class | Raised for |
|---|---|
AuthenticationError |
401 responses |
PermissionError |
403 responses |
NotFoundError |
404 responses |
ConflictError |
409 responses |
RateLimitError |
429 responses, exposing retryAfterSeconds |
ApiError |
5xx responses after retries are exhausted |
SignatureVerificationError |
Webhook verification failures |
Verify webhooks
import express from "express";
app.post("/hooks/ledgerline", express.raw({ type: "application/json" }), (req, res) => {
try {
const event = ll.webhooks.constructEvent(
req.body,
req.header("Ledgerline-Signature") ?? "",
process.env.LEDGERLINE_WEBHOOK_SECRET!,
);
queue.enqueue(event);
res.sendStatus(200);
} catch {
res.sendStatus(400);
}
});
constructEvent checks the HMAC-SHA256 signature and the five-minute tolerance. Pass the raw body. See Verifying webhook signatures.
Rate limit awareness
Each response exposes the limit state through ll.lastResponse.rateLimit, with limit, remaining and resetAt. The default is 600 requests per minute per key. See Rate limits.
Edge runtimes and TypeScript
The SDK works on Node, Bun, Deno and Cloudflare Workers. Types are generated from the same schema as the API, so request and response shapes cannot drift. Enable strict for the best inference.
Versioning
The SDK follows semantic versioning. A new API version never changes SDK behavior until you set apiVersion. For the Python equivalent, see Python SDK, and for release notes see the changelog.