Skip to content

fintech-sdk/increase-sdk

Repository files navigation

increase-sdk

A production-grade, independent TypeScript client for the Increase API — banking-as-a-service for accounts, ACH/wire/check/RTP/FedNow transfers, cards, entities, and more.

Covers Increase's full API surface (~90 resource groups, ~240 operations). Zero runtime dependencies — built entirely on the platform fetch, Headers, AbortController, and Web Crypto APIs, so it runs unmodified on Node ≥18, Deno, Bun, Cloudflare Workers, and in the browser.

Install

npm install increase-sdk

Usage

import { Increase } from "increase-sdk";

const client = new Increase({
  apiKey: process.env.INCREASE_API_KEY,
  environment: "sandbox", // or "production"
});

const account = await client.accounts.create({ name: "My First Account" });
console.log(account.id);

// Lazy, cursor-based pagination -- pages are fetched on demand as you
// iterate, not all up front.
for await (const account of await client.accounts.list()) {
  console.log(account.id, account.name);
}

// Sandbox-only simulations let you drive objects through their
// lifecycle without waiting on real banking rails.
const transfer = await client.achTransfers.create({
  account_id: account.id,
  amount: 1000,
  statement_descriptor: "Test payment",
});
await client.simulations.achTransfers.submit(transfer.id);

Error handling

import { IncreaseError } from "increase-sdk";

try {
  await client.accounts.retrieve("account_does_not_exist");
} catch (err) {
  if (err instanceof IncreaseError) {
    console.log(err.status, err.type, err.detail);
    if (err.isNotFound) {
      // ...
    }
  }
}

Webhooks

import { verifyWebhookSignature } from "increase-sdk";

// Express/Node example -- use whatever gives you the *raw* request body.
app.post("/webhooks/increase", express.text({ type: "*/*" }), async (req, res) => {
  try {
    await verifyWebhookSignature(req.body, req.headers, signingSecret);
  } catch {
    return res.status(400).send("invalid signature");
  }
  const event: unknown = JSON.parse(req.body);
  res.status(200).end();
});

Retries and idempotency

maxRetries (default 2) retries rate-limited (429) and server-error (5xx/408/409) responses with exponential backoff and jitter, honoring Retry-After when present. Because retrying a POST/PATCH naively could double-create something, the transport generates an Idempotency-Key once before the first attempt and reuses it across every retry of that request — Increase guarantees replaying the same key returns the original result.

Per-call options

Every method accepts a trailing options object for one-off overrides:

await client.accounts.create(
  { name: "My Account" },
  { idempotencyKey: "my-own-key", timeoutMs: 10_000, signal: myAbortSignal },
);

Logging

const client = new Increase({
  apiKey,
  logger: (event) => console.log(event.type, event),
});

Emits structured events for request start, completion (status, duration, attempt count), retries, and terminal failures.

Architecture

increase-sdk/
├── src/
│   ├── index.ts           Package entry point (re-exports everything below)
│   ├── client.ts           The Increase client class, wiring every resource
│   ├── version.ts
│   ├── core/
│   │   ├── request.ts      Transport: fetch + retries + idempotency + logging
│   │   ├── pagination.ts   Generic, lazy, async-iterable Page<T>
│   │   ├── resource.ts     BaseResource every generated resource extends
│   │   ├── error.ts        IncreaseError / IncreaseConnectionError
│   │   ├── webhook.ts      Standard Webhooks signature verification
│   │   └── qs.ts           Query parameter encoding
│   └── resources/          One file per resource: types + a *Resource class
│                            (account.ts, ach-transfer.ts, card.ts, ...)
└── test/                    Vitest suite: transport, pagination, webhook,
                             error decoding, and end-to-end client tests
  • Field names match the wire format (created_at, account_id, not createdAt/accountId) rather than being converted to camelCase — the same convention Stripe's, OpenAI's, and Anthropic's own TypeScript SDKs use. This means there's no naming-translation layer that could introduce bugs or drift from Increase's own API documentation; what you see in the docs is exactly what you type.
  • Enums are string-literal unions ("open" | "closed"), not runtime enum objects, matching modern TypeScript convention and keeping the compiled output small.
  • Nullable response fields are typed T | null; optional request parameters are field?: T.
  • Pagination: every list() method returns a Promise<Page<T>>. Page implements AsyncIterable, so for await (const item of await resource.list()) walks every item across every page, fetching each subsequent page only when the current one is exhausted.
  • File uploads: client.files.create is the one method that sends multipart/form-data (via the platform FormData) instead of JSON, since it uploads raw bytes. Its response type is named IncreaseFile rather than File to avoid shadowing the platform's built-in File/Blob API type.

Provenance

Domain models and endpoint definitions were derived from Increase's published API surface (cross-referenced against Increase's official Go SDK for field-level accuracy) and reimplemented from scratch as an independent, generated TypeScript client — not a fork or a port of any existing package.

Development

npm run build          # tsup -> dist/ (ESM + CJS + .d.ts)
npm run typecheck      # tsc --noEmit
npm run lint            # eslint .
npm run format:check    # prettier --check .
npm test                 # vitest run
npm run test:coverage    # vitest run --coverage

About

A production-grade, independent TypeScript client for the Increase API — banking-as-a-service for accounts, ACH/wire/check/RTP/FedNow transfers, cards, entities, and more.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors