快速开始
通用约定
两种响应形状(裸响应与平台信封)、错误形状、错误分类、HTTP 状态速查、幂等、限流、本地化、数据类型、NF-e 访问密钥结构与文件下载链接。
TF Fiscal 开放 API 各端点共用的约定。
响应形状
API 有两种响应形状,收到哪一种取决于端点以及产生响应的层。
裸响应(标准端点)
全部标准端点(开票主体、NF-e、CT-e、DC-e、验证、身份核验、Webhook 注册)都不带信封响应:
| 端点组 | 成功形状 |
|---|---|
| 主体注册、Webhook 注册 | 裸对象({ "empresaId": ... }、{ "webHookId": ... }) |
| 证书关联、NF-e / CT-e / DC-e 开票与取消 | HTTP 200 无响应体;结果异步到达 |
| NF-e / CT-e / DC-e 查询、更正函与事件登记 | 裸对象:凭证、协议号或事件列表 |
| XML 验证、chave 查询 | 裸对象:解析后的票面(XML 验证额外带 validation 块) |
| CNPJ 查询、CPF 查询 | 裸对象:登记记录 |
标准端点的业务与请求级错误按端点族分为两种错误形状。
开票族(开票主体、NF-e、CT-e、DC-e、Webhook 注册;HTTP 400 / 404):错误数组,每项含 codigo 与 mensagem。请求体字段校验失败时每个字段一条:
[{ "codigo": "NFe0001", "mensagem": "A Nota fiscal nao foi encontrada. Por favor, verifique se o id foi informado corretamente" }]
codigo 为字符串:GW001(城市 / 州不合法)、CER0005(证书密码不符)、NFe0001(发票不存在)三个原码沿用字母数字取值,DC-e 族的 DCe* 码也是如此;其余各项均为平台错误码数字串。
验证族与身份核验族(HTTP 400,身份核验另有 422 / 428 / 451 / 503):含 code 与 message 的裸对象:
{ "code": 10015004, "message": "Invoice not found" }
| 字段 | 类型 | 说明 |
|---|---|---|
code | integer | 平台错误码 |
message | string | 人类可读说明,已本地化 |
平台信封
用于联调回显端点(POST /openapi/demo/echo)的全部响应、文件下载端点的失败响应,以及平台网关在任意端点上产出的鉴权层错误(HTTP 401 / 403 / 429),后者在请求到达端点之前产生:
{ "success": true, "message": "OK", "data": { } }
{ "success": false, "errorType": 1, "code": 10009003, "message": "Signature error" }
| 字段 | 类型 | 出现性 | 说明 |
|---|---|---|---|
success | boolean | 恒有 | 所有错误恒为 false |
errorType | integer | 错误时 | 错误分类,见错误分类 |
code | integer | 错误时 | 平台错误码,见错误码 |
message | string | 恒有 | 人类可读说明,已本地化 |
data | object | null | 成功时 | 端点载荷;错误时不填充 |
兼容两种形状
错误处理必须同时接受信封与裸错误形状。稳妥做法:
- 把 HTTP 400 及以上视为失败;响应体是信封时,
success: false也视为失败。 - 把响应体按 JSON 解析。是数组则逐项读取
codigo;是对象则读取code。 - 按错误码分支,永远不要按
message/mensagem文案分支(它们会本地化)。
错误分类(errorType)
信封错误带 errorType 字段,标明失败来源:
| errorType | 分类 | 含义 |
|---|---|---|
| 1 | API 错误 | TF Fiscal 的鉴权、授权或业务拒绝 |
| 2 | SEFAZ 驳回 | 巴西税务机关拒绝了该操作 |
| 3 | 系统异常 | 平台意外故障;可退避重试 |
| 4 | 字段校验失败 | 请求字段校验未通过 |
HTTP 状态速查
| HTTP | 场景 | 响应形状 |
|---|---|---|
| 200 | 请求已受理;XML 验证时含校验不通过(看 validation 块) | 裸数据,或无响应体 |
| 400 | 请求非法或违反业务规则 | [{codigo, mensagem}](开票)或 {code, message}(验证 / 身份核验) |
| 404 | empresaId / 凭证 id 不存在(开票族) | [{codigo, mensagem}] |
| 401 | 鉴权失败(token / sign / timestamp),或下载链接无效 / 过期 | 平台信封 |
| 403 | 应用停用 / 未生效 / 集成商停用 / 未订阅 | 平台信封 |
| 422 / 428 / 451 | CPF 查询依法拦截(持有人 16 到 17 岁 / 年龄无法核实 / 持有人小于 16 岁);勿重试 | {code, message},无人员字段 |
| 429 | 超出限流额度 | 平台信封 |
| 503 | 上游数据源不可用(身份核验,10016020)或文件尚未生成(下载,10009037);按 Retry-After 重试 | {code, message} 或平台信封 |
| 5xx | 平台侧故障 | 退避重试;持续失败请携带失败请求的 timestamp 与路径联系平台 |
幂等
- NF-e 开票以你生成的请求
id为幂等键:同一id重复提交复用原任务。若上一次开票被驳回(Negada),同一id修正字段后重提会按新报文重新开票,无需换 id。上一次仍在处理或已授权时改动收件人等关键字段重提,则以codigo10004032拒绝。 - CT-e 与 DC-e 开票同样以
id为幂等键:报文相同复用原任务,同一id报文不同则拒绝(CT-e 为10017030,DC-e 为10019030),终态失败(Falha)后重提会用新报文重开任务。 - XML 验证以访问密钥(
chave)为幂等键:验证进行中重复提交返回当前进度,终态结论 24 小时内复用。需强制重验时,在 XML 端点加请求头forceRevalidate: true(该头不参与签名)。chave 查询为固定 GET,无重验通道;需强制重验请走 XML 端点重新提交。一级REJECTED无二级记录,重验须重新提交 XML。 - Webhook 投递以
event_id为幂等键:同一事件的所有重试与多目标扇出共用同值,接收方据此去重。见 Webhooks。
限流与退避
- 应用级配额:超出返回 HTTP 429 与错误码
10009006。限流按应用与接口组两级实施。退避重试(初始 1 秒,倍增至 30 秒上限,加抖动)并平滑调用频率。 - CNPJ 级防洪:主体待处理开票任务积压过多时,新提交以
codigo10004002拒绝,直到队列消化;稍后重试。 - 时间戳窗口:
timestamp与服务器时钟偏差超 ±300 秒的请求被拒绝(10009001),这也限制了被截获请求的重放。 - 401 与 403 属配置错误,不修复就重试只会消耗配额。
- 文件下载计入应用总闸并单列接口组,不计费。
响应本地化
message、mensagem 与 *Description 字段随请求语言返回:Language 头(zh / en / pt / es)优先,其次 Accept-Language(支持 pt-BR 与 q 值)。未提供语言头时默认葡语(pt)。语言头不参与签名。
Webhook 载荷只携带语言无关的枚举值,其中没有 *Description 字段。程序判断一律使用错误码与枚举字段(code、codigo、status、validationStatus、errors[].code、situacao.codigo),永远不要匹配描述文案。
时间与数据类型
- 平台产生的时间(已开凭证的
dataCriacao、dataAutorizacao,Webhook 的occurred_at、verifiedAt,echo 的serverTime)均为带Z后缀的 ISO-8601 UTC,与环境无关。 - 验证 API 从第三方凭证解析出的时间(
dataEmissao、dataAutorizacao)原样返回并保留凭证自带的时区偏移,例如2026-07-23T11:20:05-03:00。 - 请求头
timestamp是 Unix 秒级时间,不是毫秒。 - 标识符即使是数字也一律为字符串(
empresaId、webHookId、event_id),以避免 JavaScript 数字精度丢失。把所有 id 当作不透明字符串;你生成的凭证id同样是字符串。 - 凭证号(
numero)与系列(serie)为字符串。金额与数量为 JSON 数字。 cnpj、cpf、chave等路径变量为纯数字字符串,不含格式符;CPF 出生日期(nascimento)为DDMMYYYY。
NF-e 访问密钥(chave)
chave de acesso 是 NF-e 全国唯一的 44 位标识。它在查询与验证响应中以 chaveAcesso 出现,也是 chave 查询的路径变量。结构如下:
| 位置 | 长度 | 字段 | 含义 |
|---|---|---|---|
| 1 至 2 | 2 | cUF | 开票州的 IBGE 代码(如 35 = SP) |
| 3 至 6 | 4 | AAMM | 开票年月(YYMM) |
| 7 至 20 | 14 | CNPJ | 开票方 CNPJ |
| 21 至 22 | 2 | mod | 税务凭证模型(55 = NF-e) |
| 23 至 25 | 3 | serie | 发票系列 |
| 26 至 34 | 9 | nNF | 发票号 |
| 35 | 1 | tpEmis | 开票方式 |
| 36 至 43 | 8 | cNF | 随机数字码 |
| 44 | 1 | cDV | 校验位(模 11) |
说明:
- 始终以 44 字符的字符串存储与传输 chave(前导零有意义)。
- chave 查询在发起任何查询之前先本地校验长度、字符与校验位;chave 非法返回 HTTP 400 与错误码
10015104。 - CT-e(模型 57)与 DC-e(模型 99)的密钥沿用同样的 44 位布局,只是
mod取值不同。
文件下载链接
查询响应与回调载荷中的下载链接(linkDanfe、linkDownloadXml、linkDacce 及其 CT-e / DC-e 对应字段)形如 https://api.v2.tffiscal.com/openapi/files/{kind}/{ref}?token=...。它们不需要签名头:直接 GET 并跟随 302 跳转即可。令牌与路径、集成商、应用绑定,请原样使用返回的链接。链接默认 7 天有效,每次查询都重新签发;过期链接返回 401 与 10009036。详见文件下载。
