neofolio

API de Neofolio

Con esta API tu sistema pide un documento tributario y Neofolio se encarga de emitirlo. Todo viaja en JSON por HTTPS.

Dirección base

https://neofolio.app/api/v2
  1. Registra tu empresa en el ambiente de pruebas desde el panel.
  2. Copia la llave de pruebas que te entrega el panel.
  3. Envía tu primer documento con POST /documents.

Ambientes

La llave decide el ambiente. No hay que cambiar la dirección.

AmbienteLlaveQué hace
Pruebasnf_test_…Valida el documento igual que en producción y le asigna un folio ficticio. Nunca contacta al SII. El PDF sale marcado como documento de prueba.
Producciónnf_live_…Emite el documento real en el SII. Se habilita empresa por empresa, a pedido desde el panel.
Hoy la API pública atiende el ambiente de pruebas. Una llave de producción recibe 503 PRODUCTION_DISABLED hasta que su empresa esté habilitada.

Autenticación

Envía tu llave en cada petición. Guárdala en tu servidor: no la pongas en una app ni en una página web.

Authorization: Bearer nf_test_xxxxxxxxxxxxxxxx
GET/context

Devuelve la organización, el ambiente y los permisos de la llave. Sirve para comprobar que está bien configurada.

Emitir un documento

POST/documents

La emisión es asíncrona: la respuesta es 202 con el documento en estado processing. El resultado llega por webhook o consultando el documento.

El encabezado Idempotency-Key es obligatorio. Si repites la misma clave con el mismo contenido, recibes el documento ya creado y no se emite dos veces. Usa el identificador de la venta en tu sistema.

curl -X POST https://neofolio.app/api/v2/documents \
  -H "Authorization: Bearer nf_test_xxxxxxxx" \
  -H "Idempotency-Key: venta-1042" \
  -H "Content-Type: application/json" \
  -d '{
  "dte": {
    "encabezado": {
      "idDoc": { "tipoDte": 39, "fchEmis": "2026-11-15", "medioPago": "TD" },
      "emisor": {
        "rutEmisor": "76123456-0",
        "rznSoc": "MI EMPRESA SPA",
        "giroEmis": "VENTA AL POR MENOR",
        "acteco": [477399],
        "dirOrigen": "AV EJEMPLO 123",
        "cmnaOrigen": "SANTIAGO"
      },
      "receptor": {},
      "totales": { "mntNeto": 10000, "iva": 1900, "mntTotal": 11900 }
    },
    "detalle": [
      { "nmbItem": "Servicio", "qtyItem": 1, "prcItem": 11900, "montoItem": 11900 }
    ]
  }
}'

Tipos de documento

tipoDteDocumentoTener en cuenta
39 / 41Boleta afecta / exentaEl detalle va con IVA incluido. El receptor es opcional.
33 / 34Factura afecta / exentaEl detalle va en neto. Receptor completo: RUT, razón social, giro, dirección y comuna.
61 / 56Nota de crédito / débitoExige referencia con codRef: 1 anula, 2 corrige texto, 3 corrige montos.
52Guía de despachoExige idDoc.indTraslado entre 1 y 9.

Reglas de validación

  • tipoDte y los montos son números, no texto. Los montos son enteros en pesos.
  • Las fechas van como AAAA-MM-DD.
  • El RUT del emisor debe ser el de una empresa registrada en tu organización.
  • Cada línea: montoItem = qtyItem × prcItem.
  • iva = 19 % del neto, y neto + IVA + exento = total.
  • Medios de pago en boleta: EF efectivo, TD débito, TC crédito, PE pago electrónico, CH cheque, OT otro.

Consultar documentos

GET/documents/{id}

Devuelve el documento con su estado, folio y enlace al PDF.

{
  "data": {
    "id": "2a8877fb-ed0b-46d3-911a-20a714258984",
    "status": "accepted",
    "folio": 1,
    "documentTypeCode": 39,
    "issuedAt": "2026-11-15",
    "environment": "sandbox",
    "livemode": false,
    "pdfUrl": "https://…/pdf/…",
    "amounts": { "total": 11900 },
    "error": null
  }
}
statusSignifica
processingRecibido, en proceso de emisión.
acceptedEmitido. Ya tiene folio y PDF.
rejectedNo se emitió. El motivo viene en error.
failedFalló el proceso. Se puede reintentar con una clave de idempotencia nueva.
GET/documents?limit=25

Lista los documentos más recientes de la organización. limit va de 1 a 100.

GET/documents/{id}/pdf

Descarga el PDF. Responde 409 NOT_READY si el documento aún no tiene folio.

Empresas

GET/companies

Lista las empresas emisoras de la organización, con su estado de conexión al SII y los tipos de documento que pueden emitir.

Webhooks

Neofolio avisa a tu servidor cada vez que un documento cambia de estado, con el evento document.updated.

POST/webhooks
{ "url": "https://tusistema.cl/neofolio/aviso" }

La dirección debe ser https, pública y en el puerto 443. La respuesta trae el secreto de firma una sola vez.

GET/webhooks
DELETE/webhooks/{id}

Verificar la firma

Cada aviso trae dos encabezados. La firma es el HMAC-SHA256, en hexadecimal, del texto <timestamp>.<cuerpo> usando tu secreto.

x-emitto-timestamp: 1794772000
x-emitto-signature: 5f2c…
// Node.js
const crypto = require("crypto");
function firmaValida(secreto, timestamp, cuerpoCrudo, firma) {
  const esperada = crypto.createHmac("sha256", secreto)
    .update(timestamp + "." + cuerpoCrudo).digest("hex");
  return esperada.length === firma.length &&
    crypto.timingSafeEqual(Buffer.from(esperada), Buffer.from(firma));
}

Responde con un código 2xx en menos de 10 segundos.

Errores

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "El documento no paso la validacion",
    "details": [ { "field": "encabezado.totales.iva", "issue": "IVA no cuadra: se esperaba 1900" } ]
  }
}
HTTPcodeQué hacer
400IDEMPOTENCY_KEY_REQUIRED, INVALID_JSONCorrige la petición.
401UNAUTHORIZEDRevisa la llave.
403FORBIDDENLa llave no tiene ese permiso.
404NOT_FOUNDEl recurso no existe en tu organización.
409IDEMPOTENCY_CONFLICT, NOT_READYEsa clave ya se usó con otro contenido, o el documento aún no está listo.
413PAYLOAD_TOO_LARGEReduce el tamaño del documento.
422VALIDATION_ERROR, LIMIT_REACHEDLee details y corrige los campos.
503PRODUCTION_DISABLEDLa empresa aún no está habilitada en producción.

Límites

  • Tamaño máximo del documento: 200 KB.
  • Hasta 60 líneas de detalle y 3 referencias por documento.
  • Hasta 5 webhooks y 5 llaves activas por organización.