npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tink-client

v2.0.0

Published

Production-ready TypeScript SDK for the Tink Open Banking API. Zero dependencies. Full coverage of OAuth, accounts, transactions, enrichment, providers, categories, statistics, users, investments, loans, budgets, cash flow, financial calendar, account che

Readme

tink-client

npm version TypeScript Zero dependencies License: MIT

Production-grade TypeScript SDK for the Tink Open Banking API. Zero external dependencies. Full coverage of all Tink products.


Architecture

src/
├── domain/          ← Pure types & TinkError. Zero I/O, zero dependencies.
│   ├── errors.ts    TinkError with type discriminant, retryable getter
│   └── types.ts     80+ typed interfaces for every Tink API aggregate
│
├── application/     ← One service per bounded context
│   ├── auth.ts      OAuth flows, authorization grants, token caching
│   ├── accounts.ts  Accounts, credentials, identities
│   ├── transactions.ts  Transactions, enrichment, categories, statistics
│   ├── providers.ts Financial institution reference data
│   ├── users_investments_loans.ts  Users, investments, loans
│   ├── finance.ts   Budgets, cash flow, financial calendar
│   ├── verification.ts  Account check, balance check, all risk products
│   └── connectivity.ts  Monitoring, Connector ingestion, Link URL builders
│
├── infrastructure/  ← Transport adapters — no domain logic
│   ├── http.ts      fetch wrapper: bearer token, retry, cache, rate limit
│   ├── cache.ts     LRU cache with per-entry TTL
│   ├── retry.ts     Exponential backoff with full jitter
│   ├── rate_limiter.ts  Token-bucket rate limiter (instance-based)
│   └── webhook.ts   HMAC-SHA256 verification + typed event dispatch
│
└── index.ts         TinkClient — wires all services, re-exports everything

Installation

npm install tink-client

Requires Node.js ≥ 18 (Web Crypto API, fetch, URLSearchParams).


Quick start

import { TinkClient } from "tink-client";

const tink = new TinkClient({
  clientId: process.env.TINK_CLIENT_ID,
  clientSecret: process.env.TINK_CLIENT_SECRET,
  webhookSecret: process.env.TINK_WEBHOOK_SECRET,
  cache: true,
});

// 1. Get an app-level token
const token = await tink.auth.clientCredentials("accounts:read,transactions:read");

// 2. Create an authorization grant for an end user
const grant = await tink.auth.createAuthorizationGrant(token.access_token, {
  externalUserId: "your-user-id",
  scope: "accounts:read,transactions:read",
  idHint: "Alice",
});

// 3. Build the Tink Link URL and redirect the user
const linkUrl = tink.connectivity.buildTransactionsLink(grant.code, {
  clientId: process.env.TINK_CLIENT_ID!,
  redirectUri: "https://yourapp.com/tink/callback",
  market: "GB",
  locale: "en_US",
});

// 4. After callback, exchange code for user token
const userToken = await tink.auth.exchangeCode(callbackCode);

// 5. Fetch all accounts
const accounts = await tink.accounts.listAll();

// 6. Fetch all transactions
const txns = await tink.transactions.listAll({ bookedDateGte: "2026-01-01" });

// 7. Enriched transactions (Tink Enrichment API)
const enriched = await tink.transactions.listAllEnriched({ accountIdIn: ["acc-id"] });

Error handling

Every method throws TinkError on failure:

import { TinkClient, TinkError } from "tink-client";

try {
  await tink.accounts.listAll();
} catch (err) {
  if (err instanceof TinkError) {
    console.log(err.type); // "authentication_error" | "rate_limit_error" | ...
    console.log(err.status); // 401
    console.log(err.errorCode); // "TOKEN_INVALID"
    console.log(err.retryable); // false
    console.log(err.format()); // "[401] Unauthorized (TOKEN_INVALID)"
  }
}

err.retryable returns true for network errors, timeouts, and HTTP 408/429/500/502/503/504. The infrastructure layer retries these automatically (up to maxRetries attempts with exponential backoff + jitter).


Webhook verification

// Register typed handlers
tink.webhooks.on("credentials.updated", async (event) => {
  console.log("credentials updated:", event.data);
});
tink.webhooks.on("*", async (event) => {
  // wildcard — receives every event type
});

// In your HTTP handler (Express example):
app.post("/webhooks/tink", express.raw({ type: "application/json" }), async (req, res) => {
  const sig = req.headers["x-tink-signature"] as string;
  try {
    await tink.webhooks.dispatch(req.body.toString(), sig);
    res.sendStatus(204);
  } catch (err) {
    res.status(400).json({ error: err instanceof TinkError ? err.format() : String(err) });
  }
});

Configuration

| Option | Type | Default | Description | | --------------- | -------------- | ------------------------- | -------------------------------------- | | clientId | string | TINK_CLIENT_ID env | Tink application client_id | | clientSecret | string | TINK_CLIENT_SECRET env | Tink application client_secret | | webhookSecret | string | TINK_WEBHOOK_SECRET env | HMAC-SHA256 webhook signing secret | | baseUrl | string | https://api.tink.com | API base URL override | | timeoutMs | number | 30000 | Per-request timeout | | maxRetries | number | 3 | Max retry attempts on transient errors | | cache | boolean | true | Enable GET-response LRU cache | | cacheMaxSize | number | 512 | Max LRU cache entries | | fetchFn | typeof fetch | globalThis.fetch | Custom fetch (e.g. for testing) |


License

MIT — see LICENSE.