Cargando documentación…
Cargando documentación…
@notheadless/sdk
createClient devuelve un cliente agrupado por recurso: products, categories, shipping, checkouts y cart. Funciona en cualquier runtime con fetch: Node, Edge, Bun, Deno y workers.
import { createClient } from "@notheadless/sdk"
export const nube = createClient({
storeId: 7338212,
token: process.env.STOREFRONT_TOKEN,
})| Prop | Tipo | Descripción |
|---|---|---|
| storeId | string | number | ID numérico de la tienda en Tiendanube. |
| token | string | Token de Storefront, enviado como Authorization: Bearer. Omitilo solo si la configuración de tu API permite acceso sin token. |
| baseUrl | string = "…/v2026-11" | Base de la API, incluido el segmento de versión. |
| locale | string = "es" | Elige qué string tomar de los campos localizados ({ es, pt, en }) en las tiendas que los devuelven. |
| batch | { windowMs, maxSize } | false = { 2, 30 } | Ventana de batching automático para findUnique. maxSize tiene un tope de 30, el límite de la API. |
| concurrency | number = 8 | Máximo de requests HTTP en paralelo. La paginación y las búsquedas divididas en lotes lo respetan. |
| retries | number = 3 | Reintentos de GET ante 429 (respetando Retry-After), 5xx y errores de red. Los POST solo se reintentan ante 429. |
| timeoutMs | number = 15000 | Timeout por intento. |
| cache | { ttlMs } | Cache de GET en memoria. Viene desactivada; preferí la cache de tu framework. |
| fetchOptions | RequestInit & { next? } | Se combina con cada GET, por ejemplo { next: { revalidate: 60 } }. Los POST siempre son no-store. |
| buyerIp | string | Envía X-LinkedStore-Buyer-IP para aplicar límites de tasa (rate limits) por comprador (solo con acceso por token). |
| onRequest | (e: RequestEvent) => void | Observá cada request: método, url, status, duración e intento. |
| fetch | typeof fetch | fetch personalizado, para tests o instrumentación. |
| schema | "warn" | "throw" | "off" = "warn" | Validación en runtime de las respuestas contra los modelos. Mirá Errores y límites. |
| onSchemaIssue | (issue: SchemaIssue) => void | Recibí los reportes de drift (por ejemplo, para mandarlos a Sentry) en lugar de console.warn. |
Para los requests que dispara el comprador, asociá un cliente a su IP usando una dirección verificada por el proxy de tu hosting. La API devuelve los límites vigentes en los headers de la respuesta:
const scoped = nube.withBuyerIp("203.0.113.10")
await scoped.shipping.quote({ zipCode: "1414", variantId, quantity: 1 })createCatalogCacheFetch ofrece una cache acotada para las lecturas públicas del catálogo, usando la Cache API de Cloudflare o una implementación compatible. La tienda, el token, la versión de la API y la query forman parte del aislamiento de la cache. Las operaciones transaccionales nunca se cachean.
import { createClient } from "@notheadless/sdk"
import { createCatalogCacheFetch } from "@notheadless/sdk/server"
const runtime = { baseUrl, storeId, token }
const catalog = createClient({
...runtime,
fetch: createCatalogCacheFetch({ ...runtime, cache, ttlSeconds: 30 }),
fetchOptions: { cache: "no-store" },
})
// Usá un cliente aparte, sin cache, para validar el carrito y para el checkout.
const transactional = createClient({ ...runtime, fetchOptions: { cache: "no-store" } })El TTL por defecto es de 30 segundos, con un máximo de 60. Si omitís la cache o usás ttlSeconds: 0, los requests van siempre en vivo.
nube.stats // { requests, deduped, batched, cacheHits, retries }
nube.rateLimit // { limit: 1200, remaining: 1187, reset: 1790457756 } de la última respuesta
nube.clearCache()