Skip to content
Finowl

Language · TypeScript

Typed Finowl API calls in TypeScript with fetch

TypeScript lets you describe Finowl responses once and have the compiler catch typos like breach.title instead of breach.Title. Because the API returns stable JSON shapes, a few type aliases cover the breach record, the password result and the gender prediction, including the union of reason values for unknown results. Those types travel with you into Next.js route handlers, NestJS services, Hono apps on Node.js, or any backend runtime with a standard fetch.

The client on this page is a generic finowlPost function that returns Promise<T>, so each call site states the response type it expects. Failures become a FinowlError instance with status, code and retryAfter, which you can narrow with instanceof in a catch block. The examples wrap their logic in an async main function so they run under tsx or ts-node without extra module settings.

STEP 1

A reusable TypeScript client

Keep your key in the FINOWL_API_KEY environment variable and route every call through one helper, so authentication, timeouts and error handling live in one place.

Install
npm install --save-dev typescript tsx @types/node
TypeScript client
// finowl.ts
const BASE_URL = "https://api.finowl.co";

export class FinowlError extends Error {
  readonly status: number;
  readonly code: string;
  readonly retryAfter: number | null;

  constructor(status: number, code: string, retryAfter: number | null) {
    super("Finowl API error " + status + ": " + code);
    this.name = "FinowlError";
    this.status = status;
    this.code = code;
    this.retryAfter = retryAfter;
  }
}

type ErrorBody = { error?: { code?: string } };

export async function finowlPost<T>(path: string, body: unknown, timeoutMs = 10_000): Promise<T> {
  const apiKey = process.env.FINOWL_API_KEY;
  if (!apiKey) throw new Error("FINOWL_API_KEY is not set");

  const res = await fetch(BASE_URL + path, {
    method: "POST",
    headers: { Authorization: "Bearer " + apiKey, "Content-Type": "application/json" },
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(timeoutMs),
  });
  if (res.ok) return (await res.json()) as T;

  const err = (await res.json().catch(() => ({}))) as ErrorBody;
  const retryAfter = res.headers.get("retry-after");
  throw new FinowlError(
    res.status,
    err.error?.code ?? "unknown_error",
    retryAfter ? Number(retryAfter) : null,
  );
}

STEP 2

Call the API you need

  • Check email breaches in TypeScript with typed results

    The email breach response has two levels: a lowercase envelope with email, breached and breaches, and PascalCase breach records with fields such as Title, BreachDate, DataClasses and IsVerified. Writing those as TypeScript types means your editor autocompletes the right casing and the compiler flags any mismatch, which is handy when the same data feeds an API response, a React email template and a database model.

  • Check breached passwords in TypeScript

    A password check in TypeScript works best as a small function that returns a verdict type your signup handler can switch on. The Finowl endpoint replies with breached and count, which the example maps to a discriminated union: ok, or breached with the number of sightings. That keeps the policy decision, such as rejecting any password seen at least once, in one obvious place.

  • Batch gender prediction in TypeScript

    When you have a list of contacts, the batch endpoint accepts 1 to 50 items in one request and returns results in the same order. Each item has an id you choose, a type of name, email or username, a value, and an optional country for names. In TypeScript you can model the item result as a type with an optional data prediction or an optional error, then branch on which one is present.

A FEW GOOD QUESTIONS

TypeScript questions

Other languages and frameworks

Ship with TypeScript today

100 free credits every month. Try every request in the sandbox first.