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.

bash
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:

typescript
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.

bash
pip install folyo
python
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:

javascript
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);