TF Fiscal
开发文档

发票邮件

把已授权的 NF-e / NFS-e / CT-e / DC-e 以邮件发给买方:模板与变量、正文 HTML 与图片、附件与下载链接、发件人规则、状态流转、幂等与 409、回调事件、错误模型与联调清单。

能力概述与接入流程

步骤接口说明
1 保存模板POST /openapi/v2/emails/templates租户级,所有主体共用;同一发票类型可有多份,padrao 标默认
2 登记回调POST /openapi/v1/webhooks在 eventos 里显式加上 email.sent 与 email.failed;不订阅就只能靠查询
3 发送POST /openapi/v2/empresas/{empresaId}/emails受理即返回 emailId,投递异步
4 查询GET /openapi/v2/empresas/{empresaId}/emails/{emailId}状态、等待原因、失败原因、实际发了什么
辅助GET .../emails/templates · GET .../emails/templates/{templateId}模板列表与详情,详情带可用变量清单

鉴权与其他开放接口相同:请求头 token / timestamp / sign,见认证与签名。邮件只在你调用发送接口时才发,票授权时不会自动发。

模板与发送的关系

  • 模板属于集成商(租户级),不绑定主体;任何已注册主体都可以用任何模板。
  • 每份模板固定一个发票类型(tipoDocumento)和一种语言(idioma)。同一类型可以有多份,例如每种语言一份。
  • 每个发票类型最多一份默认模板(padrao = true),不分语言。发送时不传 templateId 就用它,没有默认返回 10021012;要用非默认的模板,发送时传 templateId。
  • 把某份模板置为默认会自动取消同类型原来的默认;停用(ativo = false)的模板不能用于发送,也不能当默认。
  • 保存是整份覆盖:传 templateId 时所有字段都要重传,可选字段不传就回到缺省。
  • 发送时模板必须启用且类型与单据一致,否则 10021002。

变量替换

在主题与正文里写 {{名字}},名字以字母开头,可含字母、数字、下划线与点,花括号内可有空格。保存时按发票类型校验白名单,未知名字返回 10021003;渲染时无值的变量成空文本。正文里的取值经 HTML 转义,主题里不转义。

四类单据共有:

变量含义
numero票号
serie系列号
chaveAcesso访问密钥,44 位或 50 位
dataEmissao开票时间,圣保罗时区
valorTotal票面总额:NF-e 取票总额,NFS-e 取服务金额,CT-e 取运输服务总额,DC-e 取申报总额
emitente.nome开票主体名称
emitente.cnpj开票主体 CNPJ
cliente.nome收件方名称:NF-e 买方,NFS-e 与 CT-e 承担方,DC-e 收货人
cliente.documento收件方证件号,CPF 或 CNPJ
linkPdfPDF 凭证下载链接
linkXml授权 XML 下载链接;XML 尚未归档时为空

按类型专属:

类型变量含义
NFSecodigoVerificacaoNFS-e 校验码
NFSemunicipio开票主体所在市镇名称
NFSedescricaoServico服务描述
NFSevalorIssISS 税额
CTeremetente.nome发货人名称
CTedestinatario.nome收货人名称
CTevalorFrete运费总额
DCemarketplace.site平台站点,取自主体的 DC-e 档案

金额与日期按模板 idioma 格式化:pt / es 为 1.234,56 与 dd/MM/yyyy HH:mm;en / zh 为 1,234.56 与 yyyy-MM-dd HH:mm。时刻一律按圣保罗时区展示。查询模板的 variaveisDisponiveis 就是该类型的完整清单。

正文 HTML 与图片

正文只拒绝不清洗:超出白名单的内容在保存时返回 10021004 并点名位置。允许的标签:p、div、span、br、hr、h1 到 h6、strong、b、em、i、u、s、ul、ol、li、blockquote、table、thead、tbody、tr、th、td、a、img;允许的属性:style、href、src、alt、width、height、align、colspan、rowspan。style 里不能有 url(、expression(、position:、behavior:;href 只接受 https:、mailto:、{{linkPdf}}、{{linkXml}};正文上限 64 KB。

图片只能引用 https 地址。 平台没有图片上传接口,logo 请放在你自己的公网地址上。http 图片会被邮件客户端标为混合内容,内联的 data: 图片在部分网页邮箱里不显示,两者都在保存时被拒绝。带 logo 与按钮的完整例子见保存邮件模板。

附件与下载链接

  • enviarPdf = true 附上 PDF 凭证(DANFE / DANFSe / DACTE / DACE),enviarXml = true 附上授权 XML 原件;文件名 {tipo}-{chave}.pdf / .xml。
  • 凭证或 XML 尚未就绪时邮件不会缺件发出,而是停在 Aguardando(motivoEspera 为 pdf 或 xml),每 30 秒重查,最长 120 分钟,超时转 Falha。
  • 不附文件也可以在正文里放 {{linkPdf}} / {{linkXml}} 下载链接;链接有效期按集成商的文件链接设置,缺省 7 天。

发件人与收件人

  • 发件地址是平台地址,不能自定义发件邮箱或域名;显示名为开票主体的公司名,回复地址为主体注册的邮箱,客户回信会到主体那里。
  • 收件人 destinatarios 最多 5 个;不传时取开票时给的买方邮箱,只有 NF-e 与 NFS-e 有,CT-e 与 DC-e 必须显式传。都没有返回 10021013。
  • 地址会去重、域名转小写;受理响应与查询里的 destinatarios 是归一化后的实际收件人。

状态流转

text
Aguardando ──► Enfileirado ──► Enviando ──┬──► Enviado(终态)
└──► Falha(终态)
状态含义是否终态
Aguardando已受理,等票的数据到齐;motivoEspera 为 chaveAcesso / pdf / xml否
Enfileirado待发送,数据已齐否
Enviando正在渲染与出站否
Enviado发信服务已接收是
Falha终态失败,motivoFalha 说明原因是

Aguardando 只在缺密钥(圣保罗 NFS-e 的 50 位密钥由全国环境稍后回填)、缺 PDF 或缺 XML 时出现,不消耗重试次数。出站失败按递增间隔重试,最多 5 次,用尽转 Falha。Falha 的其他原因:票已不再是授权态、受理后模板被停用、凭证不可出具。

幂等与 409

  • id 是幂等键,主体内唯一。同 id 重复请求返回原受理结果,不会再建一封邮件,请求体不同也一样;响应里的 status 是当前状态。
  • 同一张票(同主体、同 tipoDocumento、同 documentoId)上一封邮件未到终态前,换 id 再发返回 HTTP 409 与 10021015,消息带在途邮件的 emailId 与状态。等回调或查询到 Enviado / Falha 后,用新的 id 重发。

回调事件

在注册 Webhook的 eventos 里显式加上 email.sent 与 email.failed,这两个事件只推给显式订阅的应用。载荷是统一事件体,data 字段名为下划线风格:

json
{
"version": "1.0",
"event_id": "1950000000000006",
"event_type": "email.sent",
"occurred_at": "2026-09-28T12:00:31Z",
"data": {
"email_id": "2103160000000000001",
"id": "email-pedido-8842-1",
"tipo_documento": "NFe",
"documento_id": "pedido-8842",
"chave": "35241204893402000113650010000117691017244265",
"destinatarios": ["comprador@exemplo.com"],
"status": "Enviado",
"motivo_falha": null
}
}
事件触发data.status
email.sent发信服务已接收Enviado
email.failed终态失败,data.motivo_falha 说明原因Falha

email.sent 表示发信服务接收了邮件,不代表已进入收件人邮箱。完整字段说明见 Webhooks。

错误模型

对外端点返回无包装的数组:

json
[{"codigo": "10021013", "mensagem": "Sem destinatário: destinatarios não informado e o documento não tem e-mail do cliente"}]
码HTTP含义处置
10001001400字段校验失败按消息修正
10003000404主体不存在核对 empresaId
10021001404模板不存在或不属于本集成商核对 templateId
10021002400模板已停用,或类型与单据不符换模板或启用
10021003400模板引用了白名单外的变量按消息里的名字修正
10021004400模板 HTML 含禁止内容或超过 64 KB按消息点名的位置修正
10021005400发票类型不支持只用 NFe / NFSe / CTe / DCe
10021010404发票不存在或不属于本主体核对 documentoId 与 tipoDocumento
10021011400发票尚未授权等授权后再发
10021012400该类型没有默认模板传 templateId 或标一个默认
10021013400没有收件人传 destinatarios
10021015409同票上一封邮件在途等终态后用新 id 重发
10021020404邮件不存在或不属于本主体核对 emailId

鉴权与授权错误(10009xxx)见认证与签名,完整错误码表见错误码。

联调清单

  1. 保存一份 NFe 模板并标 padrao = true,确认响应里 variaveisDisponiveis 有 11 项。
  2. 故意在正文里写 {{codigoVerificacao}},确认收到 10021003;把图片改成 http 地址,确认收到 10021004。
  3. 在 Webhook 的 eventos 里加上 email.sent 与 email.failed。
  4. 对一张已授权的 NF-e 发送(enviarPdf 与 enviarXml 都为 true,不传 destinatarios),确认受理为 Enfileirado,随后收到 email.sent,查询里 assunto 与 enviadoEm 有值。
  5. 在上一封到终态前用另一个 id 再发同一张票,确认收到 409 与 10021015;用同一个 id 再发,确认返回原 emailId。
  6. 对一张圣保罗 NFS-e 发送,确认受理为 Aguardando 且 motivoEspera 为 chaveAcesso,密钥回填后自动转 Enviado。