# Node.js SDK (preview)

> The @anytimecapital/node SDK preview: typed resources, auto-pagination, Idempotency-Key retries, typed errors and webhook verification for Node.js 18+.

Source: https://anytime-capital.com/docs/node-sdk · Markdown: https://anytime-capital.com/docs/node-sdk.md · All docs: https://anytime-capital.com/docs/llms-full.txt

> **Not on npm yet:** `@anytimecapital/node` is a preview: it isn't published, so you can't install it yet. Until it is, call the API with `fetch` (every [reference page](https://anytime-capital.com/docs/payments.md) shows the Node.js version of each request) or generate a client from the [OpenAPI document](https://anytime-capital.com/docs/openapi.md). This page documents its interface, which the reference's “Node SDK” samples use.

The SDK wraps the REST API for Node.js 18 and later with no runtime dependencies: a typed client per resource, `for await` over every page of a list, an Idempotency-Key on every write so its own retries never act twice, typed errors, and webhook signature verification.

## Create a client

```typescript
import { AnytimeCapital } from "@anytimecapital/node";

const client = new AnytimeCapital({
  apiKey: process.env.ANYTIME_API_KEY!, // ak_live_…, on your server only
  maxRetries: 2, // retries after the first attempt, on 429, 5xx and network errors
  timeoutMs: 30_000, // per attempt
  baseUrl: "https://anytime-capital.com/api/v1",
});
```

| Resource | Methods |
| --- | --- |
| `client.payments` | `list`, `retrieve` |
| `client.refunds` | `list`, `create`, `retrieve` |
| `client.paymentLinks` | `list`, `create`, `retrieve`, `update`, `deactivate` |
| `client.invoices` | `list`, `create`, `retrieve`, `send` |
| `client.customers` | `list`, `create`, `retrieve`, `update` |
| `client.products` | `list`, `create`, `retrieve`, `update`, `archive` |
| `client.subscriptionPlans` | `list`, `create`, `retrieve` |
| `client.subscriptions` | `list`, `retrieve`, `cancel`, `pause`, `resume` |
| `client.discountCodes` | `list`, `create`, `retrieve`, `deactivate` |
| `client.payouts` | `list`, `retrieve` |
| `client.balance` | `retrieve` |
| `client.disputes` | `list`, `retrieve` |
| `client.webhookEndpoints` | `list`, `create`, `retrieve`, `update`, `del` |
| `client.events` | `list`, `retrieve` |
| `client.testHelpers.events` | `create` (test keys only: [Test helpers](https://anytime-capital.com/docs/test-helpers.md)) |

Meters and usage events aren't in the SDK yet: send them with `fetch` as on [Meters & usage events](https://anytime-capital.com/docs/meters.md).

## Lists and pages

```typescript
// One page…
const page = await client.payments.list({ status: "paid", limit: 50 });

// …or every payment, each page fetched as you reach it.
for await (const payment of client.payments.list({ createdFrom: "2026-10-01" })) {
  console.log(payment.id, payment.amountCents, payment.metadata.orderId);
}

// Or collect them (stops at 10,000 by default).
const all = await client.refunds.list({ paymentId: "pay_7Hq2LmX9cR4tVb" }).toArray();
```

## Writes and retries

Every write sends an `Idempotency-Key`: yours when you pass one, otherwise one made per call. The SDK retries `429`, `5xx` and network errors with backoff that honours `Retry-After`, always with the same key, so a retry never acts twice. Pass your own key, stored with your order, to stay safe across process restarts too.

```typescript
const refund = await client.refunds.create(
  { paymentId: "pay_7Hq2LmX9cR4tVb", amountCents: 2500, reason: "requested_by_customer" },
  { idempotencyKey: `refund-${orderId}` },
);
if (refund.status === "pending_approval") {
  // Over your refund approval limit: an owner approves it in the dashboard.
}
```

## Errors

| Class | When |
| --- | --- |
| `InvalidRequestError` | `400` or `422`: fix the request; the message names the field. |
| `AuthenticationError` | `401`: missing, unknown or revoked key. |
| `PermissionError` | `403`: `PERMISSION_DENIED` or `NOT_ENROLLED`. |
| `NotFoundError` | `404`. |
| `ConflictError` | `409`: the object's state doesn't allow it. |
| `RateLimitError` | `429`, after its retries. |
| `ApiError` | `5xx`, after its retries. |
| `ConnectionError` | No answer, after its retries (`TIMEOUT` or `CONNECTION_ERROR`). |
| `SignatureVerificationError` | A webhook that didn't verify. |

All extend `AnytimeCapitalError`, with `code`, `message`, `status` and `retryAfterSeconds`. Branch on `instanceof` or on `code`; every code is in the [error code catalogue](https://anytime-capital.com/docs/error-codes.md).

## Webhooks

```typescript
import express from "express";
import { AnytimeCapital } from "@anytimecapital/node";

const app = express();
app.post("/webhooks/anytime", express.raw({ type: "application/json" }), (req, res) => {
  let event;
  try {
    event = AnytimeCapital.webhooks.constructEvent(
      req.body, // the raw Buffer, not parsed JSON
      req.header("Anytime-Signature"),
      process.env.ANYTIME_WEBHOOK_SECRET!,
    );
  } catch {
    return res.sendStatus(400);
  }
  if (event.type === "payment.succeeded") {
    // event.data is the payment: match your order with data.paymentLinkId or data.metadata.
  }
  res.sendStatus(200);
});
```

`constructEvent` rejects signatures older than 5 minutes (`{ toleranceSeconds }` changes it), and `generateTestHeader(body, secret)` signs a body for your own tests. Without the SDK, verify as on [Verify webhooks](https://anytime-capital.com/docs/webhook-signatures.md).

---

Anytime Capital is a fintech company, not a bank. Payment processing, banking and payout services are provided by Anytime Capital's licensed partners. Rates shown are for US card payments; international cards, currency conversion and disputes may carry additional fees shown in your dashboard before you accept a payment.
