Primeiros passos
Em simulação você percorre o fluxo inteiro — emitir, consultar, receber o webhook — sem certificado digital e sem falar com a SEFAZ. O código que funciona aqui funciona em produção trocando só a chave.
1. Crie a chave de simulação
No painel, abra Integração › Chaves de API, clique em Nova chave e escolha o ambiente Simulação. A chave começa com mn_sim_ e aparece uma única vez. Guarde-a numa variável de ambiente:
export MADNOTAS_CHAVE="mn_sim_SuaChaveAqui" export MADNOTAS_URL="https://notas.madbuilder.dev/api/v1"
2. Confira a conexão
curl "$MADNOTAS_URL/ping" -H "Authorization: Bearer $MADNOTAS_CHAVE"
A resposta confirma o ambiente e a empresa da chave:
{
"ok": true,
"ambiente": "simulacao",
"empresa": { "id": 42, "nome": "Loja Exemplo Ltda" },
"chave": { "id": 7, "prefixo": "mn_sim_aB3d" },
"request_id": "req_01jbx4k2m9q7t3v8w5z6y1r0ac"
}3. Cadastre o emitente
O emitente é o CNPJ que assina a nota. Cadastre pelo painel (Notas fiscais › Emitentes) ou pela API, em POST /emitentes. Em simulação o certificado não é exigido, e a conta nova já vem com um emitente de demonstração para os primeiros testes.
4. Emita a NF-e
Mande os dados da venda. A conta nova já tem um emitente de demonstração em São Paulo, então o exemplo abaixo funciona como está, com a sua chave mn_sim_. O parâmetro aguardar=20 segura a resposta por até 20 segundos esperando a SEFAZ.
{
"ref": "pedido-1001",
"natureza_operacao": "VENDA DE MERCADORIA",
"destinatario": {
"cnpj": "12ABC34501DE35",
"nome": "COMERCIO FICTICIO LTDA",
"inscricao_estadual": "110042490114",
"email": "compras@cliente.test",
"endereco": {
"logradouro": "RUA DO CLIENTE",
"numero": "55",
"bairro": "CENTRO",
"codigo_municipio": "3550308",
"municipio": "SAO PAULO",
"uf": "SP",
"cep": "01001000"
}
},
"itens": [
{
"codigo": "P001",
"descricao": "PRODUTO FICTICIO",
"ncm": "21069090",
"cfop": "5102",
"unidade": "UN",
"quantidade": "3",
"valor_unitario": "33.3333",
"valor_bruto": "100.00",
"icms": {
"origem": "0",
"csosn": "102"
},
"pis": {
"cst": "07"
},
"cofins": {
"cst": "07"
}
}
],
"pagamentos": [
{
"forma": "pix",
"valor": "100.00"
}
]
}curl -X POST "$MADNOTAS_URL/nfe?aguardar=20" \ -H "Authorization: Bearer $MADNOTAS_CHAVE" \ -H "Content-Type: application/json" \ -d @pedido.json
$ch = curl_init(getenv('MADNOTAS_URL') . '/nfe?aguardar=20');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => file_get_contents('pedido.json'),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('MADNOTAS_CHAVE'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$nota = json_decode(curl_exec($ch), true);
echo $nota['status']; // autorizadaimport { readFile } from 'node:fs/promises';
const r = await fetch(`${process.env.MADNOTAS_URL}/nfe?aguardar=20`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MADNOTAS_CHAVE}`,
'Content-Type': 'application/json',
},
body: await readFile('pedido.json', 'utf8'),
});
const nota = await r.json();
console.log(nota.status); // autorizadaimport json, os, requests
with open("pedido.json") as f:
corpo = json.load(f)
r = requests.post(
os.environ["MADNOTAS_URL"] + "/nfe",
params={"aguardar": 20},
headers={"Authorization": "Bearer " + os.environ["MADNOTAS_CHAVE"]},
json=corpo,
timeout=30,
)
print(r.json()["status"]) # autorizada5. Leia o resultado
A resposta é 201 com a nota. Se a SEFAZ já respondeu, o status vem final (autorizada ou rejeitada); se não, vem processando e você consulta depois:
curl "$MADNOTAS_URL/nfe/nfe_01jbx4k2m9q7t3v8w5z6y1r0ac" -H "Authorization: Bearer $MADNOTAS_CHAVE"
Com a nota autorizada, baixe o XML em GET /nfe/{id}/xml e o DANFE em PDF em GET /nfe/{id}/danfe.
Não faça polling apertado. Prefira o webhook (próximo passo). Se precisar consultar, espere ao menos 2 segundos entre as tentativas.
6. Receba o webhook
Em Integração › Webhooks, cadastre a URL do seu sistema e marque nfe.*. Cada mudança de estado chega num POST assinado. Veja como conferir a assinatura no guia de webhooks.
7. Provoque os erros antes do cliente
A simulação tem valores mágicos que forçam rejeição, timeout, contingência e conflito de numeração. Use-os para testar o tratamento do seu sistema: Simulação.
Depois: homologação e produção
- Envie o certificado A1 do emitente (guia do certificado).
- Crie uma chave
mn_hom_e emita na SEFAZ de homologação (guia de homologação). - Crie a chave
mn_prod_e troque no seu sistema. Nada mais muda.