Emite un comprobante de verdad. Ahora.
Esta página habla con una instancia de InkFact igual que lo haría tu ERP: misma API, misma firma, mismas credenciales. Lo que emitas aquí va a la beta de SUNAT y vuelve con su CDR.
Estás viendo una grabación. La factura se emitió el desde esta misma página contra la beta de SUNAT. El CDR, el PDF, el XML firmado y los tiempos del historial son los que devolvió la API. Nada de lo que toques aquí sale a ningún sitio.
Conectar
Nada de lo que escribas sale de esta pestaña. El secreto nunca viaja: solo firma. ¿No tienes una instancia a mano? Mira la muestra: una factura real, aceptada por SUNAT, grabada dentro de este fichero. Y si quieres probar con tus datos, escríbenos.Armar el comprobante
Los importes van sin IGV. Impuestos, totales, importe en letras, XML y firma los pone el servicio. Tal como se rellenó en la grabación. Para cambiarlo, conecta a una instancia.Orientativo. Los importes que valen los calcula el servidor con aritmética exacta y son los que van al XML.
Qué pasa con el comprobante
El número se asigna al instante. Todo lo demás pasa después, en cola. Aquí lo vas viendo.- Total
- SUNAT
- Hash del QR
Historial ·
Lo que se envió y lo que contestó la API
Últimos comprobantes
Solo los del alcance de esta key.| Comprobante | Cliente | Total | Estado | SUNAT |
|---|
Integrarlo en tu ERP
La API es JSON plano: mandas el comprobante, recibes el número al instante y el estado te llega por webhook. Lo único con truco es la firma, y es la misma en cualquier lenguaje.
cadena = <timestamp>.<MÉTODO>.<ruta>.<sha256hex(cuerpo)> X-Signature = sha256=<hmac-sha256(secreto, cadena)>
- Hashea el cuerpo tal cual viaja. Si lo reformateas después de firmar, la firma deja de valer.
- Arma la cadena con la hora, el método y la ruta: una firma robada no sirve para otra ruta ni pasados unos minutos.
- Fírmala con el secreto. El secreto nunca viaja: solo la firma.
- Manda tu id de venta como Idempotency-Key: si la red se cae a mitad, reintentas con el mismo y no se emite dos veces.
// cliente.php: sin Composer, se copia dentro del ERP y funciona. $inkfact = new InkFact(baseUrl: 'https://facturacion.tu-dominio', apiKey: 'ik_…', hmacSecret: '…'); $r = $inkfact->emitir([ 'emisor_ruc' => '20553219702', 'doc_type' => 'boleta', 'serie' => 'B001', 'issue_date' => date('Y-m-d'), 'currency' => 'PEN', 'operation_type' => '0101', 'customer' => ['doc_type' => '1', 'doc_number' => '45678912', 'name' => 'MARIA QUISPE HUAMAN'], 'items' => [['description' => 'Menu del dia', 'quantity' => 2, 'unit' => 'NIU', 'unit_value' => 12.7119, 'igv_type' => '10']], 'external_reference' => 'pedido_1234', ], claveIdempotencia: claveIdempotencia('pedido_1234')); // Aquí ya puedes imprimir: el correlativo está asignado. SUNAT viene después. echo $r['comprobante']['full_number']; // B001-00001247
// cliente.mjs: Node sin dependencias. const inkfact = new InkFact({ baseUrl: 'https://facturacion.tu-dominio', apiKey: 'ik_…', hmacSecret: '…' }); const { comprobante } = await inkfact.emitir({ emisor_ruc: '20553219702', doc_type: 'boleta', serie: 'B001', issue_date: new Date().toISOString().slice(0, 10), currency: 'PEN', operation_type: '0101', customer: { doc_type: '1', doc_number: '45678912', name: 'MARIA QUISPE HUAMAN' }, items: [{ description: 'Menu del dia', quantity: 2, unit: 'NIU', unit_value: 12.7119, igv_type: '10' }], external_reference: 'pedido_1234', }, claveIdempotencia('pedido_1234')); // Aquí ya puedes imprimir: el correlativo está asignado. SUNAT viene después. console.log(comprobante.full_number); // B001-00001247
# La firma a mano: hash del cuerpo, cadena canónica, HMAC con el secreto. BODY='{"emisor_ruc":"20553219702","doc_type":"boleta","serie":"B001", … }' TS=$(date +%s) HASH=$(printf '%s' "$BODY" | sha256sum | cut -d' ' -f1) SIG=$(printf '%s' "$TS.POST./v1/comprobantes.$HASH" | openssl dgst -sha256 -hmac "$SECRETO" | sed 's/^.* //') curl -X POST https://facturacion.tu-dominio/v1/comprobantes \ -H "X-Api-Key: $API_KEY" -H "X-Timestamp: $TS" -H "X-Signature: sha256=$SIG" \ -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" -d "$BODY" # 202 con el correlativo ya asignado. Luego: GET /v1/comprobantes/{id}
Los dos clientes completos —con la clave de idempotencia derivada de tu pedido, la consulta y las descargas— están en el repositorio: cliente.php y cliente.mjs. Sin dependencias. Con el código va también una colección de Postman con 75 peticiones.
Qué hay dentro
Lo que hace falta para facturar ante SUNAT desde cualquier ERP, y lo que hace falta para seguir operándolo el mes que viene.
- Boletas y facturas
- Notas de crédito y débito, resumen diario de boletas y comunicación de baja. Anular decide solo cuál toca según el tipo y el plazo.
- Guías de remisión
- Por la API REST de SUNAT, con OAuth2 y verificadas contra un servidor que la imita. La baja, que SUNAT solo admite desde SOL, se registra para que el ERP no la vea vigente.
- Correlativos sin carreras
- Dos cajas cobrando a la vez nunca sacan el mismo número. Lock de fila en la base, no en el código.
- Idempotencia
- Un timeout no emite dos veces: la misma clave devuelve el mismo comprobante.
- Cola con reintentos y contingencia
- El ERP recibe el número al instante y nunca espera a SUNAT. Si SUNAT se cae, se reintenta con espera creciente.
- Webhooks firmados
- Cada cambio de estado llega a tu sistema con HMAC y reintentos hasta que contestes 2xx.
- PDF con QR y hash
- A4 y ticket de 80 y 58 mm, con logo. Envío por correo con el PDF y el XML firmado adjuntos.
- Multiempresa
- Cada RUC con su certificado, su ambiente y sus series. Una API key solo ve los RUC de su alcance.
- Certificados cifrados en reposo
- Nunca en el repositorio, nunca en variables de entorno, nunca en logs. Aviso 30 días antes de que venzan.
- Panel y fiscalización
- Documentos por estado, errores, vencimientos. Un informe mensual busca huecos de numeración y comprobantes sin respaldo.
- Verificado contra la beta de SUNAT
- 31 comprobantes distintos: gratuitas, ISC, exportación, dólares, descuentos globales, notas y resúmenes. Y las guías, contra el servidor de pruebas de la GRE.
- Se instala en tu servidor
- Docker y Postgres. Guía de despliegue, runbook por síntoma, respaldos que se restauran de verdad cada semana.
Cómo se compra
Se vende el código fuente completo, con licencia de uso propio y doce meses de actualizaciones. No es una suscripción a un servicio de terceros: el servicio es tuyo y corre donde tú digas.
- EscríbenosCuéntanos qué sistema tienes —PHP, Node, lo que sea— y cuántos RUC vas a facturar.
- Recibes el accesoAl repositorio privado, con la licencia a tu nombre y el historial de cambios completo.
- Despliegas y facturasCon la guía de despliegue, primero en la beta de SUNAT y luego en producción, RUC por RUC.
Las actualizaciones cubren los cambios de SUNAT en el periodo: validaciones nuevas, catálogos, plazos. Lo que se rompa por una resolución nueva se arregla en el mismo código que ya tienes.