Exports principales para los sitios React generados por Nimlio: cliente de API, hooks, runtime bilingüe, formato COP y componentes conectados. El SDK viene dentro de tu sitio de código en Nimlio; no se instala desde un registro público.
Puntos de partida para copiar y pegar con los hooks del storefront headless. Cada uno ya está exportado por el SDK; muestran el código y no lo ejecutan.
Soportado significa que el hook o la clase está exportado por @nimlio/sdk en esta versión y el ejemplo usa solo sus opciones y campos reales.
Crea el cliente y el provider
Soportado
createClient solo acepta una llave publicable que empiece por nk_pub_ y lanza un error con cualquier otra. baseUrl es opcional: si la omites, el cliente usa el valor de build o de la configuración del sitio y, si no hay ninguno, la ruta del mismo origen /api/v1. NimlioProvider crea su propio cliente de TanStack Query a menos que pases queryClient.
import { createClient } from "@nimlio/sdk"; import { NimlioProvider } from "@nimlio/sdk/react";
page empieza en 1 y pageSize va de 1 a 100 (por defecto 50); el SDK los convierte en offset y limit de la API. data.meta trae hasMore, nextCursor y limit. useProducts devuelve la primera página como un arreglo plano. Los precios son priceAmount en centavos de COP y pueden ser null.
import { useProductsPage } from "@nimlio/sdk/react"; import { money } from "@nimlio/runtime";
useProduct carga un producto por id y además emite el evento de analítica view_content una vez por id de producto. useProductReviews recibe las mismas opciones page y pageSize y devuelve las reseñas junto con meta con count y average.
import { useProduct, useProductReviews } from "@nimlio/sdk/react";
El storefront nunca envía precios. Cada item lleva solo un id, un type y una cantidad (más variantId cuando el producto tiene opciones); el servidor resuelve precios unitarios, descuentos, crédito de regalo y envío desde el catálogo publicado al cotizar y de nuevo al crear el pedido. Un cuerpo que incluya price, total, discount, currency o businessId se rechaza con 400 client_order_fields_not_allowed.
import { useRef, useState } from "react"; import { useQuoteOrder, useCreateOrder, useOrderStatus } from "@nimlio/sdk/react";
export function Checkout({ discountCode, shippingRateId }: { discountCode?: string; shippingRateId?: string }) { const quote = useQuoteOrder(); const create = useCreateOrder(); const [orderId, setOrderId] = useState(""); // Order creation requires an Idempotency-Key. The SDK sends one per call by default; // keeping one key per checkout attempt makes a re-submit replay the same order. // Mint a fresh key when the cart changes. Raw fetch must send the header itself. const attemptKey = useRef(crypto.randomUUID()); // An empty id keeps the query disabled; polling stops on a terminal status. const status = useOrderStatus(orderId, { poll: 3000 });
async function placeOrder() { // Selections only: ids, quantities and codes, never prices. const checkout = { items: [{ id: "product-id", type: "product" as const, quantity: 2 }], discountCode, shippingRateId, };
// 1. Ask the server what the cart costs. await quote.mutateAsync({ ...checkout, customerCity: "Medellín" }); // quote.data.subtotal, .discount and .shippingOptions come from the published catalog.
// 2. Create the order with the same selections. const order = await create.mutateAsync({ input: { ...checkout, customer: { name: "Ana Pérez", phone: "+573001112233" }, paymentMethod: "online", }, options: { idempotencyKey: attemptKey.current }, }); setOrderId(order.orderId); }
useOrderStatus consulta cada 3000 ms con poll: true o con el intervalo que pases, y se detiene solo en un estado terminal. Crear un pedido requiere Idempotency-Key: useCreateOrder envía una clave generada y el SDK reintenta los fallos transitorios con esa misma clave (useQuoteOrder nunca reintenta); pasa options.idempotencyKey, estable durante todo el intento de pago, para que un reenvío repita el mismo pedido. Con fetch directo envía el encabezado Idempotency-Key o recibirás 400 idempotency_key_required. Formatea los montos con money(), que espera centavos de COP.
Las peticiones fallidas lanzan NimlioApiError con status, code, reason, fieldErrors y requestId, y los hooks exponen el mismo error en su resultado. Las mutaciones nunca reintentan solas; las lecturas reintentan una vez por defecto con el query client del provider.
import { NimlioApiError } from "@nimlio/sdk";
try { await create.mutateAsync(input); } catch (e) { if (e instanceof NimlioApiError) { // e.status, e.code, e.reason, e.fieldErrors, e.requestId if (e.code === "invalid_input") showFieldErrors(e.fieldErrors); else if (e.code === "rate_limited") retryLater(); else report(e.requestId); } }