Production-grade TypeScript SDK for the Tink Open Banking API. Zero external dependencies. Full coverage of all Tink products.
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
npm install tink-clientRequires Node.js ≥ 18 (Web Crypto API, fetch, URLSearchParams).
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"] });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).
// 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) });
}
});| 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) |
MIT — see LICENSE.