Primeros pasos
Convenciones generales
Las dos formas de respuesta (respuestas simples vs. sobre de la plataforma), formas de error, tipificación de errores, referencia de estados HTTP, idempotencia, límites de tasa, localización, tipos de datos, la estructura de la clave de acceso de la NF-e y los enlaces de descarga de archivos.
Convenciones compartidas por los endpoints de la Open API de TF Fiscal.
Formas de respuesta
La API tiene dos formas de respuesta, y cuál recibe depende del endpoint y de la capa que produjo la respuesta.
Respuestas simples (endpoints estándar)
Todos los endpoints estándar (empresas, NF-e, CT-e, DC-e, verificación, consulta de registro, registro de webhook) responden sin sobre:
| Grupo de endpoints | Forma de éxito |
|---|---|
| Registro de empresa, registro de webhook | Objeto simple ({ "empresaId": ... }, { "webHookId": ... }) |
| Vinculación de certificado, emisión y cancelación de NF-e / CT-e / DC-e | HTTP 200 sin cuerpo; el resultado llega de forma asíncrona |
| Consulta de NF-e / CT-e / DC-e, registro de carta de corrección y de eventos | Objeto simple: el documento, el protocolo o la lista de eventos |
| Verificación por XML, consulta por chave | Objeto simple: la factura interpretada (la verificación por XML añade el bloque validation) |
| Consulta de CNPJ, consulta de CPF | Objeto simple: el registro |
Los errores de negocio y de solicitud de los endpoints estándar vienen en dos formas de error, según la familia del endpoint.
Familia de emisión (empresas, NF-e, CT-e, DC-e, registro de webhook; HTTP 400 / 404): un array de errores, cada uno con codigo y mensagem. Los fallos de validación del cuerpo producen una entrada por campo:
[{ "codigo": "NFe0001", "mensagem": "A Nota fiscal nao foi encontrada. Por favor, verifique se o id foi informado corretamente" }]
codigo es una cadena: los tres códigos GW001 (ciudad / estado inválido), CER0005 (contraseña del certificado incorrecta) y NFe0001 (factura no encontrada) conservan sus valores alfanuméricos, igual que los códigos DCe* de la familia DC-e; todas las demás entradas llevan el código de error de la plataforma como cadena numérica.
Familias de verificación y consulta de registro (HTTP 400, y 422 / 428 / 451 / 503 en la consulta de registro): un objeto simple con code y message:
{ "code": 10015004, "message": "Invoice not found" }
| Campo | Tipo | Descripción |
|---|---|---|
code | integer | Código de error de la plataforma |
message | string | Explicación legible, localizada |
Sobre de la plataforma
Lo usan el endpoint de echo (POST /openapi/demo/echo) en toda respuesta, el endpoint de descarga de archivos en sus fallos y el gateway de la plataforma para los errores de la capa de autenticación en cualquier endpoint (HTTP 401 / 403 / 429), producidos antes de que la solicitud llegue al endpoint:
{ "success": true, "message": "OK", "data": { } }
{ "success": false, "errorType": 1, "code": 10009003, "message": "Signature error" }
| Campo | Tipo | Presencia | Descripción |
|---|---|---|---|
success | boolean | siempre | false en todo error |
errorType | integer | en error | Clase del error, vea Tipificación de errores |
code | integer | en error | Código de error de la plataforma, vea Códigos de error |
message | string | siempre | Explicación legible, localizada |
data | object | null | en éxito | Carga del endpoint; no se rellena en errores |
Manejar ambas formas
Su manejador de errores debe aceptar el sobre y las formas de error simples. Una regla robusta:
- Trate HTTP 400 o superior como fallo y, además,
success: falsecuando el cuerpo sea un sobre. - Interprete el cuerpo como JSON. Si es un array, lea
codigode cada entrada; si es un objeto, leacode. - Ramifique por el código, nunca por el texto de
message/mensagem(están localizados).
Tipificación de errores (errorType)
Los errores en sobre llevan un campo errorType que clasifica el origen del fallo:
| errorType | Clase | Significado |
|---|---|---|
| 1 | Error de API | Rechazo de autenticación, autorización o de negocio por TF Fiscal |
| 2 | Rechazo de la SEFAZ | La autoridad fiscal brasileña rechazó la operación |
| 3 | Fallo del sistema | Fallo inesperado de la plataforma; es seguro reintentar con backoff |
| 4 | Fallo de validación | La validación de los campos de la solicitud falló |
Referencia rápida de estados HTTP
| HTTP | Escenario | Forma del cuerpo |
|---|---|---|
| 200 | Solicitud aceptada; en la verificación por XML esto incluye una validación fallida (revise el bloque validation) | Datos simples, o sin cuerpo |
| 400 | Solicitud inválida o regla de negocio violada | [{codigo, mensagem}] (emisión) o {code, message} (verificación / consulta de registro) |
| 404 | empresaId / id del documento no encontrado (familia de emisión) | [{codigo, mensagem}] |
| 401 | Fallo de autenticación (token / sign / timestamp), o enlace de descarga inválido o vencido | Sobre de la plataforma |
| 403 | Aplicación deshabilitada / no vigente / integrador deshabilitado / no suscrito | Sobre de la plataforma |
| 422 / 428 / 451 | Consulta de CPF retenida por ley (titular de 16 a 17 años / edad no verificable / titular menor de 16); no reintente | {code, message}, sin campos personales |
| 429 | Límite de tasa excedido | Sobre de la plataforma |
| 503 | Fuente de datos upstream no disponible (consulta de registro, 10016020) o archivo aún no renderizado (descarga, 10009037); reintente tras Retry-After | {code, message} o sobre de la plataforma |
| 5xx | Fallo del lado de la plataforma | Reintente con backoff; si persiste, contacte a la plataforma con el timestamp y la ruta del fallo |
Idempotencia
- La emisión de NF-e es idempotente por el
idde la solicitud que usted genera: reenviar el mismoidreutiliza la tarea original. Si el intento anterior fue denegado (Negada), reenviar el mismoidcon los campos corregidos emite de nuevo con la nueva carga, sin necesidad de un nuevo id. Cambiar campos clave como el destinatario mientras el intento anterior sigue en proceso o ya fue autorizado se rechaza concodigo10004032. - La emisión de CT-e y DC-e también es idempotente por
id: un mensaje idéntico reutiliza la tarea original, un mensaje distinto bajo el mismoidse rechaza (10017030para CT-e,10019030para DC-e), y un fallo terminal (Falha) reabre la tarea con el nuevo mensaje. - La verificación por XML es idempotente por la clave de acceso (
chave): reenviar mientras una verificación está en curso devuelve el progreso actual, y los veredictos terminales se reutilizan durante 24 horas. Para forzar una nueva verificación, envíe la cabeceraforceRevalidate: trueen el endpoint de XML (la cabecera no forma parte de la firma). La consulta por chave es un GET fijo y no tiene canal de reverificación; para forzar una nueva verificación, reenvíe por el endpoint de XML. UnREJECTEDdel nivel 1 no tiene registro de nivel 2; la reverificación exige reenviar el XML. - Las entregas de webhook son idempotentes por
event_id: cada reintento y cada destino de un mismo evento llevan el mismo valor, así que deduplique por él. Vea Webhooks.
Límite de tasa y backoff
- Cuota por aplicación: excederla devuelve HTTP 429 con el código
10009006. Los límites se aplican por aplicación y por grupo de endpoints. Retroceda y reintente (empiece en 1 s, duplique hasta 30 s, añada jitter) y suavice su tasa de llamadas. - Anti-flood por CNPJ: si una empresa acumula demasiadas tareas de emisión pendientes, los nuevos envíos se rechazan con
codigo10004002hasta que la cola se vacíe; reintente más tarde. - Ventana del timestamp: las solicitudes con
timestampfuera de ±300 s del reloj del servidor se rechazan (10009001), lo que también limita el replay de solicitudes capturadas. - 401 y 403 son errores de configuración; reintentarlos sin corregir solo consume cuota.
- Las descargas de archivos cuentan contra el límite de la aplicación en su propio grupo y no se facturan.
Localización de las respuestas
Los campos message, mensagem y *Description siguen el idioma de la solicitud: la cabecera Language (zh / en / pt / es) tiene precedencia, luego Accept-Language (admite pt-BR y valores q). Sin cabecera de idioma, las respuestas usan por defecto portugués (pt). Las cabeceras de idioma no forman parte de la firma.
Las cargas de webhook solo llevan valores de enumeración independientes del idioma; no hay campos *Description en ellas. Para decisiones programáticas use siempre códigos y campos de enumeración (code, codigo, status, validationStatus, errors[].code, situacao.codigo), nunca texto descriptivo.
Horas y tipos de datos
- Las horas producidas por la plataforma (
dataCriacao,dataAutorizacaode los documentos emitidos,occurred_atde webhook,verifiedAt,serverTimedel echo) son ISO-8601 UTC con el sufijoZ, en todos los entornos. - Las horas extraídas de un documento de terceros por la API de verificación (
dataEmissao,dataAutorizacao) se devuelven tal cual, con el desfase horario del documento, por ejemplo2026-07-23T11:20:05-03:00. - La cabecera
timestampde la solicitud es tiempo Unix en segundos, no milisegundos. - Los identificadores son cadenas aunque sean numéricos (
empresaId,webHookId,event_id), para evitar pérdida de precisión numérica en JavaScript. Trate todos los ids como cadenas opacas; elidde documento que usted genera también es una cadena. - Los números de documento (
numero) y las series (serie) son cadenas. Los importes y cantidades son números JSON. - Las variables de ruta como
cnpj,cpfychaveson cadenas solo de dígitos sin caracteres de formato; la fecha de nacimiento del CPF (nascimento) esDDMMYYYY.
La clave de acceso de la NF-e (chave)
La chave de acesso es el identificador nacionalmente único de 44 dígitos de una NF-e. Aparece como chaveAcesso en las respuestas de consulta y verificación y como variable de ruta de la consulta por chave. Su estructura:
| Posiciones | Longitud | Campo | Significado |
|---|---|---|---|
| 1 a 2 | 2 | cUF | Código IBGE del estado emisor (p. ej. 35 = SP) |
| 3 a 6 | 4 | AAMM | Año y mes de emisión (AAMM) |
| 7 a 20 | 14 | CNPJ | CNPJ del emisor |
| 21 a 22 | 2 | mod | Modelo del documento fiscal (55 = NF-e) |
| 23 a 25 | 3 | serie | Serie de la factura |
| 26 a 34 | 9 | nNF | Número de la factura |
| 35 | 1 | tpEmis | Tipo de emisión |
| 36 a 43 | 8 | cNF | Código numérico aleatorio |
| 44 | 1 | cDV | Dígito verificador (módulo 11) |
Notas:
- Almacene y transmita siempre la chave como una cadena de 44 caracteres (los ceros a la izquierda son significativos).
- La consulta por chave valida longitud, caracteres y dígito verificador localmente antes de intentar cualquier consulta; una chave malformada devuelve HTTP 400 con el código
10015104. - Las claves de CT-e (modelo 57) y DC-e (modelo 99) comparten el mismo diseño de 44 dígitos con su propio valor de
mod.
Enlaces de descarga de archivos
Los enlaces de descarga en las respuestas de consulta y en las cargas de callback (linkDanfe, linkDownloadXml, linkDacce y sus equivalentes de CT-e / DC-e) tienen la forma https://api.v2.tffiscal.com/openapi/files/{kind}/{ref}?token=.... No necesitan cabeceras de firma: basta un GET simple que siga la redirección 302. El token está vinculado a la ruta, al integrador y a la aplicación, así que use el enlace exactamente como se devolvió. Los enlaces son válidos 7 días por defecto y cada consulta emite enlaces nuevos; un enlace vencido devuelve 401 con 10009036. Detalles: Descarga de archivos.
