Skip to navigation

Quickstart (5 min)

Emite tu primera factura en PILOTO. Pre-requisitos: API corriendo (GET /v1/health → {"status":"ok"}), una X-API-Key válida y un punto de venta con CUIS/CUFD vigente. Sin tenant todavía: Onboarding.

Cada POST de creación inicia otra factura (no hay Idempotency-Key). Guarda siempre id + cuf y concilia por ID. Nunca reintentes un emit a ciegas.

1

Smoke test (sin auth)

import { Supay } from "@supay/sdk";
// Cliente con la key del tenant
const supay = new Supay({
apiKey: process.env.SUPAY_API_KEY!,
baseUrl: "http://localhost:8081",
});
// Sin auth: solo verifica que la API responde
await supay.system.healthCheck(); // { status: "ok" }
2

Validar sin crear nada (no toca SIAT)

// Vista previa: valida el payload, no persiste nada
const preview = await supay.invoices.preview({
point_of_sale_id: "5226da47-74da-4b27-a26d-892c62fa6d26",
// Receptor: snapshot completo (customer.id está prohibido)
customer: {
document_type: "ci",
document_number: "1234567",
name: "Ada Lovelace",
},
// Líneas: sku + snapshot fiscal obligatorio por línea
items: [
{
sku: "PLAN-PRO",
description: "Plan profesional",
codigo_producto_sin: 5113100, // del catálogo sincronizado
unidad_medida: 58,
quantity: 1,
price: 150,
},
],
// Operación: venta local, sector 1 (auto lo resuelve)
sector: "auto",
});
console.assert(preview.codigo_documento_sector === 1);

sku solo no alcanza: description, codigo_producto_sin y unidad_medida son obligatorios (snapshot fiscal). Tabla completa en Emitir factura.

3

Crear + emitir (ruta estrella)

// Mismo payload del paso 2: crea y emite en un request
const invoice = await supay.invoices.emit(payload);
// invoice.status: ACCEPTED | OBSERVED | OFFLINE | REJECTED
// Guarda siempre: invoice.id + invoice.cuf

Qué hacer con cada estado

statusSignificadoAcción
ACCEPTEDAceptada por el SIATGuardar id + cuf. Descargar XML/PDF.
OBSERVEDAceptada con observacionesLeer siat_mensajes, no re-emitir.
OFFLINETimeout/caída SIAT, firmada local (codigoEmision=2)Guardar XML + contingency_event_id. Ver Contingencia.
REJECTEDRechazada por el SIATCorregir y crear una factura nueva (no se reencola).

Ciclo completo

// Leer y re-verificar contra el SIAT
const inv = await supay.invoices.get({ id });
const reverificado = await supay.invoices.getSiatStatus({ id });
// Artefactos fiscales
const xml = await supay.invoices.downloadXml({ id }); // XML firmado
const pdf = await supay.invoices.downloadPdf({ id }); // on-demand si hay CUF
// Anular con motivo del catálogo SIAT
await supay.invoices.annul({ id, codigo_motivo: 1 });