Model or dataset
token-js/token.js avatar
token-js/token.js

Token.js: One TypeScript SDK for 200+ LLMs in OpenAI's Format

Integrate 200+ LLMs with one TypeScript SDK using OpenAI's format.

310 stars38 forksTypeScriptMIT

At a glance

What is it?
Token.js is an MIT-licensed TypeScript client that routes chat, streaming, tool calls and image input across ten or more providers without a proxy server. Here is what the README promises, what the package actually ships, and where the abstraction leaks.
Who is it for?
Adopt Token.js if you are writing TypeScript that has to reach several providers and you want one chat.completions.create call shape, with streaming and tool calls handled per provider. Skip it if you need JSON output or image input on Cohere, AI21, Groq or Perplexity, or if you expect extended model names to type-check.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 72 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Token.js solves for TypeScript teams

Every provider ships its own SDK with its own message shape, its own streaming iterator, and its own way of describing a tool call. A team that wants to compare Claude against GPT-4o against Gemini ends up writing three adapters and keeping them in sync as each vendor changes its API. Token.js collapses that into one client whose request object mirrors OpenAI's, so a provider switch is a two-field edit: change provider and model, leave messages alone. The README states the scope plainly: 200+ LLMs from 10+ providers, using OpenAI's format, running completely on the client side with no proxy server.

The audience is narrower than the headline. This is a TypeScript library that imports provider SDKs as dependencies, so it belongs in Node or a bundler-based frontend, not in a Python pipeline or a Go service. The README recommends environment variables for credentials, one key per provider, which means the process running Token.js holds every key it can reach. That is a deliberate client-side design, and it is the reason no proxy is required. It is also the reason you would not put this in a browser bundle with a production key inside it. The README does not discuss that trade-off.

How Token.js routes a request to ten different providers

The mechanism is visible in the package.json. Token.js depends on @anthropic-ai/sdk, @aws-sdk/client-bedrock-runtime, @google/generative-ai, @mistralai/mistralai, cohere-ai and openai directly. It is not a thin HTTP wrapper that reshapes JSON. It is a dispatcher that holds each vendor's official client and translates your OpenAI-shaped request into whatever that client expects, then translates the response back.

That design has consequences. The dependency list is the real support matrix: a provider appears in the README's table because a vendor SDK is already a dependency, and a provider that only speaks an OpenAI-compatible API is handled through the openai package rather than a dedicated adapter. It also means your install pulls in the Anthropic, Bedrock, Google, Mistral and Cohere SDKs whether or not you call those providers. The README lists AI21, Anthropic, AWS Bedrock, Cohere, Gemini, Groq, Mistral, OpenAI, Perplexity, OpenRouter and Requesty, plus any other model provider with an OpenAI compatible API.

The feature table is where the abstraction stops being uniform. Streaming is marked supported for every provider listed. Function calling is not: AI21, Groq and Perplexity are marked with a dash. JSON output is missing for Cohere, AI21, Perplexity and the truncated OpenRouter row. Image input is missing for Mistral, Cohere, AI21, Groq and Perplexity. The SDK gives you one call signature, but it does not give you one capability set, and the README is explicit that function calling works for providers and models that offer it.

Install Token.js and make a first call

Installation is a single npm command. The README gives no yarn or pnpm instruction, though the repository itself is managed with pnpm@8.6.12.

bash
npm install token.js

Credentials go in environment variables. The README recommends this approach and the repository ships a .env.example listing every key the SDK reads. For an OpenAI call you only need the first one.

bash
OPENAI_API_KEY=<openai api key>

The smallest working program imports TokenJS, constructs the client with no arguments, and calls chat.completions.create with a provider, a model and a messages array. The README's example prints completion.choices[0].

ts
import { TokenJS } from 'token.js'

const tokenjs = new TokenJS()

async function main() {
  const completion = await tokenjs.chat.completions.create({
    provider: 'openai',
    model: 'gpt-4o',
    messages: [{ role: 'user', content: 'Hello!' }],
  })
  console.log(completion.choices[0])
}
main()

To switch provider, change the two identifying fields and set the matching key. The README's function-calling example uses provider 'gemini' and model 'gemini-1.5-pro', passing a tools array and tool_choice: 'auto', then reading result.choices[0].message.tool_calls. Streaming uses the same create call with stream: true, and the return value becomes an async iterable whose parts expose part.choices[0]?.delta?.content.

The extendModelList escape hatch and its type cost

Token.js ships a predefined model list, and the README acknowledges it will lag behind vendor releases. The extendModelList method registers a new model name against a provider and copies feature support from an existing model, or takes an explicit featureSupport object with streaming, json, toolCalls and images booleans. The README's example registers a Bedrock Claude model with a regional prefix, us.anthropic.claude-3-5-sonnet-20241022-v2:0, copying features from anthropic.claude-3-sonnet-20240229-v1:0.

ts
const tokenjs = new TokenJS();
tokenjs.extendModelList(
  "bedrock",
  'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
  "anthropic.claude-3-sonnet-20240229-v1:0"
);

The README states that type casting with as any is required when using an extended model, because the model field is typed against the predefined list. That is a real ergonomic cost, not a footnote. Every call site for that model loses compile-time checking on the model name, and a typo becomes a runtime error from the provider rather than a build failure. The featureSupport parameter is also your responsibility: if you copy from a model that supports JSON mode onto one that does not, the SDK has no way to know.

Where the single-interface promise breaks down

The compatibility table is the honest part of the README and the part to read before choosing Token.js. If your application depends on JSON output, the table marks Cohere, AI21 and Perplexity as unsupported, and image input is unsupported on Mistral, Cohere, AI21, Groq and Perplexity. Tool calls are unsupported on AI21, Groq and Perplexity. A pipeline that needs structured extraction from a Perplexity search model has no path through this SDK, and no amount of provider switching fixes it.

There is a second failure mode around credentials. Because everything runs client-side with no proxy, the process needs the API key for every provider it might call. A multi-tenant backend that lets users pick a provider is now holding those users' keys, or its own keys, in one process. The README does not document per-request credential injection, key rotation, or request signing. If your security model requires that the server never sees a provider key, this library is the wrong shape, and a proxy-based gateway is the right one.

A third gap is release cadence against the model list. The repository package.json says 0.8.1, while the most recent tagged release in the repository is v0.7.1 from 2025-04-21. The last push to the repository was on 2026-07-05. The README does not document a deprecation policy for models removed by providers, so a predefined model name can become a runtime failure with no compile-time warning.

Token.js against a self-hosted gateway

The obvious alternative is a proxy gateway such as LiteLLM or a self-hosted OpenAI-compatible router. The difference is architectural, not cosmetic. A gateway runs as a service: your application speaks one HTTP API to one endpoint, and the gateway holds the provider keys, applies rate limits, logs spend and can be upgraded without redeploying clients. Token.js does the opposite. It puts the translation layer inside your process, adds vendor SDKs as dependencies, and removes the network hop and the extra service to operate.

That makes Token.js a better fit when the calling code is already TypeScript, when the number of providers is small and known, and when you do not want to run infrastructure. It is a worse fit when several languages call the same models, when you need centralized key management or cost accounting, or when you want to swap models without shipping a new client build. The README's claim that no proxy server is required is accurate and is the whole point; it is also the reason features that normally live in a gateway have no home here.

A narrower alternative is to use each vendor SDK directly and write your own adapter. That is what Token.js already does internally, so the comparison is whether you want to maintain six SDK integrations or one dependency that maintains them for you. The cost of the second option is that you inherit Token.js's release schedule, its model list, and its decisions about which features are worth normalizing.

Licence, maintenance and what upgrading costs

Token.js is MIT licensed, and the README repeats that it is free and open source under MIT. MIT permits commercial use, modification and redistribution with the licence and copyright notice retained. The dependencies are the part to check separately: the package.json pins @anthropic-ai/sdk, @aws-sdk/client-bedrock-runtime, @google/generative-ai, @mistralai/mistralai, cohere-ai and openai to specific versions, and each carries its own licence. This is not legal advice; read the notices if you redistribute.

The maintenance signal is mixed. The repository is not archived, and the last push was on 2026-07-05. The release tags stop at v0.7.1 on 2025-04-21, while package.json declares 0.8.1, so the tagged releases and the working tree have diverged. Version pinning matters here: a caret range on token.js will pull whichever version npm resolves, and the provider SDK versions are pinned inside the package, so a Token.js upgrade can change six vendor SDKs at once. The README does not document a migration guide between minor versions. The repository does contain .changeset/, which is the tooling for recording versioned changes, and a CHANGELOG.md at the top level.

Editorial conclusion

Adopt Token.js if you are writing TypeScript that has to reach several providers and you want one chat.completions.create call shape, with streaming and tool calls handled per provider. Skip it if you need JSON output or image input on Cohere, AI21, Groq or Perplexity, or if you expect extended model names to type-check. Before committing, verify which provider your app actually uses against the compatibility table, check that the featureSupport flags you pass match that model, and confirm whether the npm version you install matches the 0.8.1 in the repository package.json.

Frequently asked questions

What is Token.js used for?

It calls 200+ LLMs from 10+ providers through one TypeScript SDK that uses OpenAI's request format. The README lists chat completion, streaming, function calling, JSON output and image input as the supported features, subject to the per-provider compatibility table.

What is a Token.js example?

The README's smallest example constructs new TokenJS() and calls tokenjs.chat.completions.create with provider: 'openai', model: 'gpt-4o' and a messages array, then logs completion.choices[0]. Streaming is the same call with stream: true, iterated with for await.

What is meant by a token in Token.js?

The README does not define the term. Token.js is the name of the SDK, and the README uses it for the client class and the npm package rather than for a unit of text or an authentication token.

Does Token.js use JWT?

No. The README configures each provider with a plain API key environment variable such as OPENAI_API_KEY or ANTHROPIC_API_KEY, and AWS Bedrock with AWS_REGION_NAME, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. No JWT or bearer-token flow appears in the README.

Is there a token.json config file?

No. Token.js is the npm package name token.js, installed with npm install token.js, and configuration is done through environment variables listed in the repository's .env.example. The README describes no token.json file.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. token-js/token.js on GitHub
Community notes

Community notes