SDKs
Una clase, tres métodos
Un cliente
Invoiceconissue(),consult()ycancel()— nada más que instanciar.Modelos tipados
Cada ítem es un
Producttipado, con campos fiscales de Brasil validados en el cliente antes de que salga la solicitud.El mismo contrato en cada lenguaje
Python, Go y PHP siguen el mismo contrato de API — métodos, errores y recursos se comportan igual, así que cambiar de lenguaje no significa reaprender stackin.
¿Recién empezando?
Cree una cuenta gratuita, genere una SDK key y emita su primer documento en homologation — es gratis e ilimitado, sin tarjeta.
pip install stackin-python-sdkAutenticación
El SDK autentica con una SDK key — pásela una vez al crear el client, la librería se encarga del resto. Nunca construye una URL ni define un header manualmente.
Cómo obtener una SDK key
- 1Regístrese e inicie sesión en .
- 2Cree una empresa — obligatorio antes de la key.
- 3Vaya a Settings → API key en el dashboard, y deje el contexto en
sdk. No se necesita certificado en este paso — la key se puede crear y usar de inmediato; el certificado solo se exige después, al emitir un documento. - 4Nombre la key y elija su entorno (
homologationoproduction, por defectohomologation) — queda fijo durante toda la vida de la key, no se puede cambiar después. - 5Copie la key de inmediato — se muestra , al crearla, y no se puede recuperar después. Si la pierde, revóquela y cree otra.
from stackin import Invoice
client = Invoice(api_key="$STACKIN_API_KEY")Una empresa puede tener hasta 3 keys en total (cualquier combinación de contexto sdk/api y entorno homologation/production), así puede mantener keys separadas por superficie o entorno.
Un token ausente o inválido devuelve 401 — ver abajo.
Entornos
Cada SDK key se crea para exactamente un entorno — o or — elegido al generarla en el dashboard, fijo durante toda la vida de la key. No hay campo de entorno en las llamadas del SDK: la key con la que se autentica decide a dónde va el documento.
Gratis e ilimitado — es el entorno de prueba real de SEFAZ/ADN, no un mock — así que integra y prueba todo antes de cambiar a production.
Para documentos reales. Asegúrate de que todo funcione en homologation antes de cambiar.
Una empresa puede tener keys de ambos entornos a la vez (hasta 3 en total).
Errores
Los SDKs traducen cada falla en un tipo distinto: APIError para lo que respondió la API (con status y detail), ConnectionFailedError para una falla de red antes de cualquier respuesta, y el error de validación del propio lenguaje para lo que se detecta en el cliente, antes de que salga la solicitud.
from stackin import APIError, ConnectionFailedError
try:
result = client.issue(...)
except ValueError as error:
# Caught before the request left — empty items, missing ncm/cfop,
# incomplete recipient_address on an NFE.
print(f"Invalid request: {error}")
except APIError as error:
# 4xx/5xx from the API. 502 carries the authorizer's own message.
print(f"[{error.status_code}] {error.detail}")
except ConnectionFailedError as error:
print(f"Could not reach the API: {error}")| HTTP | Error | Cuándo |
|---|---|---|
| 400 | Configuración inválida | La configuración del emisor (certificado, dirección, campos fiscales) está ausente o es inválida. |
| 401 | No autorizado | El Bearer token está ausente, expirado, es inválido o no fue creado para el host que estás llamando (api.stackin.io vs sdk.stackin.io). |
| 402 | Límite alcanzado | La cuota del plan de la empresa para notas de production fue alcanzada y el plan no tiene precio de excedente (trial). |
| 409 | Conflicto de operación | La operación solicitada no aplica a ese document_type (ej.: una operación exclusiva de nfse en una nfe). |
| 422 | Error de validación | El cuerpo de la solicitud falló la validación — campo obligatorio faltante o malformado. |
| 501 | No implementado | La firma para ese tipo de documento/país aún no está implementada en el servidor. |
| 502 | El autorizador rechazóRechazo del autorizador | El autorizador (SEFAZ/estado o ADN) rechazó la solicitud. detail.message trae el error del propio autorizador, y detail.invoice_id (solo en la emisión) permite consultar el intento rechazado. |
Facturas
Emite un nuevo documento. items[].product.br (ncm, cfop) es obligatorio para , se ignora en , ignored for — un servicio no tiene código de clasificación fiscal, así que nfse solo lee description y amount de cada ítem.
La misma llamada funciona para nfse — solo cambia document_type.
from stackin import Address, DocumentType, Invoice
from stackin.br import Product
client = Invoice(api_key="$STACKIN_API_KEY")
result = client.issue(
document_type=DocumentType.NFE,
client_name="Buyer Company Ltd",
tax_id="11222333000181",
items=[
Product(
description="Rosa Holambra Vermelha",
amount=112.44,
ncm="06031100",
cfop="5102",
)
],
recipient_address=Address(
street="Rua das Flores",
number="1200",
neighborhood="Centro",
city="Joinville",
state="SC",
zip_code="89201100",
city_code="4209102",
),
)Consulta el estado actual de un documento directamente en el autorizador por su access key. Requiere como query param.
result = client.consult(
document_type=DocumentType.NFE,
access_key="42260831112223330001815500000012341123456789",
)Cancela un documento previamente autorizado. debe tener al menos 15 caracteres para nfe (el campo xJust del autorizador lo exige). Cancelar no devuelve la cuota del plan — la capacidad del autorizador ya se gastó en la emisión.
result = client.cancel(
document_type=DocumentType.NFE,
access_key="42260831112223330001815500000012341123456789",
reason="Duplicate order, cancelled by the buyer within 24h",
)Reenvía una emisión fallida por el `id` local del documento (no por su clave de acceso — una nota rechazada no tiene una). Útil para reintentar después de corregir un problema de configuración o una caída del autorizador. Consume crédito como una emisión nueva, ya que es una nueva transmisión.
result = client.reissue(
invoice_id="9f2c1e3a-4b5d-6e7f-8a9b-0c1d2e3f4a5b",
)