Skip to Content
API Reference (English)General Conventions

General Conventions

Conventions shared by the endpoints of the TF Fiscal Open API.

Response shapes

The API has two response shapes, and which one you receive depends on the endpoint and on which layer produced the response.

Platform envelope

Used by the echo endpoint (POST /openapi/demo/echo) for every response, and by the platform gateway for authentication-layer errors on every endpoint (HTTP 401 / 403 / 410 / 429), which are produced before the request reaches the endpoint:

// echo success { "success": true, "message": "OK", "data": { } } // gateway error (any endpoint) { "success": false, "errorType": 1, "code": 10009003, "message": "Signature error" }
FieldTypePresenceDescription
successbooleanalwaysfalse for every error
errorTypeintegeron errorError class — see Error typing
codeintegeron errorPlatform error code — see Error Codes
messagestringalwaysHuman-readable explanation, localized
dataobject | nullon successEndpoint payload; not populated on errors

Bare responses

All standard endpoints (issuance, verification, identity) respond without the envelope:

Endpoint groupSuccess shape
Company registration, webhook registrationBare object ({ "empresaId": ... }, { "webHookId": ... })
Certificate association, NF-e issuance, NF-e cancellationHTTP 200 with no body
NF-e queryBare object: the invoice itself
XML verification, chave lookupBare object: the parsed invoice (XML verification adds a validation block)
CNPJ lookup, CPF lookupBare object: the registry record

Business and request-level errors of the standard endpoints come in two error shapes, by endpoint family:

Issuance family (HTTP 400 / 404) — an array of errors, each with codigo and mensagem. Request-body validation failures produce one entry per field:

[ { "codigo": "NFe0001", "mensagem": "A Nota fiscal nao foi encontrada. Por favor, verifique se o id foi informado corretamente" } ]

codigo is a string: the three codes GW001 (invalid city / state), CER0005 (certificate password mismatch) and NFe0001 (invoice not found) keep their alphanumeric values; all other entries carry the platform error code as a numeric string.

Verification and identity families (HTTP 400) — a bare object with code and message:

{ "code": 10015004, "message": "Invoice not found" }
FieldTypeDescription
codeintegerPlatform error code
messagestringHuman-readable explanation, localized

Handling both shapes

Your error handler must accept the envelope and the bare error shapes. A robust rule:

  1. Treat HTTP ≥ 400 as failure, and additionally success: false when the body is an envelope.
  2. Parse the body as JSON. If it is an array, read codigo from the first entry; if it is an object, read code.
  3. Branch on the code, never on message / mensagem text (they are localized).

Error typing (errorType)

Envelope errors carry an errorType field that classifies the failure source:

errorTypeClassMeaning
1API errorAuthentication, authorization or business rejection by TF Fiscal
2SEFAZ rejectionThe Brazilian tax authority rejected the operation
3System faultUnexpected platform failure; safe to retry with backoff
4Validation failureRequest field validation failed

HTTP status quick reference

HTTPScenarioBody shape
200Request accepted — for XML verification this includes a failed validation (check the validation block)Bare data, or no body
400Request invalid or business rule violated[{codigo, mensagem}] (issuance) or {code, message} (verification / identity)
404empresaId / nfeId not found (issuance family)[{codigo, mensagem}]
401Authentication failed (token / sign / timestamp)Platform envelope
403Application disabled / not effective / integrator disabled / not subscribedPlatform envelope
410Endpoint retired — see Deprecated EndpointsPlatform envelope
429Rate limit exceededPlatform envelope
5xxPlatform-side faultRetry with backoff; if persistent, contact the platform with the failing timestamp and path

Idempotency

  • NF-e issuance is idempotent on the request id you generate: re-submitting the same id within the idempotency window reuses the original task instead of creating a new one. Use a stable, unique id per invoice and retry with the same value. A denied invoice (Negada) is resubmitted under a new id after fixing the cause.
  • XML verification is idempotent on the access key (chave): resubmitting while a verification is in progress returns the current progress, and terminal verdicts are reused for 24 hours. To force a re-check, send the header forceRevalidate: true on the XML endpoint (the header is not part of the signature). The chave lookup is a fixed GET and has no re-verification channel. A Tier-1 REJECTED has no Tier-2 record; re-verification requires resubmitting the XML.
  • Webhook deliveries are idempotent by event_id — see Webhooks.

Rate limiting and anti-flood

  • Per-application quota: exceeding it returns HTTP 429 with code 10009006. Limits are enforced per application and per endpoint group. Back off and retry (start at 1 s, double up to 30 s, add jitter) and smooth your call rate.
  • Per-CNPJ anti-flood: if a company accumulates too many pending issuance tasks, new submissions are rejected with codigo 10004002 until the queue drains — retry later.
  • Timestamp window: requests with a timestamp beyond ±300 s of the server clock are rejected (10009001), which also bounds replay of captured requests.
  • A 410 response for a retired endpoint consumes no rate-limit token.

Response localization

message, mensagem and *Description fields follow the request language: the Language header (en / pt / es / zh) takes precedence, then Accept-Language (supports pt-BR and q-values). Without a language header, responses default to Portuguese (pt).

Webhook payloads carry only language-independent enum values — there are no *Description fields there. For programmatic decisions always use codes and enum fields (code, codigo, status, validationStatus, errors[].code, situacao.codigo), never description text.

Timestamps and data types

  • Times produced by the platform (issuance API dataCriacao, dataAutorizacao, webhook occurred_at, verifiedAt, …) are ISO-8601 UTC with the Z suffix.
  • Times parsed from a third-party document by the verification API (dataEmissao, dataAutorizacao) are returned verbatim with the document’s UTC offset, e.g. 2026-07-23T11:20:05-03:00.
  • The timestamp request header is Unix time in seconds, not milliseconds.
  • Identifiers are strings even when numeric (empresaId, webHookId, event_id), to avoid JavaScript number precision loss. Treat all ids as opaque strings.
  • Invoice numbers (numero) and series (serie) are strings. Amounts are JSON numbers.
  • Download links (linkDanfe, linkDownloadXml, nfeLinkXml) embed a 10-minute token; fetch a fresh link each time you need the file rather than persisting the URL.

The NF-e access key (chave)

The chave de acesso is the nationally unique, 44-digit identifier of an NF-e. It appears as chaveAcesso in query and verification responses and as the path variable of the chave lookup. Its structure:

PositionsLengthFieldMeaning
1–22cUFIBGE code of the issuing state (e.g. 35 = SP)
3–64AAMMYear and month of issue (YYMM)
7–2014CNPJIssuer CNPJ
21–222modFiscal document model (55 = NF-e)
23–253serieInvoice series
26–349nNFInvoice number
351tpEmisEmission type
36–438cNFRandom numeric code
441cDVCheck digit (modulo 11)

Notes:

  • Always store and transmit the chave as a 44-character string (leading zeros are significant).
  • The chave lookup validates length, characters and the check digit locally before any lookup is attempted; a malformed chave returns HTTP 400 with code 10015104.
Last updated on