Pular para o conteúdo

CT-e ​

Emita CT-e de qualquer tipo de serviço pelas empresas da conta, acompanhe a autorização por polling, baixe o XML e registre cancelamento e carta de correção. A inutilização foi descontinuada. Precisa de uma empresa pronta, com o certificado enviado. Para ser avisado das mudanças, cadastre um webhook.

Os caminhos abaixo são completos, a partir do domínio https://api.logmonitor.com.br. As escritas (POST) levam assinatura e Idempotency-Key. Aqui o {id} é o UUID do documento, devolvido na emissão. A {chave} é a chave de acesso, com 44 dígitos. As rotas de CT-e exigem também que o plano da conta inclua a API de emissão (403 feature_indisponivel, veja escopos).

Situações ​

O campo status do documento segue o emissor:

PENDENTE → AUTORIZADO ou REJEITADO. Na contingência offline, o CT-e passa antes por PENDENTE_CONSULTA. Depois de autorizado, o CT-e pode virar CANCELADO.

  • PENDENTE: a emissão foi aceita e a SEFAZ ainda não deu o veredito.
  • PENDENTE_CONSULTA: só na contingência offline. O CT-e foi emitido sem a SEFAZ e está à espera do veredito. O detalhe traz xml_contingencia, para imprimir o DACTE.
  • AUTORIZADO: tem chave, protocolo e, em seguida, o XML (xml_disponivel).
  • REJEITADO: codigo_status_sefaz e motivo_sefaz dizem o porquê. Corrija o dado e emita de novo.
  • CANCELADO: o cancelamento foi homologado.

Emitir ​

Emitir um CT-e ​

POST /services/v1/integracoes/ctes · ctes:emitir

A emissão é assíncrona: a resposta é 202 e o veredito da SEFAZ chega depois.

  1. POST /services/v1/integracoes/ctes → 202, com data.id e data.status PENDENTE.
  2. GET /ctes/{id} a cada poucos segundos, até o status ser final (AUTORIZADO ou REJEITADO).
  3. Para acompanhar vários de uma vez, liste com atualizado_desde.
  4. Com AUTORIZADO, baixe o XML.

Corpo mínimo de um CT-e normal:

json
{
  "conteudo": {
    "identificacao": {
      "serie": "1",
      "numero": 1234,
      "tipoServico": "0",
      "origem": {
        "municipio": "5107602",
        "nome": "Rondonópolis",
        "uf": "MT"
      },
      "destino": {
        "municipio": "5103403",
        "nome": "Cuiabá",
        "uf": "MT"
      }
    },
    "emitente": {
      "cnpj": "00000000000000",
      "ie": "000000000",
      "crt": "3",
      "razaoSocial": "TRANSPORTADORA EXEMPLO LTDA",
      "endereco": {
        "uf": "MT"
      }
    },
    "tomador": {
      "tipo": "0"
    },
    "remetente": {
      "cnpjCpf": "00000000000000",
      "ie": "000000000",
      "razaoSocial": "REMETENTE EXEMPLO",
      "endereco": {
        "logradouro": "RUA A",
        "numero": "1",
        "bairro": "CENTRO",
        "municipio": "5102678",
        "uf": "MT",
        "cep": "78000000"
      }
    },
    "destinatario": {
      "cnpjCpf": "00000000000000",
      "ie": "000000000",
      "razaoSocial": "DESTINATARIO EXEMPLO",
      "endereco": {
        "logradouro": "RUA B",
        "numero": "2",
        "bairro": "CENTRO",
        "municipio": "5103403",
        "uf": "MT",
        "cep": "78000000"
      }
    },
    "carga": {
      "valor": 64101.33,
      "produtoPredominante": "SOJA EM GRAOS",
      "quantidades": [
        {
          "unidade": "01",
          "tipoMedida": "PESO BRUTO",
          "quantidade": "32320.0000"
        }
      ]
    },
    "documentos": [
      {
        "tipo": "nfe",
        "chave": "00000000000000000000000000000000000000000000"
      }
    ]
  }
}

Os campos do corpo:

  • conteudo: o CT-e. identificacao (serie, numero, tipoServico, origem, destino), emitente, tomador, as partes (remetente, destinatario), carga e documentos.
  • conteudo.emitente.cnpj: o CNPJ (só dígitos) da empresa emitente. É por ele que a API acha a empresa cadastrada; o ambiente é o da credencial.
  • tipoEmissao: opcional. normal (padrão), offline (veja a contingência offline), svc-rs ou svc-sp.

Tipos de emissão extintos

epec e fsda foram extintos pela SEFAZ. Enviar qualquer um dos dois devolve 422 de validação, com a recusa em data.errors.tipoEmissao.

O tipoServico escolhe o tipo de CT-e. Todos são aceitos com o escopo ctes:emitir:

tipoServicoTipoO que muda no corpo
0Normaltomador { "tipo": "0" } (o remetente) e documentos com as NF-e.
1Serviço contratado de outra transportadoratomador com "tipo": "4" e os dados do contratante; documentosAnteriores com o CT-e dele.
2RedespachoComo o tipo 1.
3Redespacho intermediárioComo o redespacho, sem documentos próprios: só documentosAnteriores.
4Vinculado a multimodalSem documentos próprios.

Exemplo do trecho que muda no tipo 1:

json
{
  "conteudo": {
    "identificacao": {
      "tipoServico": "1"
    },
    "tomador": {
      "tipo": "4",
      "cnpjCpf": "00000000000000",
      "ie": "000000000",
      "razaoSocial": "CONTRATANTE EXEMPLO S/A"
    },
    "documentosAnteriores": [
      {
        "emitente": {
          "cnpjCpf": "00000000000000",
          "ie": "000000000",
          "razaoSocial": "CONTRATANTE EXEMPLO S/A"
        },
        "eletronicos": [
          {
            "chave": "00000000000000000000000000000000000000000000"
          }
        ]
      }
    ]
  }
}

Contingência offline ​

Com tipoEmissao: "offline", o CT-e é emitido sem a SEFAZ no ar e enviado a ela depois. Dois campos de conteudo.identificacao passam a ser obrigatórios:

  • dataContingencia: quando a contingência começou (ISO 8601, como 2026-11-04T09:30:00-04:00).
  • justificativaContingencia: o motivo, de 15 a 256 caracteres.
json
{
  "tipoEmissao": "offline",
  "conteudo": {
    "identificacao": {
      "dataContingencia": "2026-11-04T09:30:00-04:00",
      "justificativaContingencia": "SEFAZ indisponível na emissão."
    }
  }
}

O trecho acima mostra só o que muda; o resto do corpo é o de um CT-e normal. A emissão responde 202 e o CT-e fica em PENDENTE_CONSULTA. GET /ctes/{id} devolve o xml_contingencia, com o qual você imprime o DACTE enquanto espera. Ao fim, o status vira AUTORIZADO ou REJEITADO, como numa emissão normal.

Homologação de MT

A homologação da SEFAZ-MT ainda não aceita a contingência offline (cStat 215 em 04/11/2026). A produção está prevista para 14/12/2026, sem garantia de data. Teste o offline em outra UF.

Impostos e valores ​

  • conteudo.impostos.valorTotalDFe: obrigatório sempre que houver conteudo.impostos.ibsCbs. Sem ele, a resposta é 422 de validação.
  • conteudo.valoresPrestacao.totalLiquido: opcional.
json
{
  "conteudo": {
    "impostos": {
      "valorTotalDFe": 12500.00,
      "ibsCbs": {}
    }
  }
}

O ibsCbs está vazio de propósito: o exemplo mostra só a regra do valorTotalDFe.

A mesma numeração (série e número) já enviada não é reenviada: a resposta traz situacao_envio existente.

Resposta 202 (data): o documento (veja o detalhe) em PENDENTE, mais situacao_envio.

Erros:

  • 404: não há empresa com o CNPJ de conteudo.emitente.cnpj na conta.
  • 403 empresa_fora_da_integracao: a empresa existe, mas o CNPJ não está entre os da credencial.
  • 422 certificado_ausente: a empresa está pendente_certificado. Envie o certificado e emita de novo.
  • 422 ambiente_indisponivel: credencial de produção com a conta ainda em homologação.
  • 422 numero_em_uso: a numeração já existe; data.proximo_numero traz o próximo livre.
  • 422 de validação, com data.errors, ou com a message do dado que falta.
  • Repetir a mesma Idempotency-Key devolve a mesma resposta (idempotência).

Veja a lista completa em respostas e erros.

Acompanhar ​

Listar ​

GET /services/v1/integracoes/ctes · ctes:ler

Parâmetros de consulta, todos opcionais:

  • atualizado_desde: só os CT-e alterados a partir deste instante (ISO 8601, como 2026-10-05T14:30:00-04:00).
  • cnpj: o CNPJ do emitente, só dígitos.
  • status: PENDENTE, PENDENTE_CONSULTA, AUTORIZADO, REJEITADO, CANCELADO.
  • por_pagina: de 1 a 100 (padrão 50). A página vem em page.

Sem atualizado_desde, a lista vai do mais recente ao mais antigo. Com ele, vai do mais antigo ao mais novo, para o polling: guarde o atualizado_em do último item lido e use-o como o próximo atualizado_desde. O filtro é "a partir de" (>=): o último item pode voltar, então ignore o que você já processou, pelo id. Veja também acompanhar.

Resposta 200 (data): a página, com os documentos em data.data (cada um como no detalhe, com xml_disponivel), mais current_page, per_page, total e last_page.

Detalhe ​

GET /services/v1/integracoes/ctes/{id} · ctes:ler

O {id} é o UUID que a emissão devolveu. Um número não serve: o CT-e não é achado (404). Enquanto não há veredito, cada chamada consulta o emissor: use esta rota para o polling até AUTORIZADO ou REJEITADO.

json
{
  "id": "00000000-0000-0000-0000-000000000000",
  "chave": "00000000000000000000000000000000000000000000",
  "serie": "1",
  "numero": 1234,
  "ambiente": "homologacao",
  "status": "AUTORIZADO",
  "codigo_status_sefaz": 100,
  "motivo_sefaz": "Autorizado o uso do CT-e",
  "protocolo": "000000000000000",
  "tipo_emissao": "normal",
  "xml_contingencia": null,
  "xml_disponivel": true,
  "cancelamento_solicitado_em": null,
  "criado_em": "2026-10-01T17:11:40+00:00",
  "atualizado_em": "2026-10-01T17:11:58+00:00",
  "finalizado_em": "2026-10-01T17:11:58+00:00"
}

Resposta 200 (data): o documento acima. chave e protocolo só existem depois da autorização. tipo_emissao é o que você enviou, e xml_contingencia só vem preenchido em PENDENTE_CONSULTA.

Erros: 404 "Documento fiscal não encontrado": o UUID não existe, é de outra conta ou de empresa fora dos CNPJs da credencial.

Baixar o XML ​

GET /services/v1/integracoes/ctes/{id}/xml · ctes:ler

Resposta 200: o XML autorizado (application/xml, fora do envelope), como anexo <chave>.xml. O download fica registrado na trilha do documento.

Erros: 404 "O XML do CT-e ainda não está disponível.": antes da autorização, ou documento de outra conta.

Eventos ​

Registrar um evento ​

POST /services/v1/integracoes/ctes/{chave}/eventos · ctes:eventos

Registra o evento num CT-e autorizado. O tipo escolhe qual:

  • cancelamento: justificativa, de 15 a 255 caracteres.
  • carta-correcao: correcoes, uma lista com grupoAlterado, campoAlterado, valorAlterado e, opcional, nroItemAlterado.
json
{
  "tipo": "cancelamento",
  "justificativa": "Prestação de serviço cancelada pelo contratante."
}
json
{
  "tipo": "carta-correcao",
  "correcoes": [
    {
      "grupoAlterado": "toma3",
      "campoAlterado": "xNome",
      "valorAlterado": "TRANSPORTADORA EXEMPLO LTDA"
    }
  ]
}

O emissor responde 202, e o veredito vem depois: consulte os eventos.

Cancelar um CT-e que já está cancelado não é erro: o pedido é idempotente e responde 200, com data.status CANCELADO e a mensagem "O documento já estava cancelado na SEFAZ.".

Resposta 202 (data): idEvento e o estado do envio.

Erros:

  • 404: a chave não é de um documento desta credencial (outra conta, ou empresa fora dos CNPJs dela).
  • 422 modelo_incompativel: o evento não vale para o modelo da chave, por exemplo carta-correcao numa chave de MDF-e (use as rotas de MDF-e).
  • 422 de validação: tipo fora de cancelamento e carta-correcao (é o caso de encerramento numa chave de CT-e), ou campo do evento faltando.
  • 422 documento_encerrado: a situação do documento não aceita o evento.
  • 409 cancelamento_ja_solicitado: o cancelamento já foi pedido; aguarde o veredito da SEFAZ.
  • 403: a credencial não pode fazer o evento neste documento (recusas 403).

Listar os eventos ​

GET /services/v1/integracoes/ctes/{chave}/eventos · ctes:ler

Resposta 200 (data): a lista de eventos, cada um com tipo, codigoStatusSefaz, motivoSefaz e numeroProtocolo. Sem eventos, lista vazia.

json
[
  {
    "tipo": "cancelamento",
    "codigoStatusSefaz": 135,
    "motivoSefaz": "Evento registrado e vinculado a CT-e",
    "numeroProtocolo": "000000000000000"
  }
]

Erros: 404.

Inutilizar uma numeração (descontinuada) ​

POST /services/v1/integracoes/ctes/inutilizacoes · ctes:eventos

Descontinuada

A inutilização foi descontinuada no CT-e 4.00. A rota continua existindo, mas todo pedido é recusado. Um número sem uso não precisa ser inutilizado.

Resposta 422, para qualquer corpo válido:

json
{
  "status": "error",
  "codigo": "cte.inutilizacao-descontinuada",
  "identifier": 1790000000,
  "message": "A inutilização foi descontinuada no CT-e 4.00.",
  "data": null,
  "return_type": "ERROR"
}

Antes da recusa da SEFAZ, valem as checagens de sempre: 404 se a empresa não existe na conta, 403 empresa_fora_da_integracao, 422 conta_em_homologacao e 422 de validação.

Corpo do pedido (mantido só como referência):

json
{
  "emitente": { "cnpj": "00000000000000" },
  "ano": 26,
  "serie": 1,
  "numeroInicial": 1230,
  "numeroFinal": 1233,
  "justificativa": "Numeração pulada por falha de sistema."
}
  • emitente.cnpj: a empresa emitente, só dígitos.
  • ano: o ano com dois dígitos.
  • serie, numeroInicial e numeroFinal: a faixa.
  • justificativa: no mínimo 15 caracteres.

Documentação da API da Subcontratei.