Official TypeScript SDK for the CoCart REST API. Build headless WooCommerce storefronts — meaning your frontend (React, Astro, Next.js, or any framework) talks to WooCommerce through its API instead of using PHP templates.
Important
This SDK is looking for feedback, if you experience a bug please report it.
- Add SDK docs to documentation site
- Add support for Cart API extras
- Add Checkout API support
- Add Customers Account API support
- Node.js 20+ — Node.js is the JavaScript runtime that lets you run JavaScript outside a browser (e.g., on a server). Version 20 or higher is required because it includes a built-in
fetchfunction for making HTTP requests. You can check your version by runningnode -vin your terminal. - CoCart plugin installed on your WooCommerce store — This is the WordPress plugin that provides the REST API endpoints the SDK communicates with.
- CoCart JWT Authentication plugin for JWT features (optional) — Only needed if you want to use JSON Web Token authentication (explained in the Authentication guide).
- TypeScript 5.0+ (recommended) — Not strictly required, but you get the best experience (autocompletion, type checking) with TypeScript.
See SUPPORT.md for our versioning policy, supported Node.js versions, and support lifecycle.
- Zero runtime dependencies — uses native
fetch(Node 20+, all modern browsers), no extra packages to install - ESM + CJS dual output — works with both modern
importsyntax and olderrequire()syntax - Typed responses and parameters with generics
- Client-side input validation (catches errors before network requests)
- Currency formatting and timezone utilities
- Event system for request/response lifecycle hooks
- Response transformer for custom processing
- Configurable auth header name (for proxies that strip
Authorization) - Encrypted localStorage for session persistence (AES-256-GCM, Web Crypto API)
- JWT authentication with auto-refresh
- Legacy CoCart plugin support with version-aware endpoint guards
- Framework adapters for Astro, Next.js, Nuxt, Remix, SvelteKit, Vite, Elysia.js, Fastify, Hono, and Deno
npm is the default package manager that comes with Node.js. Run this in your project's root folder:
npm install @cocartheadless/sdkYarn is an alternative package manager. If you use Yarn in your project:
yarn add @cocartheadless/sdkpnpm is a fast, disk-efficient package manager. If you use pnpm:
pnpm add @cocartheadless/sdkBun is a fast JavaScript runtime with a built-in package manager. If you use Bun:
bun add @cocartheadless/sdkZero runtime dependencies — the SDK does not install any additional packages, keeping your project lightweight.
For platforms like Framer, Webflow, or any environment where you just need a <script> tag — no npm required:
jsDelivr:
<script src="https://cdn.jsdelivr.net/npm/@cocartheadless/sdk/dist/index.global.js"></script>unpkg:
<script src="https://unpkg.com/@cocartheadless/sdk/dist/index.global.js"></script>Then use it:
<script>
const client = new CoCart('https://your-store.com');
</script>This loads a single minified file that exposes all SDK exports under the CoCart global. See the dedicated guides for Framer and Webflow.
You can also pin a specific version:
<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/@cocartheadless/sdk@1.1.0/dist/index.global.js"></script>
<!-- unpkg -->
<script src="https://unpkg.com/@cocartheadless/sdk@1.1.0/dist/index.global.js"></script>An SDK (Software Development Kit) is a library that provides ready-made functions for talking to a specific service — in this case, the CoCart REST API on your WooCommerce store. Instead of writing raw HTTP requests yourself, you call simple methods like client.cart().addItem(123, 2) and the SDK handles the details for you.
The import statement loads the SDK into your code. The await keyword is used before operations that talk to the server, because network requests take time and JavaScript needs to wait for the response before continuing.
import { CoCart } from '@cocartheadless/sdk';
// Create a client pointing to your WooCommerce store
const client = new CoCart('https://your-store.com');
// Browse products (no auth required)
const products = await client.products().all({ per_page: '12' });
// Add to cart (guest session created automatically)
const response = await client.cart().addItem(123, 2);
// Get cart
const cart = await client.cart().get();
console.log(cart.getItems()); // Array of items in the cart
console.log(cart.get('totals.total')); // Reach into nested data with dot notationNote: Code using
awaitmust be inside anasyncfunction. If you're using a modern framework like Next.js, Astro, or Nuxt, your component or page functions are already async. In a plain script, wrap your code in an async function:async function main() { const client = new CoCart('https://your-store.com'); const cart = await client.cart().get(); console.log(cart.getItems()); } main();
| Guide | Description |
|---|---|
| Configuration & Setup | Options, fluent config, framework adapters, white-labelling |
| Authentication | Guest, Basic Auth, JWT, consumer keys |
| Cart API | Add, update, remove items, coupons, shipping, fees |
| Products API | List, filter, search, categories, tags, brands |
| Sessions API | Admin sessions, SessionManager, storage adapters |
| Error Handling | Error hierarchy, catching errors, common scenarios |
| Utilities | Currency formatter, timezone helper, response transformer |
| Guide | Description |
|---|---|
| Astro | Browser + SSR setup, API routes, examples |
| Next.js | Client + Server Components, Route Handlers, middleware |
| Nuxt | Browser plugin, server routes, defineEventHandler |
| Remix | Loaders, actions, resource routes |
| SvelteKit | load functions, server routes, hooks |
| Vite | Browser-only SPA; pair with a backend adapter for the API layer |
| Elysia.js | Bun-first route handlers |
| Fastify | Node.js route handlers (server-only) |
| Hono | Multi-runtime (Node, Bun, Cloudflare Workers, Deno) |
| Deno | Deno.serve(), Fresh islands |
| Framer | CDN script, Code Overrides, product display |
| Webflow | CDN script, custom code, dynamic elements |
A fluent API lets you chain multiple calls in a single expression instead of writing separate statements. Each method returns the client itself, so you can keep adding dots:
const client = new CoCart('https://your-store.com')
.setTimeout(15000)
.setMaxRetries(2)
.addHeader('X-Custom', 'value');Access nested data in API responses using a simple string path with dots — no need to chain object properties or worry about undefined errors:
const cart = await client.cart().get();
cart.get('totals.total'); // Reach into nested objects
cart.get('currency.currency_code'); // No manual null checks needed
cart.get('items.0.name'); // Access array items by indexRequest only the fields you need — the return type narrows automatically:
const response = await client.cart().getFiltered(['items', 'totals']);
const data = response.toObject();
data.items; // CartItem[] ✓
data.totals; // CartTotals ✓
data.currency; // compile error — not requested ✓import { CurrencyFormatter } from '@cocartheadless/sdk';
const fmt = new CurrencyFormatter();
const currency = response.getCurrency();
fmt.format(4599, currency); // "$45.99"
fmt.formatDecimal(4599, currency); // "45.99"Invalid inputs are caught before making a network request:
await client.cart().addItem(-1, 0);
// throws ValidationError: "Product ID must be a positive integer"client.on('request', (e) => console.log(`${e.method} ${e.url}`));
client.on('response', (e) => console.log(`${e.status} in ${e.duration}ms`));
client.on('error', (e) => console.error(e.error));Cart keys and tokens are stored in the browser's localStorage encrypted with AES-256-GCM via the Web Crypto API — a browser-native encryption API that requires no extra libraries:
import { CoCart, EncryptedStorage } from '@cocartheadless/sdk';
const storage = new EncryptedStorage('your-secret-key');
const client = new CoCart('https://your-store.com', { storage });JWT (JSON Web Token) is a secure authentication method where you log in once and receive a token. The SDK can automatically refresh expired tokens behind the scenes, so customers never get unexpectedly logged out:
const result = await client.jwt().withAutoRefresh(async (c) => {
return await c.cart().get();
});Pre-built adapters for Astro, Next.js, Nuxt, Remix, SvelteKit, Elysia.js, Fastify, Hono, and Deno handle the browser/server split automatically. Cart state is passed via HTTP headers instead of cookies — avoiding GDPR consent issues and CORS restrictions:
// Astro / Next.js — browser
import { createBrowserClient, attachCartKeyHeader } from '@cocartheadless/sdk/astro';
const client = createBrowserClient('https://your-store.com', {
encryptionKey: 'your-key',
});
await client.restoreSession();
attachCartKeyHeader(client);
// Astro / Next.js — server
import { createServerClient } from '@cocartheadless/sdk/astro';
const client = createServerClient('https://your-store.com', Astro.request);We have different channels at your disposal where you can find information about the CoCart project, discuss it and get involved:
- 📖 Documentation: this is the place to learn how to use CoCart API. Get started!
- 👪 Community: use our Discord chat room to share any doubts, feedback and meet great people. This is your place too to share how are you planning to use CoCart!
- 🐞 GitHub: we use GitHub for bugs and pull requests, doubts are solved with the community.
- 🐦 Social media: a more informal place to interact with CoCart users, reach out to us on X/Twitter.
Website cocartapi.com · GitHub @cocart-headless · X/Twitter @cocartapi · Facebook · Instagram
MIT