cauril/Docs

Node.js · @cauril/node

El cliente oficial para tu backend. Tipado de punta a punta, idempotente por diseño, con reintentos automáticos, auto-paginación y verificación de firmas de webhook. Cero dependencias en runtime.

Instalación

Requiere Node.js ≥ 20 (usa el fetch global). Funciona en ESM y CommonJS.

BASH
npm install @cauril/node

Inicialización

Pasá tu API key (sk_test_… o sk_live_…). El modo lo determina la key, no la URL. Nunca la pongas en el browser ni la subas al repo.

JS
import { Cauril } from "@cauril/node";

const cauril = new Cauril(process.env.CAURIL_API_KEY);

Opciones

JS
const cauril = new Cauril(process.env.CAURIL_API_KEY, {
  baseURL: "https://api.cauril.com", // default
  apiVersion: "2026-06-01",          // pinea el header Cauril-Version
  maxRetries: 2,                     // reintentos en red/429/5xx (hasta 3 intentos)
  timeout: 60_000,                   // timeout por intento, en ms
  retryInitialDelayMs: 500,          // primer backoff (duplica por intento, con jitter)
  // fetch,                          // inyectá un fetch propio (tests / runtimes sin global)
});
OpciónDefaultQué hace
baseURLhttps://api.cauril.comURL base de la API.
apiVersion2026-06-01Fija el header Cauril-Version.
maxRetries2Reintentos ante error de red, 429 y 5xx (respeta Retry-After).
timeout60000Timeout por intento, en ms.
retryInitialDelayMs500Primer paso de backoff; duplica por intento, con full jitter.
fetchglobalImplementación de fetch a inyectar.

Tu primer pago

Los métodos mutantes aceptan un segundo argumento con opciones por llamada. idempotencyKey es lo que hace que reintentar sea seguro: pasá un id estable (por ejemplo el id de tu orden) y la operación corre a lo sumo una vez.

JS
const payment = await cauril.payments.create(
  {
    amount: 5000,            // entero en unidad mínima → USD 50.00
    currency: "USD",
    payment_method: { type: "card", token: "pm_card_visa" },
  },
  { idempotencyKey: order.id },
);

console.log(payment.id, payment.status); // pay_…  "processing"
Si omitís idempotencyKey, el SDK genera uno fresco por llamada (un randomUUID). Eso te cubre de un reintento interno de red, pero no de que tu propio código llame dos veces. Para eso pasá una key estable. Ver Idempotencia.

Opciones por llamada

Todo método acepta un último argumento RequestOptions:

CampoQué hace
idempotencyKeySobreescribe la key autogenerada (solo mutaciones).
expandRelaciones a inlinear, ej. ["attempts", "customer"].
signalAbortSignal para cancelar la request.

Recursos

Cada recurso es una propiedad del cliente. Los nombres de campo son los mismos que la API (snake_case), sin capa de traducción sorpresa.

RecursoMétodos
paymentscreate, retrieve, list, listAutoPaging, refund
refundsretrieve
customerscreate, retrieve, list, listAutoPaging
providerConnectionscreate, list
routingRulescreate, list, update, del
webhookEndpointscreate, list
webhookDeliverieslist, listAutoPaging, retrieve, resend
eventslist, listAutoPaging
analyticssummary
checkout.sessionscreate, retrieve, cancel
planscreate, retrieve, list, listAutoPaging
subscriptionscreate, retrieve, list, listAutoPaging, update, cancel
invoicesretrieve, list, listAutoPaging
webhooksconstructEvent, verifySignature, sign

Paginación automática

Las listas devuelven una página (data + has_more + next_cursor). Para recorrer todo sin manejar el cursor a mano, usá listAutoPaging, que es un async-iterator y va trayendo páginas por demanda:

JS
for await (const payment of cauril.payments.listAutoPaging({ status: "succeeded" })) {
  console.log(payment.id);
}

Verificar webhooks

cauril.webhooks no necesita API key: usa el secreto del endpoint (whsec_…). Pasá el cuerpo crudo de la request (nunca un objeto re-serializado) o la firma no va a coincidir. Lanza CaurilSignatureVerificationError ante cualquier fallo (firma faltante, malformada, vencida o que no coincide).

JS
// Ejemplo con Express (body crudo). El secreto se devuelve UNA sola vez al crear el endpoint.
app.post("/webhooks/cauril", express.raw({ type: "*/*" }), (req, res) => {
  try {
    const event = cauril.webhooks.constructEvent(
      req.body,                          // Buffer/string crudo
      req.headers["cauril-signature"],
      process.env.CAURIL_WEBHOOK_SECRET, // whsec_…
    );
    if (event.type === "payment.succeeded") fulfill(event.data);
    res.sendStatus(200);
  } catch {
    res.sendStatus(400); // firma inválida → no confíes en el payload
  }
});
verifySignature(...) hace lo mismo sin parsear, y sign(rawBody, secret) produce un header válido, práctico para testear tu propio handler. Detalle del formato de la firma en Webhooks.

Errores

Todo lo que lanza el SDK extiende CaurilError, así un solo catch te cubre. Usá CaurilError.is(e) o instanceof para distinguir el tipo.

JS
import { CaurilError, CaurilAPIError, CaurilConnectionError } from "@cauril/node";

try {
  await cauril.payments.create(params, { idempotencyKey: order.id });
} catch (e) {
  if (e instanceof CaurilAPIError) {
    // respuesta estructurada de la API (4xx/5xx)
    console.error(e.statusCode, e.type, e.code, e.message, e.requestId);
    if (e.isProviderError) console.error(e.providerError); // un PSP rechazó
  } else if (e instanceof CaurilConnectionError) {
    // no se pudo llegar a la API (DNS/TCP/TLS, timeout o abort)
  } else if (CaurilError.is(e)) {
    // CaurilSignatureVerificationError u otro del SDK
  }
}
ClaseCuándo
CaurilAPIErrorLa API devolvió { error } (4xx/5xx). Trae statusCode, type, code, param, requestId, providerError, docUrl.
CaurilConnectionErrorNo se pudo llegar a la API: fallo de red, timeout o request abortada.
CaurilSignatureVerificationErrorUna firma de webhook no verificó.
CaurilErrorClase base abstracta de todas las anteriores.
El SDK reintenta automáticamente errores de red, 429 y 5xx con backoff y jitter. Como toda mutación lleva una Idempotency-Key, reintentar es seguro: nunca cobra dos veces (regla dura #4).

Tipos

El paquete exporta todos los tipos de la wire (Payment, Refund, CheckoutSession, CaurilEvent, PaymentStatus, …) y los tipos de parámetros de cada método (CreatePaymentParams, ListPaymentsParams, …). Importalos directo de @cauril/node.