TF Fiscal
Documentation

DC-e

DC-e (model 99, Declaração de Conteúdo Eletrônica) issuance on behalf of marketplaces and companies, including onboarding, webhook payloads, error model, state machine and integration checklist.

Overview and onboarding flow

The DC-e (model 99, Declaração de Conteúdo Eletrônica, Ajuste SINIEF 05/2021) is the electronic content declaration that accompanies shipments of goods sent by non-taxpayers, issued on their behalf by a marketplace, or by a company for itself. Company registration, certificate association and webhook registration are shared with NF-e; the resource segment keeps the document's original dc-e and every document-level operation lives under /dc-e/{dceId}.

StepAPINotes
1 Register companyPOST /openapi/v2/empresasSame as NF-e, with the optional emissaoDCe section; at least one of emissaoNFeProduto / emissaoDCe is required, a DC-e-only integrator may omit the NF-e block; a body carrying id is an update
2 Link certificatePOST /openapi/v1/empresas/{empresaId}/certificadoDigitalSame as NF-e
3 Register webhookPOST /openapi/v1/webhooksSame as NF-e; DC-e results reuse the same callback URL
4 IssuePOST /openapi/v2/empresas/{empresaId}/dc-eAccepted immediately (200, no body); authorized asynchronously with SEFAZ
5 QueryGET /openapi/v2/empresas/{empresaId}/dc-e/{dceId}Status, protocol, XML / DACE download links, request echo
6 CancelDELETE /openapi/v2/empresas/{empresaId}/dc-e/{dceId}Within 24 hours after authorization; asynchronous: 200 with no body, result via webhook

Authentication is identical to NF-e: headers token / timestamp / sign, with sign = MD5(token + path + body + timestamp) as lowercase hex; path includes the /openapi prefix and path variables and excludes the query string; GET / DELETE without a body use an empty string; a DELETE with a body (cancellation with a reason) signs the raw JSON with CR/LF removed. See Authentication.

Prerequisites

  • The company must be approved with a usable certificate (otherwise DCe00008). The DC-e authorizer is SEFAZ-PR (the only authorizer listed on the national DC-e portal); companies from every state are routed to it.
  • The company must have its DC-e issuance parameters configured: emissaoDCe.tipoEmitente and a model 99 number series (sequencialDCe / serieDCe); missing either returns DCe00004.
  • Phase one supports two issuer types: Marketplace (a platform issuing on behalf of non-taxpayer sellers / individuals) and OwnIssuer (a company issuing for itself). Carrier can be registered but issuance is rejected (10019013) until SVRS publishes the new schema package.
  • ambiente in the request must match the company's current environment, otherwise DCe00004 (document wording: "not configured for the informed environment"). After registration the company is in the certification environment (Homologacao); switching to production is an operations action with no API, and sending ambiente=Producao before the switch returns DCe00004.
  • Phase one supports normal issuance only (tpEmis=1); offline contingency comes in phase two.

Company registration: the emissaoDCe section

Register company accepts an optional emissaoDCe section (all other fields unchanged):

json
"emissaoDCe": {
"ambienteProducao": {
"tipoEmitente": "Marketplace",
"sequencialDCe": 1,
"serieDCe": "1",
"siteMarketplace": "https://loja.exemplo.com.br"
}
}
FieldTypeRequiredDescription
tipoEmitentestringyesMarketplace / OwnIssuer (document alias EmissorProprio) / Carrier (alias Transportadora; registration allowed, issuance rejected)
sequencialDCeintegeryesFirst nDC (1-999999999); the platform numbers sequentially from it
serieDCestringyesSeries (0-999, up to 3 digits)
siteMarketplacestringRequired for MarketplacePlatform site (2-120 characters), written to XML Marketplace/Site and to the DACE
  • A company registered without emissaoDCe is not enabled for DC-e: registration still succeeds, but the response carries dceHabilitado=false and issuance returns DCe00004. Check that field right after registering.
  • To enable DC-e later, raise the starting number or fix contact details, resend the registration payload with id. The model 99 series only moves up; the full update rules are on the Register company page.

Endpoints

EndpointPurpose
Issue DC-ePOST /openapi/v2/empresas/{empresaId}/dc-e, accepted with HTTP 200 and no body; idempotent on id
Query DC-eGET /openapi/v2/empresas/{empresaId}/dc-e/{dceId}, status, protocol, download links and request echo
Cancel DC-eDELETE /openapi/v2/empresas/{empresaId}/dc-e/{dceId}, asynchronous, within 24 hours after authorization

Webhook payload

Webhook registration and signature headers are shared with NF-e; register the callback URL with Register webhook. Delivery request headers: besides the five platform signature headers (X-Tffiscal-Event / X-Tffiscal-Event-Id / X-Tffiscal-Delivery-Id / X-Tffiscal-Timestamp / X-Tffiscal-Signature), every delivery carries both token and x-token with the same value (the token registered with the webhook, sent back verbatim); the receiver may verify either one.

Event codes and the compatibility payload (tipo="DC-e", 14 fields in fixed order):

Event codeTriggerdceStatus
dce.authorizedAuthorization 100Autorizada
dce.rejectedSEFAZ rejection or terminal task failure (including failures before the document is numbered, which have no chave)Negada (dceMotivoStatus is cStat - reason; a terminal failure without cStat carries the reason only)
dce.canceledCancellation registered (135 / 136 / 155)Cancelada (dceDataAutorizacao is the cancellation registration time, dceNumeroProtocolo the cancellation event protocol)
dce.cancel_rejectedSEFAZ rejected the cancellation or the cancellation task failed terminallyCancelamentoNegado (the document stays authorized; carries the authorization protocol / digest / XML link)

Payload fields

FieldTypeDescription
tipostringAlways DC-e
empresaIdstringCompany identifier
dceIdstringThe id sent at issuance; correlate deliveries by this field
dceStatusstringAutorizada / Negada / Cancelada / CancelamentoNegado
dceMotivoStatusstringcStat - xMotivo on rejection or cancellation rejection, the failure reason on terminal failure; null otherwise
dceLinkDacestringDACE link lazily rendered by chave (authorized / cancelled callbacks); null on rejection
dceLinkXmlstringXML download link; null when there is no authorized XML
dceNumerostringDC-e number; null when the document was never numbered
dceSeriestringDC-e series; null when the document was never numbered
dceChaveAcessostring44-digit access key; null when the document was never numbered
dceDataEmissaostringIssue time; the acceptance time for failures before numbering
dceDataAutorizacaostringAuthorization time; the cancellation registration time in dce.canceled; null otherwise
dceNumeroProtocolostringAuthorization protocol; the cancellation event protocol in dce.canceled; null on rejection
dceDigestValuestringSignature digest of the authorized document; null on rejection and in dce.canceled

dce.authorized

json
{ "tipo": "DC-e", "empresaId": "1934811222334455", "dceId": "DCe-000012333", "dceStatus": "Autorizada", "dceMotivoStatus": null,
"dceLinkDace": "https://api.v2.tffiscal.com/openapi/files/dace/35260940673061000134990010000000011100000012?token=...", "dceLinkXml": "https://api.v2.tffiscal.com/openapi/files/xml/7?token=...",
"dceNumero": "1", "dceSerie": "1", "dceChaveAcesso": "41260940673061000134990010000000011101234567",
"dceDataEmissao": "2026-09-06T12:00:00Z", "dceDataAutorizacao": "2026-09-06T12:00:03Z",
"dceNumeroProtocolo": "141260000000001", "dceDigestValue": "tasG40Ic6Zh7PIBiLEEH7Hb940Y=" }

dce.rejected

json
{ "tipo": "DC-e", "empresaId": "1934811222334455", "dceId": "DCe-000012333", "dceStatus": "Negada",
"dceMotivoStatus": "225 - Rejeicao: Falha no schema XML", "dceLinkDace": null, "dceLinkXml": null,
"dceNumero": "1", "dceSerie": "1", "dceChaveAcesso": "4126...", "dceDataEmissao": "2026-09-06T12:00:00Z",
"dceDataAutorizacao": null, "dceNumeroProtocolo": null, "dceDigestValue": null }

Failure before numbering (company not configured for DC-e / missing series / message mapping failure and other terminal failures where the document was never numbered and has no chave): dce.rejected is still delivered, the document fact fields are null, dceMotivoStatus carries the failure reason and dceDataEmissao the acceptance time. Correlate by dceId and never assume dceChaveAcesso is present:

json
{ "tipo": "DC-e", "empresaId": "1934811222334455", "dceId": "DCe-000012333", "dceStatus": "Negada",
"dceMotivoStatus": "Empresa não configurada para emissão de DC-e", "dceLinkDace": null, "dceLinkXml": null,
"dceNumero": null, "dceSerie": null, "dceChaveAcesso": null, "dceDataEmissao": "2026-09-06T12:00:00Z",
"dceDataAutorizacao": null, "dceNumeroProtocolo": null, "dceDigestValue": null }

dce.canceled

json
{ "tipo": "DC-e", "empresaId": "1934811222334455", "dceId": "DCe-000012333", "dceStatus": "Cancelada", "dceMotivoStatus": null,
"dceLinkDace": "https://.../openapi/files/dace/35260940673061000134990010000000011100000012?token=...", "dceLinkXml": "https://.../openapi/files/xml/7?token=...",
"dceNumero": "1", "dceSerie": "1", "dceChaveAcesso": "4126...", "dceDataEmissao": "2026-09-06T12:00:00Z",
"dceDataAutorizacao": "2026-09-06T15:00:00Z", "dceNumeroProtocolo": "141260000000099", "dceDigestValue": null }

dce.cancel_rejected

json
{ "tipo": "DC-e", "empresaId": "1934811222334455", "dceId": "DCe-000012333", "dceStatus": "CancelamentoNegado",
"dceMotivoStatus": "594 - Rejeicao: O numero de sequencia do evento informado e maior que o permitido",
"dceLinkDace": null, "dceLinkXml": "https://.../openapi/files/xml/7?token=...", "dceNumero": "1", "dceSerie": "1",
"dceChaveAcesso": "4126...", "dceDataEmissao": "2026-09-06T12:00:00Z", "dceDataAutorizacao": null,
"dceNumeroProtocolo": "141260000000001", "dceDigestValue": "tasG40Ic6Zh7PIBiLEEH7Hb940Y=" }

In the authorized / cancelled callbacks dceLinkDace is the DACE link lazily rendered by chave (nothing is rendered at delivery time; the first download renders and archives it); both links share the query API shape (/openapi/files/{kind}/{ref}?token=…) and their lifetime comes from the tenant-level setting (default 7 days). See File download.

Error model

Same shapes as NF-e: business errors are [{ "codigo", "mensagem" }] (HTTP 400; a missing document / task is HTTP 404 with codigo DCe0001); authentication-layer errors use the platform envelope (401 / 403 / 429, see Authentication). Cases with a documented example code reuse the document's code; every other codigo is the platform's numeric error code, and mensagem is localized by request language (Portuguese uses the document wording).

codigoHTTPScenarioAction
DCe0001404dceId not found, not owned by the company, or cancellation requested before the document was materializedCheck id and empresaId; cancel Pendente documents only after authorization
10003000404empresaId not foundCheck empresaId
DCe00004400Company not configured for DC-e (missing tipoEmitente / model 99 series / Marketplace site), or ambiente differs from the company's current environmentSend emissaoDCe at registration or through an update with id; submit for the company's current environment and ask operations for the production switch
DCe00005 / DCe00006 / DCe00007400Marketplace / Carrier company without remetente / remetente.endereco missing / Brazilian sender without cpfCnpjAdd the sender data
DCe00008400Company cannot issue (not approved / certificate not ready)Wait for approval / link the certificate
DCe00009400Brazilian recipient without cpfCnpjAdd the recipient document
GW001400Municipality IBGE code not found or inconsistent with ufCheck cidade / uf
10019005 / 10019006400Concurrent duplicate request / too many pending tasks for the CNPJRetry later
10019007400Number series unresolved (several enabled series)Ask operations to consolidate the series
10019013400Issuer type Carrier not supported for issuance yetUse a Marketplace / OwnIssuer company
1001901810019022400Invalid item / enum or format / carrier CNPJ / additional information too long / autorizacaoDownloadXmlFix per mensagem
10019030 / 10019031400Same id with a different message / production: an active or authorized document already exists for the idUse a new id or resend the original message / query the original
10019040 / 10019041 / 10019042 / 10019043400Status does not allow cancellation / 24-hour window exceeded / cancellation already accepted / invalid reasonSee Cancel DC-e
10019048400dataEmissao outside the allowed window (more than 5 minutes ahead or more than 30 days back)Use the current time or omit dataEmissao
10001001400Request field validation failed (one entry per field); registration / update contract errorsFix per mensagem

The per-endpoint code lists are on Issue DC-e, Query DC-e and Cancel DC-e. SEFAZ rejections during issuance are not HTTP errors: they surface as query status Negada and the dce.rejected webhook; SEFAZ rejections of the cancellation surface as dce.cancel_rejected.

State machine

text
Accepted (POST 200) ─→ Pendente ─number + send to SEFAZ─┬─ cStat 100 ─→ Autorizada ─DELETE 200─→ CancelamentoPendente ─┬─ 135/136/155 ─→ Cancelada
│ └─ SEFAZ rejection ─→ Autorizada (webhook CancelamentoNegado)
├─ other terminal cStat ─→ Negada
└─ unparseable parameters / retry budget exhausted ─→ Falha (same id may be resubmitted)
  • While Pendente, SEFAZ outages (108 / 109) are retried with back-off by the platform; there is no contingency rerouting in phase one. Duplicate issuance (451 / 452 / 539) is reconciled by querying SEFAZ first.
  • After Negada / Falha the same id may be resubmitted (reopened with the new message); after Autorizada a resubmission with the same id only hits idempotency.

Notes

  • The CNPJ in the key is the platform company: positions 7-20 always carry the authorized issuer (the Marketplace company or the self-issuing company); a CPF sender only appears in the XML emit group and in the DACE REMETENTE block.
  • Fixed recipient name in the certification environment: with tpAmb=2 the recipient name in the XML and DACE is DCE EMITIDA EM AMBIENTE DE HOMOLOGACAO (SEFAZ validation 598); the query echo keeps the original.
  • 24-hour cancellation window: counted from the authorization time; after it the document can only be kept. The official DC-e has cancellation only: no correction letter, no number invalidation.
  • Carrier not supported yet: the current official schema restricts tpEmit to Marketplace / own issuer; a registered carrier company is rejected with 10019013 at issuance.
  • DACE: A4 portrait, rendered on demand and cached; re-rendered with the CANCELADA watermark after cancellation; the certification environment carries the SEM VALOR FISCAL - HOMOLOGAÇÃO watermark.
  • Authorizer: DC-e from every state goes to the SEFAZ-PR authorizer; the QR code points to https://www.fazenda.pr.gov.br/dce/qrcode?chDCe={chave}&tpAmb={tpAmb}.

Integration checklist

  1. In the certification environment: company registered (with emissaoDCe, response dceHabilitado=true confirmed), certificate linked, webhook registered (receiver accepts both token / x-token).
  2. Issue a minimal DC-e (the example on Issue DC-e), query it as Autorizada, download the XML and the DACE, receive the dce.authorized callback.
  3. Resend the same id once and confirm HTTP 200 with no second document; change one item and resend, confirm 10019030.
  4. Cancel the document: confirm 200 with no body, query CancelamentoPendenteCancelada, receive the dce.canceled callback, DACE carries the watermark.
  5. Cancel the cancelled document again and confirm 10019040; query a non-existent id and confirm 404 DCe0001.
  6. Send deliberate errors (ambiente=Producao, cidade=9999999, missing remetente) and confirm the 400 error array with codes DCe00004 / GW001 / DCe00005.
  7. Issue for a company not enabled for DC-e and confirm DCe00004; resend the registration payload with id and a higher sequencialDCe, confirm 200 and that the next document starts from the new number; resend a lower number and confirm 400 10001001.