Skip to content

triqai/triqai-node

Repository files navigation

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.

About

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

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors