@folyo/sdk
v0.1.1
Published
SDK oficial de Folyo para facturación electrónica chilena (DTE + SII). Del código al SII.
Maintainers
Readme
@folyo/sdk
SDK oficial de Folyo para facturación electrónica chilena (DTE + SII). Del código al SII. Sin escalas.
- TypeScript nativo, tipos derivados del OpenAPI oficial de la API.
- ESM + CJS, sin dependencias de runtime (usa el
fetchglobal de Node 18+). - Manejo de errores tipado, reintentos con backoff y emisión asíncrona con polling.
- Redacción automática de credenciales: el cliente y los errores nunca exponen
tu API key, tu JWT ni material sensible (clave SII,
.pfx, CAF, secretos).
Instalación
pnpm add @folyo/sdk
# o
npm install @folyo/sdk
# o
yarn add @folyo/sdk
# o
bun add @folyo/sdkRequiere Node.js >= 18.
Quickstart: emitir una factura electrónica (DTE 33)
import { Folyo } from "@folyo/sdk";
const folyo = new Folyo({ apiKey: process.env.FOLYO_API_KEY! });
// Emisión asíncrona + espera del resultado por polling.
const job = await folyo.dte.emitirYEsperar(
{
tipo_dte: 33, // Factura Electrónica
receptor: {
rut: "12.345.678-9",
razon_social: "Cliente SpA",
giro: "Comercio",
direccion: "Av. Siempre Viva 123",
comuna: "Santiago",
},
detalle: [
{
nombre: "Servicio de consultoría",
cantidad: 1,
precio: 100000,
monto: 100000, // requerido
},
],
},
{ idempotencyKey: crypto.randomUUID() },
);
console.log(job.estado); // "completed"
console.log(job.result?.track_id, job.folio);Emisión cruda (solo encolar) + polling manual
const encolada = await folyo.dte.emitir(body, { idempotencyKey: crypto.randomUUID() });
console.log(encolada.job_id, encolada.folio);
// más tarde, o desde un webhook `dte.emitido`:
const job = await folyo.dte.getEmision(encolada.job_id!);Autenticación
Dos esquemas, mutuamente excluyentes:
// API key (recomendado server-side; no expira; fija tenant y empresa).
const folyo = new Folyo({ apiKey: "tu-api-key" });
// JWT (sesión de usuario).
const folyo = new Folyo({ token: "access-token-jwt" });El SDK envía la API key tal cual en el header
X-API-Key(no asume prefijo). Con API key la empresa queda fijada por la key.
Configuración
const folyo = new Folyo({
apiKey: process.env.FOLYO_API_KEY!,
baseURL: "https://api.folyo.cl", // por defecto; usa http://localhost:8080 en local
timeoutMs: 30000, // timeout por request
maxRetries: 2, // reintentos ante 429 / 503 idempotentes
userAgent: "mi-app/1.0", // sufijo opcional del User-Agent
// fetch: customFetch, // inyectable (tests, proxies)
});Recursos disponibles
| Namespace | Métodos |
|---|---|
| folyo.dte | emitir, emitirYEsperar, getEmision, listDocumentos, downloadXml, downloadPdf, regeneratePdf, getEstado, getEstadoEnvio, getEmitidos, getRecibidos, getContribuyente, getSituacionTributaria |
| folyo.folios | info, cargarCaf, solicitar |
| folyo.rcv | periodos, get, sync, resumenIva |
| folyo.clientes | list, upsert, importar, buscarPorRut, update, delete |
| folyo.empresa | list, seleccionar |
| folyo.acuse | registrar, pendientes, estado |
| folyo.rcof | enviar, resumen |
| folyo.webhooks | list, create, update, delete |
| folyo.apiKeys | list, create, delete |
Algunos endpoints (clientes, RCV, plantillas, listado de documentos) requieren "panel operativo" y pueden devolver
403en planes solo-API.
Idempotencia
Para dte.emitir / dte.emitirYEsperar, pasa una idempotencyKey (8-64 chars
[a-zA-Z0-9_-], UUID v4 recomendado). Un reenvío con la misma key y el mismo
cuerpo devuelve el mismo job_id sin quemar un folio nuevo. Además habilita
el reintento seguro ante 503 del lado del SDK.
const key = crypto.randomUUID();
await folyo.dte.emitir(body, { idempotencyKey: key });
// reintento seguro con la misma key → mismo job_id
await folyo.dte.emitir(body, { idempotencyKey: key });Una misma key con un cuerpo distinto produce 409 IDEMPOTENCY_KEY_CONFLICT
(FolyoValidationError).
Manejo de errores
Todos los errores heredan de FolyoError y exponen status, code y requestId
(nunca el cuerpo de la request).
import {
FolyoError,
FolyoAuthError, // 401
FolyoRateLimitError, // 429 (.retryAfter en segundos)
FolyoQuotaError, // 402 / 403 (PLAN_LIMIT, PAYMENT_REQUIRED, ...)
FolyoValidationError, // 400 / 409 / 422
FolyoConnectionError, // red / timeout
FolyoSiiUnavailableError, // 502 / 503 / 504 (.retryAfter)
} from "@folyo/sdk";
try {
await folyo.dte.emitir(body, { idempotencyKey: crypto.randomUUID() });
} catch (err) {
if (err instanceof FolyoRateLimitError) {
console.warn(`Rate limit; reintenta en ${err.retryAfter}s`);
} else if (err instanceof FolyoQuotaError) {
console.error(`Cuota/plan: ${err.code}`); // PLAN_LIMIT, PAYMENT_REQUIRED...
} else if (err instanceof FolyoSiiUnavailableError) {
console.error("El SII no está disponible, reintenta más tarde.");
} else if (err instanceof FolyoError) {
console.error(`${err.code ?? err.status}: ${err.message} (req ${err.requestId})`);
}
}Reintentos automáticos
El SDK reintenta con backoff exponencial (respetando Retry-After) ante 429 y
503 solo en operaciones idempotentes: cualquier GET, y POST /dte/emitir
solo si entregaste una Idempotency-Key. Ajusta con maxRetries.
Seguridad
- El cliente y todos los objetos de error redactan la credencial a
***al serializar (JSON.stringify) o al imprimirse (util.inspect). - Los errores nunca incluyen el cuerpo de la request (que puede traer la clave
del SII o un
.pfx). - Sin telemetría ni logging por defecto.
Licencia
MIT — Folyo Technologies SpA.
