# openai-node: the official TypeScript and JavaScript client for the OpenAI API

> openai-node is the generated TypeScript and JavaScript SDK for the OpenAI REST API, covering Responses, Chat Completions, vision and workload identity. It is a thin, typed wrapper, not a framework, and it now requires Node 22 or newer.

**openai/openai-node** — Official JavaScript / TypeScript library for the OpenAI API

- Repository: https://github.com/openai/openai-node
- Website: https://www.npmjs.com/package/openai
- Stars: 11,193 · Forks: 1,609
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-08-27 · Updated: 2026-08-27 · Language: en
- Canonical page: https://hysenlabs.com/projects/openai-openai-node

## What openai-node actually removes from your code

The OpenAI REST API is plain HTTP, and you can call it with fetch. What you give up by doing that is the schema. openai-node is generated from the project's OpenAPI specification, so request parameters and response shapes arrive as TypeScript types rather than as documentation you read and hope you transcribed correctly. The repository ships api.md as the full API surface and an examples/ directory split by feature: assistants, audio, azure, bedrock, chat-completions, client, fine-tuning, images, live, mtls, realtime and responses.

The audience is narrow but deep. If you are writing a Node service, a CLI, a script or a serverless function in TypeScript or JavaScript and you want the API's shape to be checked at compile time, this is the intended path. If you are writing Python, this is the wrong repository entirely; the search results around openai-python and "Pip install openai" point at a different package. The README also notes Deno can import the package directly from npm, so the runtime story is not strictly Node.

## Two API generations in one client, and the newer one is the default

The README draws a line the SDK itself does not enforce. The Responses API is described as the primary API for interacting with OpenAI models. Chat Completions is described as the previous standard, supported indefinitely. Both are reachable from the same client object: client.responses.create and client.chat.completions.create.

The practical difference shows up in state handling. With Chat Completions you send a messages array and manage history yourself. With Responses you can either replay output items or pass previous_response_id for simple continuation. The README is explicit that filtering response.output down to messages is unsafe: it can drop required reasoning or tool-call items and make the next request fail. The SDK provides a toResponseInputItems() helper to normalize all replayable output items before they go into the next request. That helper is the part worth reading before you write your own conversation loop, because it encodes a rule that is easy to get wrong and hard to debug once it breaks.

Underneath, this is a generated client, not an agent framework. There is no built-in memory store, no retry policy you configure by name in the README, and no prompt templating. The repository does carry a benchmark configuration (vitest.bench.config.mts) and a bench script, but the README does not publish results, so treat performance claims about the client itself as unverified.

## Install, first request, and the Node version you need first

Installation is a single npm command. The README gives it without qualification, and the package is published as openai with main pointing at dist/index.js and types at dist/index.d.ts.

```bash
npm install openai
```

Before you run anything, check your runtime. package.json sets engines to node >=22.0.0. That is a real constraint, not a suggestion, and it is the first thing to verify on an older CI image.

The minimal request uses the Responses API. The API key is read from OPENAI_API_KEY by default, so the README notes the apiKey option can be omitted when that variable is set.

```ts
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env['OPENAI_API_KEY'], // This is the default and can be omitted
});

const response = await client.responses.create({
  model: 'gpt-5.5',
  instructions: 'You are a coding assistant that talks like a pirate',
  input: 'Are semicolons optional in JavaScript?',
});

console.log(response.output_text);
```

What you should see is the model's text on stdout via response.output_text. If you are running on Deno instead, the README shows importing the package directly rather than through npm install:

```ts
import OpenAI from 'npm:openai';
```

Vision follows the same shape. The input array carries a content list where input_text and input_image entries sit side by side, and the image is passed as a URL. The README's example points at a IIIF image endpoint, which is a useful reminder that the field takes a URL, not a base64 blob in that particular example.

## Conversation state is where this SDK will bite you

The most likely failure mode is not authentication or rate limits. It is history. The README states plainly that when you manage Responses API conversation history manually, you must preserve output items in order, and that filtering response.output to messages can drop required reasoning or tool-call items and cause the next request to fail. A developer who treats the Responses output like the old Chat Completions choices array will build a loop that works on the first turn and degrades on later ones.

The escape hatch is previous_response_id, which the README offers for simple continuation, or the toResponseInputItems() helper for full manual control. The repository points at examples/responses/manual-conversation-state.ts and a conversation state guide for the details. Neither is reproduced in the README, so the example file is the place to look.

The second constraint is Node 22. The engines field in package.json is node >=22.0.0. Any project pinned to Node 18 or 20 will need to move before adopting this version, and that is a migration cost that has nothing to do with the OpenAI API itself.

The third is scope. This library calls the API. It does not decide when to call it, how to chunk a document, or how to store embeddings. If you want a framework with those pieces, this is the wrong layer.

## Workload identity: the part most SDK comparisons miss

The README documents an authentication path that has no equivalent in the Python SDK's public description: workload identity, aimed at cloud-managed Kubernetes, Azure and GCP. Instead of a long-lived API key, the client takes short-lived tokens from cloud identity providers. The workloadIdentity parameter is mutually exclusive with apiKey, which means you pick one model per client.

For subject-token workload identity the required fields are identityProviderId, serviceAccountId and provider. The provider comes from a subpath import, openai/auth, and the README shows three concrete ones: k8sServiceAccountTokenProvider, which takes a path such as /var/run/secrets/kubernetes.io/serviceaccount/token; azureManagedIdentityTokenProvider; and gcpIDTokenProvider. A custom provider is also allowed, with a tokenType of 'jwt' and a getToken function.

Token refresh is configurable. The default refresh buffer is 1200 seconds (20 minutes) before expiration, and the README notes the effective buffer is capped at half of the actual token lifetime. You can override it with refreshBufferSeconds on the workloadIdentity object, as in 120.0.

X.509 is a separate integration with its own import path, openai/auth/x509-transport, and its own constraints. It is Node.js only, it requires the optional undici peer, and the README states it currently supports only the global https://mtls.api.openai.com/v1 API endpoint. The SDK, per the README, owns the credential's verified TLS transport, caches short-lived tokens in memory, isolates certificate generations, and bounds retries and cancellation. The repository also carries examples/mtls/ and a test:live:x509 script, so there is a runnable example to compare against.

## Where openai-node is the wrong tool

If you are not on Node 22 or newer, this version is not for you until you upgrade. The engines field is explicit.

If you want a client that manages conversation state, this is not it. The README puts that responsibility on you and warns about the specific way it goes wrong. Frameworks built on top of openai-node exist for that reason; this package is the transport, not the memory.

If you are targeting a non-OpenAI endpoint that mimics the OpenAI API, the README does not document a base URL override in the excerpt available, so treat compatibility as something to verify in api.md rather than assume. The repository does carry examples/azure and examples/bedrock directories, which indicates those paths are covered somewhere in the codebase, but the README does not describe them.

Finally, if your team is Python-first, the relevant package is not this one. The search data around "Is there a Python SDK for OpenAI?" and "Pip install openai" reflects that split, and openai-node will not serve it.

## Licence, release cadence and what upgrading costs

The package is Apache-2.0, and the LICENSE file sits at the repository root. That is a permissive licence with an explicit patent grant, which matters if you are embedding the client in a commercial product. It is not legal advice; read the licence text and your own policy.

The release history shows a fast cadence. v7.6.0, v7.7.0 and v7.8.0 all landed on 2026-08-26 and 2026-08-27, and the last push to the repository was on 2026-08-27. The package.json in the repository lists version 7.15.0, ahead of the most recent release listed above. Release automation is visible in the tree: release-please-config.json and .release-please-manifest.json. A MIGRATION.md file exists at the root, which is the document to read before a major upgrade, and CHANGELOG.md carries the per-release detail.

Because the library is generated from the OpenAPI specification, the upgrade cost is front-loaded. Minor versions mostly track API additions and should be low-risk for typed call sites. Major versions are where MIGRATION.md earns its place. There is also a NODE_VERSION_POLICY.md file at the root, which is the document to check when you need to know how long a given Node floor will hold.

## Conclusion

Adopt openai-node if you are writing TypeScript or JavaScript against the OpenAI API and want generated types over the REST surface, including the Responses API and the workload identity providers for Kubernetes, Azure and GCP. Do not adopt it if you are on Node 18 or 20, since package.json sets engines to node >=22.0.0, or if you want an abstraction that manages conversation history for you. Before writing code, read the manual conversation state example and the conversation state guide, because the README states that filtering response.output to messages can drop required reasoning or tool-call items and cause the next request to fail.

## FAQ

### What is openai-node?

It is the official JavaScript and TypeScript library for the OpenAI API, generated from the project's OpenAPI specification. The README describes it as providing convenient access to the OpenAI REST API from TypeScript or JavaScript.

### Is there a Python SDK for OpenAI?

The README covers the JavaScript and TypeScript library only and does not describe a Python package. Search results around openai-python and "Pip install openai" point to a separate project that this repository does not document.

### Is Node free to use?

The README does not address Node licensing. What it does state is that openai-node's package.json sets engines to node >=22.0.0, so the runtime version is a hard requirement regardless of cost.

## Sources

- [Official documentation](https://www.npmjs.com/package/openai)
- [Official README](https://github.com/openai/openai-node#readme)
- [Project repository](https://github.com/openai/openai-node)
- [Release notes](https://github.com/openai/openai-node/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/openai-openai-node
