@wepos/sdk
v1.1.0
Published
SDK oficial de WePOS para integradores — facturación electrónica Hacienda CR v4.4. Emite FE/TE/NC/ND/FEE, consulta catálogo, clientes e inventario.
Maintainers
Readme
@wepos/sdk
SDK oficial de WePOS — facturación electrónica Hacienda Costa Rica v4.4 para integradores.
TypeScript/Node · cero dependencias en runtime · ESM + CJS · tipos incluidos
Tabla de contenido
- ¿Qué resuelve?
- Características
- Requisitos
- Obtener una API key
- Instalación
- Inicio rápido
- Ambientes
- Configuración
- Cobertura de la API
- Recursos
- Idempotencia
- Manejo de errores
- Reintentos y timeouts
- TypeScript
- Roadmap
- Versionado
- Soporte
- Licencia
¿Qué resuelve?
Conecta cualquier sistema de terceros (ecommerce, ERP, app a medida, backend) con WePOS para emitir comprobantes electrónicos ante Hacienda Costa Rica y consultar catálogo, clientes e inventario — sin lidiar con XML, firmas digitales, claves numéricas ni el ciclo asíncrono de Hacienda. Tú llamas un método tipado; el SDK se encarga del resto.
const invoice = await wepos.invoices.issueAndWait({
documentType: 'FE',
customer: { idType: 'CEDULA_JURIDICA', idNumber: '3101123456', name: 'Cliente S.A.' },
lines: [{ description: 'Consultoría', quantity: 1, unitPrice: 25000, cabysCode: '8314300000000' }],
})
invoice.haciendaStatus // 'aceptado'Características (v1.0)
- ✅ Emisión completa: Factura (FE), Tiquete (TE), Nota de Crédito (NC), Nota de Débito (ND) y Factura de Exportación (FEE).
- ✅
issueAndWait— emite y espera (poll) la respuesta de Hacienda, encapsulando el ciclo fiscal asíncrono. - ✅ Ambientes estilo Stripe — el prefijo de la key (
wpk_test_/wpk_live_) define Sandbox vs Producción; datos aislados. - ✅ Idempotencia —
Idempotency-Keypara que un reintento nunca duplique un comprobante. - ✅ Reintentos automáticos con backoff exponencial ante
429/5xx/ errores de red. - ✅ Errores tipados con
code,statusyrequestId(rastreables en soporte). - ✅ Catálogo, clientes, inventario y sucursales.
- ✅ Referencia Hacienda — validar CABYS, contribuyentes y exoneraciones.
- ✅ 100% tipado, ESM + CJS, cero dependencias en runtime.
Requisitos
| Requisito | Versión |
| -------------- | ---------------------------------------------------- |
| Node.js | ≥ 18 (usa fetch nativo) |
| Runtimes | Node, Bun, Deno y entornos edge con fetch |
| Una API key | de WePOS — ver abajo |
Obtener una API key
La API key se solicita y administra desde el panel de WePOS:
pos.wecodecr.com → Configuración → API Keys → Crear API key
Al crearla eliges sus scopes (permisos mínimos) y su ambiente:
wpk_test_…→ Sandbox (pruebas, sin validez fiscal).wpk_live_…→ Producción (comprobantes con validez fiscal).
Guarda la key de forma segura (se muestra una sola vez) y nunca la expongas en el cliente/navegador — úsala solo desde tu backend.
Instalación
npm install @wepos/sdk
# pnpm add @wepos/sdk · yarn add @wepos/sdk · bun add @wepos/sdkInicio rápido
import { WeposClient } from '@wepos/sdk'
const wepos = new WeposClient({
apiKey: process.env.WEPOS_API_KEY!, // wpk_test_… (Sandbox) o wpk_live_… (Producción)
})
const invoice = await wepos.invoices.issueAndWait({
documentType: 'FE',
customer: {
idType: 'CEDULA_JURIDICA',
idNumber: '3101123456',
name: 'Cliente S.A.',
email: '[email protected]',
},
lines: [
{ description: 'Consultoría', quantity: 1, unitPrice: 25000, cabysCode: '8314300000000' },
],
})
console.log(invoice.haciendaStatus) // 'aceptado' | 'rechazado'
console.log(invoice.claveNumerica)Ambientes (estilo Stripe)
El ambiente lo determina el prefijo de la API key — no se configura aparte:
| Key | Ambiente | Validez fiscal |
| -------------- | ---------- | -------------- |
| wpk_test_... | Sandbox | No (pruebas) |
| wpk_live_... | Producción | Sí |
Los datos están aislados por ambiente: una key de sandbox nunca ve comprobantes de producción.
Configuración
new WeposClient({
apiKey: 'wpk_live_...',
baseUrl: 'https://pos.wecodecr.com', // default
timeoutMs: 30_000, // default
maxRetries: 2, // reintenta 429 / 5xx / red, con backoff
})Cobertura de la API
| Recurso | Estado | Scope requerido |
| ------------------------------- | :----: | ---------------------- |
| Facturas (FE/TE/NC/ND/FEE) | ✅ | invoices:read/write |
| Clientes | ✅ | customers:read/write |
| Productos | ✅ | products:read |
| Inventario | ✅ | inventory:read |
| Sucursales | ✅ | branches:read |
| Referencia (CABYS, cédulas…) | ✅ | reference:read |
| Webhooks (verificación) | 🔜 | (v1.1) |
| Ventas POS / sesiones de caja | 🔜 | (v1.3) |
| Cuentas por cobrar / pagar | 🔜 | (v1.3) |
| Reportes y exportación contable | 🔜 | (v1.3) |
Recursos
Facturas — wepos.invoices
await wepos.invoices.create(input, { idempotencyKey }) // emite y retorna de inmediato
await wepos.invoices.issueAndWait(input, { timeoutMs, pollIntervalMs }) // emite y espera a Hacienda
await wepos.invoices.get(id) // estado + detalle
await wepos.invoices.list({ limit, documentType })
await wepos.invoices.getXml(id) // XML firmado + respuesta Hacienda
await wepos.invoices.createCreditNote(id, { reason, fullReversal })
await wepos.invoices.createDebitNote(id, { reason, referenceCode, lines })
await wepos.invoices.export(input) // Factura de Exportación (FEE)Clientes — wepos.customers
await wepos.customers.create({ idType, idNumber, name, email })
await wepos.customers.list({ search, limit })Catálogo e inventario
await wepos.products.list({ search, limit })
await wepos.inventory.list({ productId, warehouseId, search, limit })
await wepos.branches.list() // para obtener el branchId a usar en emisionesReferencia Hacienda — wepos.reference
await wepos.reference.getCabys('8314300000000') // valida código, retorna tarifa IVA
await wepos.reference.searchCabys('consultoría') // busca por texto
await wepos.reference.getTaxpayer('3101123456') // valida contribuyente
await wepos.reference.getExoneration('AUT-123') // consulta exoneración DGTActividad económica (emisor y receptor)
Un contribuyente puede tener varias actividades registradas en Hacienda. Puedes:
- Elegir con cuál actividad emite el emisor →
activityCode(debe ser una actividad registrada del emisor; si se omite, usa la principal). - Enviar la actividad del comprador →
receptorActivityCode(opcional, v4.4).
Combínalo con reference.getTaxpayer() para que el comprador elija entre sus actividades:
// 1. Traer las actividades del comprador desde Hacienda
const tp = await wepos.reference.getTaxpayer('3101003937')
// tp.actividades → [{ codigo: '4730.0', descripcion: '…', tipo: 'P' }, …]
// 2. Emitir indicando la actividad del receptor (y opcionalmente la del emisor)
await wepos.invoices.create({
documentType: 'FE',
customer: { id: customerId },
activityCode: '4610.0', // actividad del EMISOR (si tiene varias)
receptorActivityCode: tp.actividades[0].codigo, // actividad del RECEPTOR
lines: [/* … */],
})Idempotencia
Pasa una idempotencyKey al emitir: un reintento con la misma key no duplica el comprobante.
await wepos.invoices.create(input, { idempotencyKey: 'orden-4821' })Manejo de errores
import { WeposApiError, WeposTimeoutError } from '@wepos/sdk'
try {
await wepos.invoices.create(input)
} catch (err) {
if (err instanceof WeposApiError) {
console.error(err.code, err.status, err.message, err.requestId)
if (err.isRateLimit) { /* 429 */ }
if (err.isAuth) { /* 401 / 403 — revisar key/scopes */ }
} else if (err instanceof WeposTimeoutError) {
// Hacienda tardó; consulta el estado más tarde con invoices.get(err.invoiceId)
}
}Todos los errores exponen el code estable de WePOS, el status HTTP y el requestId.
Reintentos y timeouts
- El SDK reintenta automáticamente ante
429,5xxy errores de red, con backoff exponencial y respeto del headerRetry-After. Configurable conmaxRetries. - Las escrituras solo deben reintentarse con una
idempotencyKey(lo hace por tiissueAndWait). - Cada request tiene un
timeoutMs(default 30s).issueAndWaittiene su propiotimeoutMspara la espera de Hacienda.
TypeScript
El SDK incluye tipos completos. Los de la superficie pública están curados a mano para la mejor DX,
pero reflejan el OpenAPI publicado en /api/v1/openapi. Para cruzarlos contra el contrato real o
expandir a nuevos endpoints, regenera desde el spec vivo:
WEPOS_BASE_URL=https://pos.wecodecr.com npm run gen:typesRoadmap
El orden refleja prioridad por valor para integradores. Sugerencias en [email protected].
✅ v1.0 — Núcleo de emisión (actual)
Emisión FE/TE/NC/ND/FEE, issueAndWait, clientes, catálogo, inventario, sucursales y referencia
Hacienda. DX: idempotencia, reintentos, errores tipados, ESM+CJS, tipos completos.
🔜 v1.1 — Webhooks y eventos
wepos.webhooks.verify(rawBody, signatureHeader, secret)— verificación de firma HMAC estilo Stripe (x-wepos-signature: t=…,v1=…), con tolerancia anti-replay.- Tipos de eventos fiscales (
document.accepted,document.rejected,document.error, …). - Handlers listos para Next.js y Express.
🔜 v1.2 — Listados y paginación
- Auto-paginación / async iterators (
for await (const inv of wepos.invoices.iterate())). - Filtros adicionales: rango de fechas, estado de Hacienda, sucursal, cliente.
🔜 v1.3 — Más recursos de negocio
- Ventas POS y sesiones de caja, devoluciones e impresión.
- Cuentas por cobrar / pagar (pagos, estados de cuenta, aging).
- Reportes (ventas, impuestos, reporte Z, libros, exportación contable).
- Catálogo avanzado (listas de precios, promociones, combos) y compras (procurement).
🔭 v2.0 — Apps móviles y desktop
- Auth de dispositivos (
login/refresh) con refresco automático del token. - Change-feed / sync con cursores para apps offline-first.
- Subida de imágenes (logo, productos) y modo contingencia.
🌎 Futuro
- SDKs de PHP y Python generados desde el OpenAPI.
- CLI
wepospara emitir/consultar desde terminal y CI. - Modo
mockpara tests de integradores sin tocar Hacienda.
Versionado
Seguimos SemVer: los cambios incompatibles solo ocurren en versiones major. Consulta el historial en la pestaña de versiones en npm.
Soporte
- 📦 npm: https://www.npmjs.com/package/@wepos/sdk
- 🌐 Plataforma: https://pos.wecodecr.com
- ✉️ [email protected]
Licencia
MIT © WeCode CR
