Freerouter

API Reference

Complete API surface for @freerouter/sdk - createFreeRouter, FreeRouter methods, types, error handling, health tracking, and key fingerprinting. All free models, $0 cost.

createFreeRouter()

Creates a shared FreeRouter instance. Can be safely shared across concurrent requests. Holds no credential state.

Usage
import { createFreeRouter } from "@freerouter/sdk"

// Default in-memory health store
const freerouter = createFreeRouter()

// Custom persistent health store
const freerouter = createFreeRouter({
  healthStore: myRedisStore,
})

FreeRouterConfig

Prop

Type

Returns

An object with three methods described below.


FreeRouter Methods

languageModel()

Returns a LanguageModelV4 (from @ai-sdk/provider) with transparent failover across providers. Compatible with generateText, streamText, generateObject, and all Vercel AI SDK v7 functions.

Usage
const model = freerouter.languageModel("free:auto", {
  groq: process.env.GROQ_API_KEY,
  google: process.env.GOOGLE_API_KEY,
})

Prop

Type

Key requirement

Providers without a matching key are skipped during resolution. Pass only providers you have keys for.


models()

Returns the full model catalog - all known models across all 13 providers.

Usage
const allModels = freerouter.models()
// [
//   {
//     provider: "groq",
//     modelId: "llama-3.3-70b-versatile",
//     capabilities: ["fast", "tool-use"],
//     contextWindow: 131072,
//     free: true,
//   },
//   ...
// ]

ModelInfo

Prop

Type

Capability

type Capability = "fast" | "reasoning" | "long-context" | "vision" | "tool-use"

healthFor()

Returns a health snapshot scoped to the given keys. Never exposes another user's health state.

Usage
const health = freerouter.healthFor({ groq: "my-groq-key" })
// {
//   groq: {
//     state: "healthy",
//     consecutiveFailures: 0,
//   }
// }

ProviderHealth

Prop

Type


Health Tracking

Health is tracked per (provider, keyFingerprint) pair. Two users with different Groq keys have completely independent health entries.

State machine

healthy ──rate-limit──▶ rate-limited ──retry-after──▶ healthy
healthy ──3× error────▶ down ──10s cooldown──▶ healthy (half-open)
StateTriggerBehavior
healthyNormal operationSingle success resets failure counter
rate-limitedHTTP 429 responseExcluded until retryAfter (from Retry-After header or 60s default)
down3 consecutive non-rate-limit errorsExcluded for 10s cooldown, then half-open (allowed one retry)

HealthStore Interface

Implement for persistent storage across restarts:

Custom health store
import { createFreeRouter } from "@freerouter/sdk"
import type { HealthStore, HealthKey, ProviderHealth } from "@freerouter/sdk"

const redisStore: HealthStore = {
  get(key: HealthKey): ProviderHealth {
    // Fetch from Redis keyed by `${key.provider}:${key.keyFingerprint}`
  },
  recordSuccess(key: HealthKey): void {
    // Write healthy state to Redis
  },
  recordFailure(key: HealthKey, kind: "rate-limit" | "error", retryAfterMs?: number): void {
    // Write degraded state to Redis with optional retry-after
  },
}

const freerouter = createFreeRouter({ healthStore: redisStore })

In-memory defaults

  • Unseen keys: Returned as { state: "healthy", consecutiveFailures: 0 }
  • recordSuccess(): Resets to healthy with 0 failures
  • recordFailure("rate-limit"): Sets "rate-limited" with retryAfter = now + retryAfterMs (default 60s)
  • recordFailure("error"): At 3+ consecutive → sets "down" with 10s cooldown

Error Handling

Error classes

class FreeRouterError extends Error {
  readonly provider: string    // Provider that failed (e.g. "groq")
  readonly cause?: unknown     // Underlying error
}

class FreeRouterAllProvidersFailedError extends FreeRouterError {
  readonly errors: FreeRouterError[]  // Failure chain, one per provider tried
}

Error handling example

Catching provider errors
import { FreeRouterAllProvidersFailedError } from "@freerouter/sdk"

try {
  const { text } = await generateText({ model, prompt })
} catch (err) {
  if (err instanceof FreeRouterAllProvidersFailedError) {
    console.error(`All ${err.errors.length} providers failed:`)
    for (const e of err.errors) {
      console.error(`  - ${e.provider}: ${e.message}`)
    }
  }
}

Failover behavior

Prop

Type

Timeouts

TimeoutValueDescription
Provider call20,000msMax time for a single provider doGenerate / doStream call
First stream chunk15,000msMax wait for the first byte from a streaming provider

Key Fingerprinting

Every raw API key is SHA-256 hashed on receipt. The first 16 hex characters form a stable, non-reversible fingerprint used for health tracking.

fingerprintKey()
import { fingerprintKey } from "@freerouter/sdk"

const fp = fingerprintKey("sk-abc123")
// => "a1b2c3d4e5f6g7h8" (16 hex characters)
PropertyDescription
DeterministicSame key → same fingerprint every time
Non-reversibleRaw key cannot be recovered from fingerprint
Safe for loggingRaw keys never appear in health snapshots, error messages, or debug output

Types

FreeRouterKeys

FreeRouterKeys
type FreeRouterKeys = Partial<Record<ProviderId, string>>

HealthKey

HealthKey
interface HealthKey {
  provider: ProviderId
  keyFingerprint: string
}

ProviderId

ProviderId
type ProviderId =
  | "groq" | "google" | "cloudflare" | "openrouter" | "nvidia"
  | "cerebras" | "together" | "fireworks" | "mistral" | "sambanova"
  | "deepseek" | "deepinfra" | "cohere"

Exported values

ExportKindDescription
createFreeRouterfunctionFactory for creating a FreeRouter instance
createMemoryHealthStorefunctionDefault in-memory health store factory
fingerprintKeyfunctionSHA-256-based API key fingerprinting
FreeRouterErrorclassSingle-provider error
FreeRouterAllProvidersFailedErrorclassAll-providers-exhausted error

On this page