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
- Registra tu empresa en el ambiente de pruebas desde el panel.
- Copia la llave de pruebas que te entrega el panel.
- Envía tu primer documento con
POST /documents.
Ambientes
La llave decide el ambiente. No hay que cambiar la dirección.
| Ambiente | Llave | Qué hace |
|---|---|---|
| Pruebas | nf_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ón | nf_live_… | Emite el documento real en el SII. Se habilita empresa por empresa, a pedido desde el panel. |
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
/contextDevuelve la organización, el ambiente y los permisos de la llave. Sirve para comprobar que está bien configurada.
Emitir un documento
/documentsLa 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
tipoDte | Documento | Tener en cuenta |
|---|---|---|
| 39 / 41 | Boleta afecta / exenta | El detalle va con IVA incluido. El receptor es opcional. |
| 33 / 34 | Factura afecta / exenta | El detalle va en neto. Receptor completo: RUT, razón social, giro, dirección y comuna. |
| 61 / 56 | Nota de crédito / débito | Exige referencia con codRef: 1 anula, 2 corrige texto, 3 corrige montos. |
| 52 | Guía de despacho | Exige idDoc.indTraslado entre 1 y 9. |
Reglas de validación
tipoDtey 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:
EFefectivo,TDdébito,TCcrédito,PEpago electrónico,CHcheque,OTotro.
Consultar documentos
/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
}
}
status | Significa |
|---|---|
processing | Recibido, en proceso de emisión. |
accepted | Emitido. Ya tiene folio y PDF. |
rejected | No se emitió. El motivo viene en error. |
failed | Falló el proceso. Se puede reintentar con una clave de idempotencia nueva. |
/documents?limit=25Lista los documentos más recientes de la organización. limit va de 1 a 100.
/documents/{id}/pdfDescarga el PDF. Responde 409 NOT_READY si el documento aún no tiene folio.
Empresas
/companiesLista 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.
/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.
/webhooks/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" } ]
}
}
| HTTP | code | Qué hacer |
|---|---|---|
| 400 | IDEMPOTENCY_KEY_REQUIRED, INVALID_JSON | Corrige la petición. |
| 401 | UNAUTHORIZED | Revisa la llave. |
| 403 | FORBIDDEN | La llave no tiene ese permiso. |
| 404 | NOT_FOUND | El recurso no existe en tu organización. |
| 409 | IDEMPOTENCY_CONFLICT, NOT_READY | Esa clave ya se usó con otro contenido, o el documento aún no está listo. |
| 413 | PAYLOAD_TOO_LARGE | Reduce el tamaño del documento. |
| 422 | VALIDATION_ERROR, LIMIT_REACHED | Lee details y corrige los campos. |
| 503 | PRODUCTION_DISABLED | La 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.