SDKs
Folyo tiene SDK oficiales para TypeScript/JavaScript y Python. Traen los tipos derivados del OpenAPI de la API, reintentos con backoff, idempotencia, el patrón de emisión asíncrona con polling resuelto por ti, y redacción automática de credenciales: nunca exponen tu API key, tu JWT ni datos sensibles en logs ni en errores. Integras en una tarde, sin escribir HTTP a mano.
TypeScript / JavaScript
Node 18+, ESM y CJS, sin dependencias de runtime. Paquete: @folyo/sdk.
pnpm add @folyo/sdk
# o: npm install @folyo/sdk · yarn add @folyo/sdk · bun add @folyo/sdk
Emitir una Factura Electrónica (DTE 33) y esperar el resultado:
import { Folyo } from "@folyo/sdk";
const folyo = new Folyo({ apiKey: process.env.FOLYO_API_KEY! });
// Emisión asíncrona con polling del resultado.
const job = await folyo.dte.emitirYEsperar(
{
tipo_dte: 33,
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 },
],
},
{ idempotencyKey: crypto.randomUUID() },
);
console.log(job.estado, job.folio, job.result?.track_id);
Python
Python 3.9+, única dependencia httpx. Paquete: folyo.
pip install folyo
import uuid
from folyo import Folyo, DTERequest, Receptor, DetalleLinea
with Folyo(api_key="<tu-api-key>") as folyo:
req = DTERequest(
tipo_dte=33,
receptor=Receptor(rut="12.345.678-9", razon_social="Cliente SpA", giro="Comercio"),
detalle=[DetalleLinea(nombre="Servicio de consultoría", monto=100000)],
)
job = folyo.dte.emitir_y_esperar(req, idempotency_key=str(uuid.uuid4()))
if job.estado == "completed" and job.result is not None:
print("Folio:", job.result.folio)
print("Track ID:", job.result.track_id)
El cliente de Python también funciona como context manager y cierra la conexión HTTP al salir.
Autenticación
Ambos SDK aceptan dos esquemas, mutuamente excluyentes:
- API Key (header
X-API-Key): recomendada para integraciones server to server, no expira y fija el tenant y la empresa. - JWT (
Authorization: Bearer): para sesiones de usuario.
Ver Autenticación.
Errores e idempotencia
Todos los errores heredan de FolyoError y exponen status, code y requestId, nunca el cuerpo de la request. Hay subtipos tipados para reaccionar distinto según el caso: FolyoRateLimitError (429, con retryAfter), FolyoQuotaError (402/403 por plan o pago), FolyoValidationError (400/409/422), FolyoAuthError (401) y FolyoSiiUnavailableError (502/503/504).
Pasa una idempotencyKey al emitir (UUID v4 recomendado) para reintentar de forma segura sin duplicar folios: un reenvío con la misma key y el mismo cuerpo devuelve el mismo job_id. Ver Manejo de errores.
Cualquier otro lenguaje
La API es REST estándar, así que la consumes desde cualquier stack con un cliente HTTP. Cada endpoint del API Reference trae ejemplos listos para copiar en cURL, JavaScript, Python, Go y PHP. Emitir un DTE:
const response = await fetch("https://api.folyo.cl/v1/dte/emitir", {
method: "POST",
headers: {
"Authorization": "Bearer <ACCESS_TOKEN>",
"X-Empresa-Id": "<valor>",
"X-SII-Ambiente": "<valor>",
"Idempotency-Key": "<valor>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"tipo_dte": 33,
"receptor": {
"rut": "12.345.678-9",
"razon_social": "Cliente SpA",
"giro": "Comercio",
"direccion": "Calle 123",
"comuna": "Santiago"
},
"detalle": [
{
"nombre": "Servicio de desarrollo",
"cantidad": 1,
"precio": 100000,
"monto": 100000,
"exento": false
}
],
"descuentos_globales": [
{
"tipo_movimiento": "D",
"glosa": "Descuento por volumen",
"tipo_valor": "%",
"valor": 10
}
],
"referencia": [
{
"tipo_doc_ref": 801,
"folio_ref": "OC-2026-1487",
"fecha_ref": "2026-07-20",
"razon_ref": "Orden de compra del cliente"
}
]
}),
});
const data = await response.json();
console.log(data);