openapi: 3.0.3 info: title: AppCTE API description: | Documentação das **APIs públicas de integração** do AppCTE. **URL base:** `https://app.appcte.com.br` Cada operação abaixo descreve autenticação, parâmetros e formatos do respectivo recurso. Novos endpoints serão incluídos nesta mesma especificação conforme forem disponibilizados. ## Convenções - Requisições e respostas em **JSON** (`Content-Type: application/json`), salvo indicação no endpoint. - Toda resposta inclui `request_id` — informe ao suporte em caso de dúvida. - Em operações em **lote**, HTTP `200` não garante sucesso de todos os itens; verifique o corpo da resposta. version: 2.1.3 contact: name: AppCTE servers: - url: / description: Mesma origem desta página — use Try it out no Swagger - url: https://app.appcte.com.br description: Produção (integração servidor-a-servidor) tags: - name: CT-e description: Emissão de Conhecimento de Transporte Eletrônico. paths: /api/cte_embarcador: post: tags: [CT-e] summary: Enviar lote de CT-e (integração embarcador) description: | Registra um ou mais CT-e para a transportadora emitente e, por padrão, solicita autorização na SEFAZ. **Content-Type:** `application/json` **Corpo:** array JSON na raiz — `[{ ... }, { ... }]`. Não envie `{ "itens": [...] }`. ### Autenticação (este endpoint) 1. Token de integração: `Authorization: Bearer ` (ou header `X-Embarcador-Token`). 2. CNPJ do emitente: header `X-Emitente-CNPJ` (14 caracteres, numérico ou alfanumérico). O token deve estar ativo para esse emitente. ### Transmissão e `chave` Padrão: grava e transmite na mesma requisição. Apenas gravar: `?transmit=0`. | `fase` | `chave` / `protocolo` | |--------|------------------------| | `autorizado` | Sim (44 dígitos + protocolo) | | `gravado_sem_transmissao` | Não — use `numero`, `serie`, `cte_id` | | `transmissao_rejeitada` | Não — veja `mensagem` e `detalhes` | ### Payload (por item do array) **Obrigatórios:** `Remetente`, `Destinatario`, `Tomador` (alias `Pagador`), `ValorTotalFrete` (> 0), `DadosNotaFiscal` (ao menos uma nota com `KeyNotaFiscal` de 44 dígitos). **Atores:** em cada parceiro, `CNPJCPF`, `RazaoSocial`, `Rua`, `Numero`, `Bairro`, `Cep` e `CidadeIBGE` ou `Cidade` + `UnidadeFederacao`. `Tomador` = pagador do frete (CNPJ igual ao remetente → tipo 0; ao destinatário → tipo 3; outro → tipo 4). **Opcionais:** `PesoTotal`, `NumeroProtocolo`, `ValorComposicaoFrete`, `DadosCIOT`, `DadosVPO`, `Observacoes`. O frete no CT-e é o valor de `ValorTotalFrete`. CFOP é calculado automaticamente (`cfop` na resposta). operationId: cteEmbarcadorPost security: - bearerAuth: [] - embarcadorToken: [] parameters: - $ref: '#/components/parameters/EmitenteCnpj' - name: transmit in: query description: | `1` ou omitido — grava e transmite (padrão). `0` — apenas grava (`fase: gravado_sem_transmissao`). schema: type: string enum: ['0', '1'] default: '1' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CteEmbarcadorRequest' examples: padrao: summary: Layout padrão — CT-e completo com CIOT e VPO value: - Remetente: CNPJCPF: "11111111000191" RazaoSocial: EMPRESA FICTICIA REMETENTE LTDA InscricaoEstadual: ISENTO Rua: RUA FICTICIA UM Numero: "100" Complemento: SALA 1 Bairro: BAIRRO FICTICIO Cidade: CIDADE FICTICIA A CidadeIBGE: "3550308" Cep: "01001000" UnidadeFederacao: SP TelefoneContato: "11999990001" TipoIdentificacao: CNPJ Destinatario: CNPJCPF: "22222222000192" RazaoSocial: EMPRESA FICTICIA DESTINATARIA LTDA InscricaoEstadual: ISENTO Rua: RUA FICTICIA DOIS Numero: "200" Bairro: BAIRRO FICTICIO Cidade: CIDADE FICTICIA B CidadeIBGE: "4106902" Cep: "80010000" UnidadeFederacao: PR Tomador: CNPJCPF: "11111111000191" RazaoSocial: EMPRESA FICTICIA REMETENTE LTDA InscricaoEstadual: ISENTO Rua: RUA FICTICIA UM Numero: "100" Bairro: BAIRRO FICTICIO Cidade: CIDADE FICTICIA A CidadeIBGE: "3550308" Cep: "01001000" UnidadeFederacao: SP ValorTotalFrete: 85.50 ValorComposicaoFrete: - CodigoServico: 1 DescricaoServico: FRETE PESO ValorServico: 45.00 - CodigoServico: 8 DescricaoServico: GRIS ValorServico: 25.50 - CodigoServico: 11 DescricaoServico: PEDAGIO ValorServico: 15.00 PesoTotal: 12000 PesoDensidadeCubagemTotal: 0.8 NumeroProtocolo: INT-FICTICIO-0001 DadosCIOT: Numero: "123456789012" CNPJ: "11111111000191" CNPJIPEF: "44444444000194" DadosVPO: NumeroCompra: "000000000001" Valor: 15.00 CNPJFornecedor: "55555555000195" tpValePed: "01" DadosNotaFiscal: - CNPJCPFEmissorNotaFiscal: "11111111000191" NumeroNotaFiscal: "000000123" SerieNotaFiscal: "1" KeyNotaFiscal: "35260111111111000191550010000000011234567890" MeioTransporte: RODOVIARIO TipoTransporteCarga: CARGA FRACIONADA ValorTotalNota: 5890.75 NumeroPedido: PED-FICTICIO-001 DataEmissao: "2026-01-15T00:00:00" NaturezaMercadoria: MERCADORIA FICTICIA NCM: "00000000" EspecieAcondicionamento: CAIXAS QuantidadeVolumes: 15 PesoTotalNota: 8000 PesoDensidadeCubagem: 0.5 NumeroProtocoloNotaFiscal: 0 lote: summary: Dois CT-e no mesmo POST value: - ValorTotalFrete: 800.0 Remetente: CNPJCPF: "11111111000191" RazaoSocial: EMPRESA FICTICIA REMETENTE LTDA Rua: RUA FICTICIA UM Numero: "100" Bairro: BAIRRO FICTICIO Cep: "01001000" CidadeIBGE: "3550308" UnidadeFederacao: SP Destinatario: CNPJCPF: "22222222000192" RazaoSocial: EMPRESA FICTICIA DESTINATARIA LTDA Rua: RUA FICTICIA DOIS Numero: "200" Bairro: BAIRRO FICTICIO Cep: "80010000" CidadeIBGE: "4106902" UnidadeFederacao: PR Tomador: CNPJCPF: "11111111000191" RazaoSocial: EMPRESA FICTICIA REMETENTE LTDA Rua: RUA FICTICIA UM Numero: "100" Bairro: BAIRRO FICTICIO Cep: "01001000" CidadeIBGE: "3550308" UnidadeFederacao: SP DadosNotaFiscal: - KeyNotaFiscal: "35260111111111000191550010000000011234567890" - ValorTotalFrete: 900.0 Remetente: CNPJCPF: "11111111000191" RazaoSocial: EMPRESA FICTICIA REMETENTE LTDA Rua: RUA FICTICIA UM Numero: "100" Bairro: BAIRRO FICTICIO Cep: "01001000" CidadeIBGE: "3550308" UnidadeFederacao: SP Destinatario: CNPJCPF: "22222222000192" RazaoSocial: EMPRESA FICTICIA DESTINATARIA LTDA Rua: RUA FICTICIA DOIS Numero: "200" Bairro: BAIRRO FICTICIO Cep: "80010000" CidadeIBGE: "4106902" UnidadeFederacao: PR Tomador: CNPJCPF: "22222222000192" RazaoSocial: EMPRESA FICTICIA DESTINATARIA LTDA Rua: RUA FICTICIA DOIS Numero: "200" Bairro: BAIRRO FICTICIO Cep: "80010000" CidadeIBGE: "4106902" UnidadeFederacao: PR DadosNotaFiscal: - KeyNotaFiscal: "35260122222222000192550010000000021234567891" responses: '200': description: | Processamento concluído. HTTP 200 mesmo com falha parcial — verifique `sucesso` e cada item em `itens`. content: application/json: schema: $ref: '#/components/schemas/CteEmbarcadorResponse' examples: todosOk: summary: Todos autorizados value: sucesso: true mensagem: Todos os itens foram processados com sucesso. request_id: a1b2c3d4e5f6789012345678abcdef01 itens: - indice: 0 sucesso: true fase: autorizado cte_id: 42 numero: 1001 serie: 1 cfop: "5352" chave: "35260199999999000199570010000010011234567890" protocolo: "199999999999999" mensagem: Autorizado com sucesso. parcial: summary: Um item falhou value: sucesso: false mensagem: Um ou mais itens falharam; veja o array itens. request_id: b2c3d4e5f6789012345678abcdef012345 itens: - indice: 0 sucesso: true fase: autorizado cte_id: 43 numero: 1002 serie: 1 chave: "35260199999999000199570010000010021234567891" - indice: 1 sucesso: false fase: transmissao_rejeitada erro_codigo: SEFAZ_OR_API cte_id: 44 numero: 1003 serie: 1 mensagem: Rejeição na autorização detalhes: cStat: "XXX" xMotivo: Motivo informado pela SEFAZ gravadoSemTx: summary: transmit=0 value: sucesso: true mensagem: Todos os itens foram processados com sucesso. request_id: c3d4e5f6789012345678abcdef01234567 itens: - indice: 0 sucesso: true fase: gravado_sem_transmissao cte_id: 45 numero: 1004 serie: 1 cfop: "5932" mensagem: CT-e registrado sem envio à SEFAZ. '400': description: Requisição inválida (CNPJ emitente, corpo vazio, JSON inválido) content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' examples: cnpj: value: sucesso: false erro_codigo: EMITTER_CNPJ_REQUIRED mensagem: Informe o CNPJ do emitente no header X-Emitente-CNPJ (14 caracteres). request_id: d4e5f6789012345678abcdef0123456789 '401': description: Token inválido ou inativo para o emitente informado content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: sucesso: false erro_codigo: UNAUTHORIZED mensagem: Não autorizado para o emitente informado. request_id: e5f6789012345678abcdef0123456789012 '405': description: Método não permitido (use POST) content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' '422': description: Array JSON vazio na raiz content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' example: sucesso: false erro_codigo: EMPTY_ARRAY mensagem: Esperado um array JSON com ao menos um objeto de CT-e. request_id: f6789012345678abcdef012345678901234 '500': description: Erro interno content: application/json: schema: $ref: '#/components/schemas/ApiErrorResponse' components: securitySchemes: bearerAuth: type: http scheme: bearer description: | Token de integração (opaco). Alternativa: header `X-Embarcador-Token` com o mesmo valor (sem prefixo `Bearer`). embarcadorToken: type: apiKey in: header name: X-Embarcador-Token description: Mesmo token do Bearer; use um dos dois métodos de autenticação. parameters: EmitenteCnpj: name: X-Emitente-CNPJ in: header required: true description: | CNPJ da transportadora **emitente** do CT-e (14 caracteres: numérico ou alfanumérico, NT 2025.001). Aliases aceitos pelo servidor: `X-Emissor-CNPJ`, `X-Company-CNPJ`. schema: type: string pattern: '^[A-Z0-9]{12}[0-9]{2}$' example: "99999999000199" schemas: CteEmbarcadorRequest: type: array minItems: 1 items: $ref: '#/components/schemas/CteEmbarcadorItem' CteEmbarcadorItem: type: object required: - Remetente - Destinatario - Tomador - ValorTotalFrete - DadosNotaFiscal properties: NumeroProtocolo: oneOf: - type: string - type: integer description: Identificador da integração; incluído no xObs do CT-e (aceita texto ou número). example: INT-2026-0001 ValorTotalFrete: type: number format: double minimum: 0.01 description: Valor total do frete (prestação de transporte). PesoTotal: type: number format: double description: Opcional. Se informado e maior que zero, substitui a soma de `PesoTotalNota` das notas. PesoDensidadeCubagemTotal: type: number description: Opcional. Peso cubado total da carga. ValorComposicaoFrete: type: array description: | Opcional. Detalhamento do frete por componente (código, descrição e valor). O total da prestação no CT-e é o campo `ValorTotalFrete`. items: $ref: '#/components/schemas/ValorComposicaoFreteItem' DadosCIOT: allOf: - $ref: '#/components/schemas/DadosCIOT' - description: Opcional. DadosVPO: allOf: - $ref: '#/components/schemas/DadosVPO' - description: Opcional. Observacoes: type: string maxLength: 2000 description: Texto adicional no xObs xObs: type: string maxLength: 2000 Remetente: $ref: '#/components/schemas/ParceiroEmissao' Destinatario: $ref: '#/components/schemas/ParceiroEmissao' Tomador: allOf: - $ref: '#/components/schemas/ParceiroEmissao' - description: | Tomador do serviço (pagador do frete). Informe o CNPJ/CPF de quem paga: igual ao remetente (tipo 0), ao destinatário (tipo 3) ou outro (tipo 4). Pagador: allOf: - $ref: '#/components/schemas/ParceiroEmissao' - description: Alias de `Tomador` (mesmo significado — pagador do frete). DadosNotaFiscal: type: array minItems: 1 items: $ref: '#/components/schemas/NotaFiscalItem' DadosCIOT: type: object description: CIOT. Obrigatórios no objeto — `Numero`, `CNPJIPEF` e `CNPJ` ou `CPF`. required: - Numero - CNPJIPEF properties: Numero: type: string pattern: '^\d{12}$' description: Código CIOT (12 dígitos) example: "123456789012" CIOT: type: string pattern: '^\d{12}$' CNPJ: type: string description: CNPJ do responsável (14 caracteres). Informe `CNPJ` ou `CPF`. example: "11111111000191" CPF: type: string description: CPF do responsável (11 dígitos). Alternativa ao `CNPJ`. ciot_cnpj: type: string ciot_cpf: type: string CNPJIPEF: type: string description: CNPJ da Instituição de Pagamento Eletrônico do Frete (14 caracteres) example: "44444444000194" cnpj_ipef: type: string DadosVPO: type: object description: Vale pedágio. Obrigatórios no objeto — `CNPJFornecedor` e `Valor`. required: - CNPJFornecedor - Valor properties: NumeroCompra: type: string maxLength: 20 description: IDVPO / nCompra example: "000000000001" nCompra: type: string VPO: type: string Valor: type: number format: double minimum: 0.01 description: Valor do vale pedágio ValorValePedagio: type: number format: double CNPJFornecedor: type: string description: CNPJ da empresa fornecedora do vale (14 caracteres) example: "55555555000195" CNPJForn: type: string CNPJPg: type: string description: CNPJ do pagador do vale, se diferente do emitente CPFPg: type: string tpValePed: type: string enum: ['01', '02', '03', '99'] description: "01=TAG, 02=Cupom, 03=Cartão, 99=Outros" ValorComposicaoFreteItem: type: object description: Componente do detalhamento de frete em `ValorComposicaoFrete`. properties: CodigoServico: type: integer description: Código do tipo de serviço/componente. DescricaoServico: type: string description: Descrição do componente (ex. FRETE PESO, GRIS, PEDAGIO). ValorServico: type: number format: double description: Valor do componente. ParceiroEmissao: type: object description: | Dados completos do participante para emissão do CT-e (usado em `Remetente`, `Destinatario` e `Tomador`/`Pagador`). Corresponde ao que o AppCTE envia no XML (`rem`, `dest` e `toma4` quando o tomador é "outros"). required: - CNPJCPF - RazaoSocial - Rua - Numero - Bairro - Cep properties: CNPJCPF: type: string description: CPF (11 dígitos) ou CNPJ (14 caracteres, numérico ou alfanumérico). Pontuação opcional. example: "11111111000191" RazaoSocial: type: string description: Razão social ou nome. example: EMPRESA FICTICIA LTDA InscricaoEstadual: type: string description: Opcional. Vazio ou `ISENTO` quando não houver inscrição estadual. example: ISENTO TelefoneContato: type: string description: Opcional. Telefone de contato (somente dígitos na gravação). TipoIdentificacao: type: string description: Opcional. Informativo (ex. CNPJ). O documento fiscal é `CNPJCPF`. Cep: type: string description: CEP com 8 dígitos (com ou sem máscara). example: "01001000" Rua: type: string description: Logradouro (xLgr no XML). example: RUA FICTICIA UM Numero: type: string description: Número do imóvel. Use `S/N` se não houver número. example: "1000" Complemento: type: string description: Opcional. Bairro: type: string example: BAIRRO FICTICIO Cidade: type: string description: | Nome do município. Obrigatório informar este campo **e** `UnidadeFederacao` quando `CidadeIBGE` não for enviado. example: CIDADE FICTICIA A UnidadeFederacao: type: string minLength: 2 maxLength: 2 description: UF (2 letras). example: SP CidadeIBGE: type: string description: | Código IBGE do município (7 dígitos). Forma preferida de localização. Alternativa: `Cidade` + `UnidadeFederacao` cadastrados no AppCTE. example: "3550308" NotaFiscalItem: type: object required: - KeyNotaFiscal properties: KeyNotaFiscal: type: string pattern: '^\d{44}$' description: | Chave de acesso da NF-e (**44 dígitos** após remover formatação). Notas sem chave válida geram erro no item (`DATABASE_OR_RULE`). ValorTotalNota: type: number format: double PesoTotalNota: type: number format: double QuantidadeVolumes: type: number format: double NaturezaMercadoria: type: string NCM: type: string SerieNotaFiscal: type: string NumeroNotaFiscal: type: string CNPJCPFEmissorNotaFiscal: type: string description: Opcional. CNPJ/CPF do emissor da NF-e. MeioTransporte: type: string description: Opcional. Meio de transporte da carga na nota. TipoTransporteCarga: type: string description: Opcional. Tipo de transporte da carga. NumeroPedido: type: string description: Opcional. Número do pedido vinculado à nota. DataEmissao: type: string description: Opcional. Data de emissão da nota (formato livre ou ISO 8601). EspecieAcondicionamento: type: string description: Opcional. Espécie de acondicionamento da mercadoria. PesoDensidadeCubagem: type: number description: Opcional. Peso cubado da nota. NumeroProtocoloNotaFiscal: oneOf: - type: string - type: integer description: Opcional. Protocolo interno da nota no embarcador. CteEmbarcadorResponse: type: object required: - sucesso - mensagem - itens - request_id description: | Resposta do lote. Em sucesso parcial, HTTP continua **200** com `sucesso: false`. `company_id` é preenchido quando a autenticação foi aceita. properties: sucesso: type: boolean description: true apenas se **todos** os itens tiveram sucesso company_id: type: integer description: Identificador do emitente no AppCTE (informativo; o CNPJ de emissão é o header `X-Emitente-CNPJ`). mensagem: type: string request_id: type: string description: Identificador único da requisição — informe ao suporte em caso de problemas. itens: type: array items: $ref: '#/components/schemas/CteEmbarcadorItemResult' CteEmbarcadorItemResult: type: object properties: indice: type: integer description: Índice no array enviado (0-based) sucesso: type: boolean fase: type: string enum: - gravado - gravado_sem_transmissao - autorizado - transmissao_rejeitada erro_codigo: type: string description: | Código do erro, quando `sucesso` = false: `VALIDATION_ERROR` (dados inválidos), `INVALID_ITEM` (item do array malformado), `DATABASE_OR_RULE` (falha ao registrar ou regra de negócio), `SEFAZ_OR_API` (rejeição ou falha na autorização). enum: - VALIDATION_ERROR - INVALID_ITEM - DATABASE_OR_RULE - SEFAZ_OR_API mensagem: type: string cte_id: type: integer description: Identificador do CT-e no AppCTE (quando o documento foi registrado com sucesso). numero: type: integer serie: type: integer cfop: type: string chave: type: string nullable: true description: | Chave de acesso do CT-e (44 dígitos). Preenchida somente quando `fase` = `autorizado` (autorização na SEFAZ concluída com sucesso). protocolo: type: string nullable: true description: Número do protocolo de autorização (`nProt`). Mesmas regras de `chave`. detalhes: type: object properties: http_code: type: integer cStat: type: string xMotivo: type: string ApiErrorResponse: type: object properties: sucesso: type: boolean example: false erro_codigo: type: string mensagem: type: string request_id: type: string detalhe: type: string description: Detalhe adicional em falhas do servidor (erro HTTP 500).