Por décadas, desenvolver um TMS (Transportation Management System) ou um módulo de expedição logística para transportadoras, embarcadores e e-commerces com frota própria era considerado um projeto exclusivo para grandes software houses legadas.
O motivo? A complexidade brutal dos schemas XML da SEFAZ para o CT-e (Conhecimento de Transporte Eletrônico — Modelo 57, v4.00) e para o MDF-e (Manifesto Eletrônico de Documentos Fiscais — Modelo 58, v3.00b). Configurar assinaturas XML-DSig com certificado A1, calcular ICMS de frete interestadual, vincular múltiplas chaves de NF-e de 44 dígitos, validar o seguro RCTR-C e controlar o encerramento de manifestos exigia meses de leitura de manuais do ENCAT.
Hoje, na era do Vibe Coding Fiscal, um único desenvolvedor fullstack ou founder técnico equipado com Cursor, Lovable, v0 ou Windsurf, Next.js 16 (App Router) e a API de CT-e e MDF-e da Notaas consegue colocar um painel completo de despacho rodoviário no ar em menos de uma tarde.
Neste guia prático passo a passo, entregamos a arquitetura, o schema de validação Zod, a Server Action em TypeScript e o Prompt de Sistema pronto para copiar e colar na sua IDE de IA para criar um emissor de CT-e e MDF-e em produção.
🏗️ Arquitetura de um Micro-SaaS de Logística / TMS Moderno
Ao invés de acoplar bibliotecas pesadas de C# ou PHP legado no seu servidor para conversar via SOAP com a SEFAZ, o fluxo moderno trata documentos fiscais de transporte exatamente como transações de pagamento no Stripe: JSON na entrada, Webhook assinado na saída.
⚡ Fluxo de Emissão Logística (Next.js + Notaas API):
- 1. Operador no Painel TMS: Seleciona as NF-es da viagem (ou bipa o código de barras do DANFE), escolhe o veículo (placa/RNTRC) e o motorista (CPF).
- 2. Validação Client/Server (Zod): O formulário Next.js valida se as chaves das NF-es possuem 44 dígitos e se a UF de carregamento e descarregamento estão preenchidas.
- 3. Disparo REST JSON (
POST /api/v1/cteou/api/v1/mdfe): A Server Action envia um JSON limpo para a Notaas.- 4. Autorização SEFAZ & PDF Instantâneo: A engine da Notaas assina o XML com o Certificado A1 em nuvem, autoriza na SEFAZ e gera o DACTE ou DAMDFE com QR Code em PDF.
- 5. Desbloqueio Automático de Viagem: Quando o caminhão entrega a carga, um botão de 1 clique chama
POST /api/v1/mdfe/{id}/encerrar, evitando a temida Rejeição 611 (MDF-e não encerrado).
📋 Passo 1: O Prompt Mestre para Cursor, Lovable ou v0
Se você está iniciando seu painel logístico no Cursor, Lovable ou v0 (Vercel), copie o prompt abaixo para gerar a interface de despacho e a camada de integração sem alucinações fiscais:
Crie um módulo de expedição logística (TMS) em Next.js (App Router, TypeScript, Tailwind CSS e shadcn/ui) integrado à API REST da Notaas (https://api.notaas.com.br/api/v1).
Requisitos do módulo:
1. Aba "Emitir CT-e (Mod 57)" para transportadoras (veja regras de CFOP 5353/6353 e seguro RCTR-C) e Aba "Emitir MDF-e (Mod 58)" para agrupamento de NF-es no veículo.
2. Formulário validado com React Hook Form + Zod:
- Dados do Veículo de Tração: Placa Mercosul (7 caracteres), RENAVAM, Tara (kg), Capacidade (kg), RNTRC da ANTT e UF.
- Dados do Condutor: Nome completo e CPF (11 dígitos).
- Lista dinâmica de Chaves de Acesso de NF-e (44 dígitos numéricos cada) com leitor de código de barras.
- UF de Carregamento, Município de Carregamento (IBGE 7 dígitos), UF de Descarregamento e UFs de Percurso.
3. Server Action segura (`src/actions/fiscal-logistica.ts`) que envia POST para `https://api.notaas.com.br/api/v1/mdfe/emitir` e `https://api.notaas.com.br/api/v1/cte/emitir` usando header `Authorization: Bearer process.env.NOTAAS_API_KEY` e `Idempotency-Key`.
4. Tela de listagem de manifestos ativos com botão "Encerrar MDF-e na SEFAZ" (`POST /api/v1/mdfe/{id}/encerrar`) para evitar a Rejeição 611, além de botões para download direto do PDF (DACTE / DAMDFE) e XML.
🛡️ Passo 2: Schema Zod para Validar CT-e e MDF-e antes da SEFAZ
Mais de 80% das rejeições da SEFAZ em transporte rodoviário acontecem por erros básicos de digitação do operador de logística: chave de NF-e com 43 dígitos, CPF de motorista inválido ou placa fora do padrão.
Com este schema Zod em TypeScript, você bloqueia dados inválidos no próprio navegador:
// src/lib/schemas/logistica-fiscal.ts
import { z } from "zod";
export const MdfeEmissaoSchema = z.object({
ambiente: z.enum(["homologacao", "producao"]).default("homologacao"),
tipoEmitente: z.enum([
"1", // 1 = Prestador de Serviço de Transporte (Transportadora - vincula CT-e)
"2" // 2 = Transporte de Carga Própria (Indústria/E-commerce - vincula NF-e)
]),
ufInicio: z.string().length(2, "Informe a sigla da UF de origem (ex: SP)"),
ufFim: z.string().length(2, "Informe a sigla da UF de destino (ex: PR)"),
municipioCarregamentoIbge: z.string().regex(/^\d{7}$/, "Código IBGE deve ter 7 dígitos"),
ufsPercurso: z.array(z.string().length(2)).optional(),
veiculoTracao: z.object({
placa: z.string().regex(/^[A-Z]{3}[0-9][0-9A-Z][0-9]{2}$/, "Placa inválida (Padrão Mercosul ou Antigo)"),
taraKg: z.number().int().positive("Tara do veículo deve ser maior que zero"),
capacidadeKg: z.number().int().positive("Capacidade em Kg obrigatória"),
rntrc: z.string().regex(/^\d{8}$/, "RNTRC da ANTT deve conter 8 dígitos").optional()
}),
condutor: z.object({
nome: z.string().min(5, "Nome completo do motorista é obrigatório"),
cpf: z.string().regex(/^\d{11}$/, "CPF do motorista deve ter 11 números")
}),
documentosVinculados: z.array(
z.object({
municipioDescarregamentoIbge: z.string().regex(/^\d{7}$/),
chaveAcesso: z.string().regex(/^\d{44}$/, "A Chave de Acesso da NF-e/CT-e deve ter exatos 44 dígitos")
})
).min(1, "Vincule pelo menos 1 documento fiscal (NF-e ou CT-e) ao manifesto"),
valorTotalCarga: z.number().positive("Valor total da carga transportada é obrigatório"),
pesoBrutoTotalKg: z.number().positive("Peso bruto total em Kg é obrigatório")
});
export type MdfeEmissaoInput = z.infer<typeof MdfeEmissaoSchema>;
💻 Passo 3: Server Action em Next.js para Emitir e Encerrar MDF-e / CT-e
Quer você esteja emitindo um CT-e Modelo 57 com cálculo de ICMS frete e DACTE ou um MDF-e para Carga Própria vinculando NF-es do seu e-commerce, a chamada para a API da Notaas segue o mesmo padrão limpo em JSON:
// src/actions/fiscal-logistica.ts
"use server";
import { MdfeEmissaoSchema, MdfeEmissaoInput } from "@/lib/schemas/logistica-fiscal";
export async function emitirMdfeViagemAction(input: MdfeEmissaoInput, viagemId: string) {
const parsed = MdfeEmissaoSchema.safeParse(input);
if (!parsed.success) {
return { ok: false, errors: parsed.error.flatten().fieldErrors };
}
const response = await fetch("https://api.notaas.com.br/api/v1/mdfe/emitir", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.NOTAAS_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `mdfe-viagem-${viagemId}`
},
body: JSON.stringify(parsed.data)
});
if (!response.ok) {
const errorBody = await response.json();
return { ok: false, message: errorBody.message || "Falha ao autorizar MDF-e na SEFAZ" };
}
const result = await response.json();
return {
ok: true,
chaveMdfe: result.chaveAcesso,
protocolo: result.protocoloAutorizacao,
damdfePdfUrl: result.pdfUrl,
xmlUrl: result.xmlUrl
};
}
// Encerramento de 1 clique quando o caminhão finaliza a entrega
export async function encerrarMdfeAction(mdfeId: string, codigoMunicipioIbge: string) {
const response = await fetch(`https://api.notaas.com.br/api/v1/mdfe/${mdfeId}/encerrar`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.NOTAAS_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
codigoMunicipioEncerramentoIbge: codigoMunicipioIbge,
dataEncerramento: new Date().toISOString()
})
});
return response.json();
}
🔗 Como Conectar todo o Ciclo Logístico no seu SaaS (NF-e ➔ CT-e ➔ MDF-e)
A grande vantagem de construir seu ERP ou TMS sobre a API Unificada da Notaas é que todos os modelos de documentos fiscais compartilham a mesma conta, o mesmo padrão de autenticação e a mesma Org API Multi-CNPJ (POST /api/v1/org/projects):
- Faturamento do Produto (API NF-e Mod 55): O embarcador emite a NF-e da mercadoria (incluindo tags B2B de Pedido de Compra
xPedenItemPedpara grandes redes). - Conhecimento de Transporte (API CT-e Mod 57): A transportadora referencia a chave de 44 dígitos da NF-e e emite o CT-e com apólice de seguro e DACTE PDF.
- Manifesto de Carga (API MDF-e Mod 58): Antes do caminhão pegar a rodovia, o sistema agrupa todos os CT-es (ou NF-es, em caso de frota própria) em um MDF-e e imprime o DAMDFE.
- Encerramento Automatizado (Solução da Rejeição 611): Ao confirmar a entrega no app do motorista, sua aplicação encerra o MDF-e via API, liberando a placa imediatamente para a próxima viagem.
🚀 Construa seu TMS Hoje com 50 Emissões Grátis/Mês em Produção
Pare de perder meses decifrando schemas XSD da SEFAZ. Com a Notaas, você integra NF-e, NFC-e, NFS-e, CT-e e MDF-e em minutos e conta com 50 notas fiscais gratuitas por mês por CNPJ em produção real (além de ambiente Sandbox 100% gratuito e ilimitado para testar seus prompts no Cursor e Lovable).
👉 Crie sua conta grátis agora em platform.notaas.com.br/sign-up ou consulte os endpoints de logística na Documentação Oficial (docs.notaas.com.br).

