Skip to content
Ledgerline Help

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.