Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

SDK de facturación electrónica SUNAT (Perú) para Python

Un SDK para emitir comprobantes electrónicos ante la SUNAT desde Python, para quien programa el sistema de facturación de una empresa. Con los datos de una factura (01), una boleta (03), una nota de crédito (07) o de débito (08), un resumen diario de boletas (RC) o una comunicación de baja (RA):

  • arma el archivo XML que pide la SUNAT y lo firma con tu certificado digital;
  • lo comprime, lo envía y lee la respuesta de la SUNAT, que dice si lo aceptó;
  • después consulta el estado de un comprobante ya enviado en la Consulta Integrada de la SUNAT (validity: aceptado, anulado o no informado).

También arma, firma y envía la guía de remisión remitente (09) por la API REST de la SUNAT (abajo). Es la versión para Python del SDK, que también funciona en JavaScript y TypeScript, PHP, Rust y la línea de comandos: los mismos datos dan el mismo comprobante firmado en todos.

SUNAT (Peru) electronic invoicing SDK for Python.

Tu sistema calcula los importes; el paquete los valida y los pone en el XML, pero no calcula impuestos. Guías y ejemplos: https://fe.kembec.com

Instalación

La versión publicada es una beta:

pip install --pre facturacion-electronica-sunat-sdk

El paquete trae el núcleo en Rust del SDK ya compilado (wheels abi3), así que no llama a ningún binario externo. Hay wheels para CPython 3.10 o posterior en Linux (x86_64 y aarch64, glibc), macOS (arm64 y x86_64) y Windows (x86_64). En otra plataforma, pip lo compila desde el sdist y necesita Rust.

Para instalar main desde el repositorio hace falta Rust:

git clone https://github.com/Kembec/facturacion-electronica-sunat-sdk.git
cd facturacion-electronica-sunat-sdk
cp LICENSE NOTICE bindings/python/
pip install ./bindings/python

Tu primer comprobante

Baja a una carpeta vacía la factura de prueba y el certificado de prueba del repositorio. Ese certificado es autogenerado y no sirve para emitir.

base=https://raw.githubusercontent.com/Kembec/facturacion-electronica-sunat-sdk/v1.0.0-rc.4
curl -fsSLO "$base/fixtures/01-invoice-taxed-cash.json"
curl -fsSLO "$base/tests/vectors/test-cert/test-cert.pem"
curl -fsSLO "$base/tests/vectors/test-cert/test-key.pem"
# primer_comprobante.py
import sunat_sdk

def read(file):
    with open(file, encoding="utf-8") as f:
        return f.read()

built = sunat_sdk.build(read("01-invoice-taxed-cash.json"))
signed = sunat_sdk.sign(built["xml"], read("test-cert.pem"), read("test-key.pem"))
print(built["file_name"], signed["digest_value"])  # 20123456789-01-F001-1 +te61a2ub5MlTFf8tKTPNGWEXKI=

Si imprime 20123456789-01-F001-1 +te61a2ub5MlTFf8tKTPNGWEXKI= (el nombre del archivo y la huella de la firma), el paquete funciona: es la misma salida que dan JavaScript, PHP, Rust y la CLI. Tus propios documentos siguen la forma del modelo de entrada, como dict o como texto JSON.

Enviar a la SUNAT

sent = sunat_sdk.exchange(
    "send", {"name": built["file_name"], "xml": signed["xml"]},
    sol_user, sol_password, bill_service_url,            # sol_user: RUC + usuario SOL
)
# {"outcome": "cdr", "cdr": {...}, "cdr_zip_base64": "..."} o {"outcome": "fault", "code", "message", "class"}

Consultar el estado de un comprobante (Consulta Integrada)

validity pregunta a la Consulta Integrada de la SUNAT si una factura, boleta o nota (01, 03, 07, 08) existe y en qué estado está. Usa las «Credenciales de API SUNAT» que se crean en SOL para esta consulta: no el usuario SOL ni el par de la GRE.

check = sunat_sdk.validity(
    {"ruc": "20123456789", "document_type": "01", "series": "F001", "number": 123,
     "issue_date": "2026-10-16", "total": "118.00"},       # fecha de emisión y total del comprobante
    client_id, client_secret,
)
# {"outcome": "validity", "state": "accepted" | "voided" | "not_reported" | ..., "observations": [...], ...}
# {"outcome": "query_error", "error_code", ...}: la SUNAT rechazó la consulta, no el comprobante
# {"outcome": "no_verdict", "stage": "token" | "query", ...}: sin respuesta (401 incluido), vuelve a consultar
  • No hay ambiente de pruebas: por defecto la consulta va a producción; token_base y base reemplazan las URL base. El token y el secreto nunca vuelven en el resultado.
  • Ningún resultado es motivo para emitir la operación con otro número: not_reported no prueba que el comprobante no llegó (el ticket de un resumen puede seguir en proceso), así que antes se concilia con ticket o status.

Guía de remisión remitente (09) por la API REST

gre_send, gre_ticket y sus piezas sin red llegaron en la 0.1.0-beta.5.

sent = sunat_sdk.gre_send(
    {"name": built["file_name"], "xml": signed["xml"]},  # RUC-09-SERIE-NUMERO, ya firmada
    client_id, client_secret,                            # el par de GRE de «Credenciales de API SUNAT»
    sol_user, sol_password,                              # sol_user: RUC + usuario SOL
    token_base, api_base,                                # sin valor por defecto
)
# {"outcome": "ticket", "ticket", "received_at", "zip_name", "hash_zip"}: guarda el ticket antes que nada
status = sunat_sdk.gre_ticket(sent["ticket"], client_id, client_secret, sol_user, sol_password, token_base, api_base)
# state: "processed" (0, con la CDR leída), "in_process" (98) o "processed_with_errors" (99, con su error)

La SUNAT no tiene ambiente de pruebas para la GRE, y ninguna guía de este SDK figura como aceptada por la SUNAT. Las URL base siempre las pasas tú (las del manual: https://api-seguridad.sunat.gob.pe/v1/clientessol para el token y https://api-cpe.sunat.gob.pe/v1 para la API). Cada llamada pide su propio token y timeout cubre las dos.

  • Con 98, vuelve a consultar con el mismo ticket; nunca reenvíes la guía por eso.
  • Si el envío no recibe respuesta, gre_send lanza SunatSdkError: la guía pudo haber llegado, así que se reenvía el mismo archivo, nunca la operación con otro número. Un token o una consulta sin respuesta dan {"outcome": "no_verdict", "stage", ...}, y un rechazo de la SUNAT, {"outcome": "api_error", "stage", "errors", ...}.
  • Para usar tu propio cliente HTTP, o reutilizar el token hasta diez minutos antes de que venza, están las mismas piezas sin red: gre_token_request y gre_token_response, gre_send_request y gre_send_response, gre_ticket_request y gre_ticket_response, más gre_token_usable y gre_timeout.

API

build arma XML UBL 2.1 (comprobantes) o UBL 2.0 (resúmenes y bajas), y sign lo firma con XML-DSig.

  • build(document), sign(xml, cert_pem, key_pem, signature_id=None), zip({name, xml}) y cdr({cdr_base64}) devuelven el mismo JSON que la CLI y el paquete npm, ya convertido en dict. La llave PEM tiene que ser RSA sin cifrar; signature_id es signatureKG si no se indica.

  • exchange(kind, input, user, password, endpoint, timeout=60) hace una llamada al web service de la SUNAT. input es la entrada del mismo comando de la CLI:

    kind input endpoint
    send name, xml billService
    summary name, xml billService
    ticket ticket billService
    status ruc, document_type, series, number billConsultService

    Verifica TLS con el contexto por defecto del sistema; context= admite otro ssl.SSLContext, nunca uno sin verificación.

  • soap_request, soap_response y soap_timeout son las mismas piezas sin red, para quien hace el POST con su propio cliente HTTP (httpx, aiohttp).

  • Un envío rechazado u observado trae diagnosis en su resultado (soap_response, soap_timeout y exchange): por cada código de la respuesta, el campo de la entrada que lo causó, p. ej. customer.document_type para el 2800 de cbc:ID/schemeID. diagnose(document_type, code, message) lo da para un solo código.

  • validity(input, client_id, client_secret, timeout=60, context=None, token_base=None, base=None) pide el token y hace la consulta dentro de timeout. validity_token_request, validity_token_response, validity_request, validity_response y validity_timeout son sus piezas sin red.

  • Un error SOAP de la SUNAT es un resultado ({"outcome": "fault", ...}), no una excepción. Si ticket o status no reciben respuesta, el resultado es {"outcome": "no_verdict", ...}: se vuelve a consultar. Con ticket, el resumen nunca se reenvía, porque el ticket prueba que llegó. Si status sigue sin veredicto, se reenvía el mismo XML firmado con el mismo número mientras el plazo de envío siga abierto, porque la SUNAT lo mide al recibirlo; según sus reglas de validación, si ya lo tenía no lo registra dos veces y contesta 1033, 1032 o 0140. En send y summary, ese caso lanza SunatSdkError, porque el documento pudo haber llegado. Un summary sin respuesta no deja ticket: se revisan los comprobantes con validity y se reenvía el mismo archivo con el mismo nombre.

  • Toda entrada inválida lanza sunat_sdk.SunatSdkError (subclase de ValueError) con el motivo.

  • El certificado, la llave y las credenciales SOL los pasa quien llama: el paquete no los busca en archivos ni en el entorno, y no escribe logs.

Qué cubre y qué no

  • IGV al 18 % y al 10,5 %, operaciones gravadas, exoneradas, inafectas, de exportación y gratuitas, en soles y en dólares, al contado o a crédito en cuotas; descuento por línea; detracción con operación 1001 o 1003; retención del IGV informada en el comprobante; IVAP; orden de compra y guías de remisión citadas.
  • Lo que el SDK no cubre lo rechaza con SunatSdkError en vez de armar un XML que la SUNAT rechazaría: ISC, ICBPER, percepción, anticipos, descuentos y cargos globales, entre otros.
  • En la guía de remisión quedan fuera los traslados de importación y exportación y la guía del transportista (31).

La lista completa está en el alcance del SDK y cada campo, en el modelo de entrada.

Pruebas

Lo que aceptó la SUNAT y cómo se comprueba cada versión está en Cómo se comprueba: la beta de la SUNAT aceptó 36 de los 38 documentos de ejemplo; las 2 guías de remisión no tienen beta. Para este paquete, el CI lo instala en un entorno limpio y exige el XML y la firma exactos de los 38; exchange, validity, gre_send y gre_ticket se prueban contra un servidor local, sin red; las tres últimas, con respuestas grabadas de los manuales de la SUNAT y, en la GRE, de un cliente de terceros.

Licencia

MIT, © 2026 Manuel Benancio: ver LICENSE.

Metadata

Release files for facturacion-electronica-sunat-sdk 1.0.0rc4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for facturacion-electronica-sunat-sdk 1.0.0rc4
File Size Uploaded
facturacion_electronica_sunat_sdk-1.0.0rc4.tar.gz 253.6 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for facturacion-electronica-sunat-sdk 1.0.0rc4
File
facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 6.4 MB

Release files / facturacion_electronica_sunat_sdk-1.0.0rc4.tar.gz

Download URL facturacion_electronica_sunat_sdk-1.0.0rc4.tar.gz
Size 253.6 kB
Tags Source
SHA-256 checksum
How to use checksums
1bc9c29f18cbce0f2a20667dfeb654955e9688dc804032513d5b38d3ec2d95e3
BLAKE2b-256 checksum
How to use checksums
11bee3eb306b1cf206e0ba8f20d9821ca828c552f76c4073f2f6da749b8d292d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-win_amd64.whl

Download URL facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-win_amd64.whl
Size 1.1 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
9614465ed670ca6c43deacfb6142ffb2b45b62747b4d21e72a976f15f2c23361
BLAKE2b-256 checksum
How to use checksums
a6f67e6076a86efdaf8348d2c3834498816eb5f5e95c7a1eef036f67029d4324
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.3 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
5f79a6f3ade773efb0abd76772860b1a89fbbf4fef208513a35535eebd5abf88
BLAKE2b-256 checksum
How to use checksums
44dfefa5d7d1736b9b7a7198235db9c7b32d520ad431261e68b7a6954bbf3901
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.3 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
e1661d13ebacef0e743a2d4317cc886557c388f3135e64e37d6b7ff19c88d703
BLAKE2b-256 checksum
How to use checksums
e1dc948fa8c0dedf70bf9c0fce78d6c35580bba93cec7031f4ca0ce8d8a0f919
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-macosx_11_0_arm64.whl

Download URL facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-macosx_11_0_arm64.whl
Size 1.2 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
034887a77b1252dba8af09a1126f7ca8fcd417ac8e52adf76fd53904ce5a9774
BLAKE2b-256 checksum
How to use checksums
5b29ccb15e0d62d62e434d73ee76892cdf83eb01ef471dd364c60d80c5de6f86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-macosx_10_12_x86_64.whl

Download URL facturacion_electronica_sunat_sdk-1.0.0rc4-cp310-abi3-macosx_10_12_x86_64.whl
Size 1.2 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
52f51d8af01e2e4ab7de608bf0ecfccedf6e5977d38e83a5f054e454f4e17498
BLAKE2b-256 checksum
How to use checksums
a88e67bdb2aa1a53e07f4bdf5877467e69f7a70806f871fcc4e29625dc4ec07a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page