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

triqai

v0.1.3

Published

Official TypeScript SDK for the Triqai Transaction Enrichment API

Readme

Triqai Node.js SDK

The official Node.js / TypeScript SDK for the Triqai Transaction Enrichment API.

Enrich raw bank transaction descriptions into structured data: merchants, categories, locations, intermediaries, and more.

Installation

npm install triqai
yarn add triqai
pnpm add triqai

Quick Start

import Triqai from "triqai";

const triqai = new Triqai("triq_your_api_key");

const result = await triqai.transactions.enrich({
  title: "STARBUCKS SEATTLE WA",
  country: "US",
  type: "expense",
});

console.log(result.data.transaction.category.primary.name);
// => "Food & Dining"

console.log(result.data.entities);
// => [{ type: "merchant", data: { name: "Starbucks", ... } }, ...]

Requirements

  • Node.js 18+ (uses native fetch)
  • Also works in Bun, Deno, and Cloudflare Workers

Configuration

const triqai = new Triqai("triq_your_api_key", {
  // Base URL (default: https://api.triqai.com)
  baseUrl: "https://api.triqai.com",

  // Retry configuration
  maxRetries: 3, // default: 3
  retryDelay: 500, // base delay in ms (default: 500)
  maxRetryDelay: 30_000, // max delay in ms (default: 30000)

  // Request timeout in ms (default: 60000)
  timeout: 60_000,

  // Extra headers for every request
  defaultHeaders: {
    "X-Custom-Header": "value",
  },

  // Debug hooks
  onRequest: (info) => console.log(`${info.method} ${info.url}`),
  onResponse: (info) => console.log(`${info.status} in ${info.durationMs}ms`),
});

API Reference

Transactions

Enrich a transaction

const result = await triqai.transactions.enrich({
  title: "AMAZON MKTPLACE PMTS AMZN.COM/BILL WA",
  country: "US",
  type: "expense",
  options: {
    // Skip specific entity extraction
    filters: {
      noLocation: true,
      noIntermediary: true,
    },
    // Pre-fill known data to improve accuracy
    merchant: {
      name: "Amazon",
    },
  },
});

// API v1.1.11+: `data.transaction.channel` is no longer returned.
// Confidence reasons are dynamic and may include tags like:
// `venue_or_attraction`, `merchant_location_crosscheck_corrected`,
// `merchant_location_crosscheck_recovered`, `merchant_location_mismatch`, `geo_mismatch`.

Enrich with idempotency

const result = await triqai.transactions.enrich(
  { title: "STARBUCKS", country: "US", type: "expense" },
  { idempotencyKey: "my-unique-key-123", force: false },
);

List transactions

// Get a single page
const page = await triqai.transactions.list({
  page: 1,
  size: 50,
  startDate: "2026-01-01T00:00:00Z",
  endDate: "2026-03-01T00:00:00Z",
});

console.log(page.data); // EnrichedTransaction[]
console.log(page.pageInfo); // { page, size, total, totalPages }

// Navigate pages
if (page.hasNextPage) {
  const nextPage = await page.nextPage();
}

Auto-paginate

const page = await triqai.transactions.list();

for await (const tx of page) {
  console.log(tx.id, tx.raw, tx.status);
}

Get a transaction

const tx = await triqai.transactions.get("550e8400-e29b-41d4-a716-446655440000");

Delete a transaction

const { deleted, transactionId } = await triqai.transactions.delete(
  "550e8400-e29b-41d4-a716-446655440000",
);

Categories

const { categories, total, categoryVersion } = await triqai.categories.list();

for (const cat of categories) {
  console.log(`${cat.name} (level ${cat.level}, type: ${cat.type})`);
}

Merchants

const merchant = await triqai.merchants.get("merchant-uuid");
console.log(merchant.name, merchant.website, merchant.icon);

Locations

const location = await triqai.locations.get("location-uuid");
console.log(location.formatted, location.structured.city);

Intermediaries

const intermediary = await triqai.intermediaries.get("intermediary-uuid");
console.log(intermediary.name); // "PayPal", "Square", etc.

Issue Reports

Report an enrichment issue

const report = await triqai.issueReports.create({
  transactionId: "tx-uuid",
  description: "Merchant was identified incorrectly",
  fields: ["entities.merchant.data.name"],
});

List issue reports

const page = await triqai.issueReports.list({
  status: "pending",
  transactionId: "tx-uuid",
});

// Auto-paginate
for await (const report of page) {
  console.log(report.id, report.status);
}

Get an issue report

const report = await triqai.issueReports.get("report-uuid");

Error Handling

All API errors are thrown as TriqaiError. Common HTTP statuses are mapped to typed subclasses:

import Triqai, {
  TriqaiError,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  InsufficientCreditsError,
  NotFoundError,
} from "triqai";

try {
  await triqai.transactions.enrich({ title: "", country: "US", type: "expense" });
} catch (err) {
  if (err instanceof ValidationError) {
    console.log("Field errors:", err.fieldErrors);
    // { title: ["Title cannot be empty"] }
  } else if (err instanceof RateLimitError) {
    console.log("Retry after:", err.rateLimitInfo.retryAfter, "seconds");
  } else if (err instanceof AuthenticationError) {
    console.log("Check your API key");
  } else if (err instanceof InsufficientCreditsError) {
    console.log("Top up credits at https://triqai.com/dashboard");
  } else if (err instanceof NotFoundError) {
    console.log("Resource not found");
  } else if (err instanceof TriqaiError) {
    console.log(`API error ${err.statusCode}: ${err.message} [${err.code}]`);
    console.log("Request ID:", err.requestId);
  }
}

Error Classes

| Class | Status | When | | --- | --- | --- | | AuthenticationError | 401 | Invalid or missing API key | | InsufficientCreditsError | 402 | No credits remaining | | AuthorizationError | 403 | Key valid but not authorized | | NotFoundError | 404 | Resource does not exist | | ClientDisconnectedError | 499 | Client disconnected before completion | | DuplicateRequestError | 409 | Idempotency key reused | | ValidationError | 422 | Request body validation failed | | RateLimitError | 429 | Rate limit exceeded | | InternalServerError | 500 | Server error (retried automatically) | | ServiceUnavailableError | 503 | Service temporarily down (retried automatically) | | GatewayTimeoutError | 504 | Upstream timeout | | ConnectionError | - | Network/DNS failure | | TimeoutError | - | Request exceeded timeout |

Automatic Retries

The SDK automatically retries on transient errors (429, 500, 503, 504, and network errors) with exponential backoff:

  • GET and DELETE requests are always retried
  • POST requests are only retried when an idempotencyKey is provided
  • The Retry-After header is respected when present
  • Default: 3 retries, 500ms base delay, 30s max delay

Disable retries:

const triqai = new Triqai("triq_your_api_key", { maxRetries: 0 });

Rate Limiting

Rate limit information is available on successful responses. The SDK handles 429 responses automatically, but you can monitor usage via the onResponse hook or rawGet/rawPost/rawDelete methods:

// Option 1: Debug hook
const triqai = new Triqai("triq_your_api_key", {
  onResponse: (info) => {
    // info.headers contains X-RateLimit-* values
  },
});

// Option 2: Raw request with full response
const resp = await triqai.rawGet("/v1/categories");
console.log(resp.rateLimitInfo.remaining); // tokens left
console.log(resp.rateLimitInfo.limit); // max tokens
console.log(resp.rateLimitInfo.concurrencyRemaining); // concurrent slots left

Health & API Info

// Check API health
const health = await triqai.health();
console.log(health.data.status); // "healthy"

// Get API version and endpoint directory
const info = await triqai.apiInfo();
console.log(info.data.version); // "v1"
console.log(info.data.endpoints);

Raw Requests

For endpoints not yet covered by a resource class, or when you need the full HTTP response (headers, rate limit info):

import type { HttpResponse } from "triqai";

// Full response with headers and rate limit info
const resp: HttpResponse<any> = await triqai.rawGet("/v1/categories");
console.log(resp.data); // response body
console.log(resp.rateLimitInfo); // { limit, remaining, ... }

Pricing

The Triqai API uses a credit-based pricing model. See triqai.com/pricing for details.

TypeScript

This package is written in TypeScript and ships with full type definitions. All request/response types are exported:

import type {
  EnrichRequest,
  EnrichSuccessResponse,
  EnrichedTransaction,
  MerchantData,
  LocationData,
  CategoryInfo,
  EntityResult,
  TransactionType,
  EnrichmentFieldPath,
} from "triqai";

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

MIT - see LICENSE for details.

The Triqai API itself is a commercial product. This SDK is open source, but API usage requires an API key and is subject to Triqai's terms of service.