Documentação › Primeiros passos
Comece aqui
Da chave de teste à primeira NFS-e autorizada, passo a passo, com curl, C# e Delphi.
Sua primeira nota
Tudo começa no ambiente de teste: a nota vai de verdade ao ambiente de testes do Sistema Nacional, sem valor fiscal, sem cobrar e sem aparecer no painel. Para produção, depois, só a chave muda.
Qual caminho é o seu?
- A. A empresa já está configurada no painel (certificado A1 e dados fiscais): faça os passos 1, 3, 4, 5, 6 e 7. Leva minutos.
- B. Primeira configuração: comece pelo passo 2. O tempo depende de ter o certificado A1 em mãos e de conhecer o regime tributário e o código de serviço da empresa.
1. Chave de teste. No painel, em Integrações › Chaves de API, crie
uma chave com ambiente Teste. Ela começa com sdr_test_. Nos exemplos
abaixo ela está na variável SUDREL_API_KEY.
2. Empresa (só no caminho B). Cadastre a empresa e envie o certificado A1
pelo painel, ou pela API com uma chave sdr_live_ (POST /v1/companies e
POST /v1/companies/{id}/certificate). A chave de teste lê as empresas e
emite em nome delas, mas não cria nem altera empresa. Os dados fiscais
(regime tributário, código de serviço padrão) ficam no painel, em
Emissão › Empresa. O empresa_id de cada empresa sai de
GET /v1/companies.
3. Prontidão. Objetivo: saber se a empresa pode emitir agora, antes de tentar.
curl https://api.sudrel.com.br/api/v1/companies/$EMPRESA/prontidao \
-H "Authorization: Bearer $SUDREL_API_KEY"
A resposta tem situacao (ok, aviso ou bloqueio) e um item por
requisito, cada um com mensagem e correcao. Próximo passo: com ok ou
aviso, siga. Com bloqueio, resolva o item indicado: a emissão seria
recusada com 412. Detalhes em Prontidão.
4. Valide antes de emitir. POST /v1/nfse/validacoes recebe o mesmo
JSON da emissão e devolve os erros e os ajustes, sem criar nada.
curl https://api.sudrel.com.br/api/v1/nfse/validacoes \
-H "Authorization: Bearer $SUDREL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"empresa_id":"'$EMPRESA'","referencia":"PED-1001","tomador":{"documento":"11222333000181"},"valor":"1500.00","servico":{"descricao":"Consultoria em sistemas"}}'
A resposta é sempre 200, com valida (true ou false), erros (cada um
com campo, mensagem e correcao) e ajustes (o que a Sudrel preencheu ou
omitiu pelo município). Próximo passo: com valida: true, emita.
5. Emita. Mande sempre referencia e Idempotency-Key: é o que torna
seguro repetir a chamada. Veja Idempotência.
curl https://api.sudrel.com.br/api/v1/nfse \
-H "Authorization: Bearer $SUDREL_API_KEY" \
-H "Idempotency-Key: 7f1c0d9a-4a51-4e0e-9b1f-2b6f0d3c5a10" \
-H "Prefer: wait=10" \
-H "Content-Type: application/json" \
-d '{"empresa_id":"'$EMPRESA'","referencia":"PED-1001","tomador":{"documento":"11222333000181"},"valor":"1500.00","servico":{"descricao":"Consultoria em sistemas"}}'
O que pode voltar:
| Status | O que aconteceu | Próximo passo |
|---|---|---|
| 201 | Autorizada. numero e chave_acesso preenchidos. |
Pronto. Baixe o PDF em GET /v1/nfse/{id}/pdf. |
| 202 | Ainda transmitindo. A Sudrel continua cuidando. |
Espere o webhook ou consulte (passo 6). Não emita de novo. |
422 validacao |
O JSON tem erro. Nada foi criado. | Corrija os itens de erros e envie de novo. |
422 nfse_rejeitada |
O Sistema Nacional recusou. A nota existe como rejeitada. |
Leia rejeicao, corrija e emita uma nota nova, com outra referencia. |
412 empresa_nao_pronta |
A empresa não pode emitir. Nada foi criado. | Resolva os itens em bloqueio (passo 3). |
Sem SDK, a mesma chamada em HTTP puro:
C# (.NET 6 ou mais novo):
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Threading.Tasks;
public static class PrimeiraNota
{
// A Idempotency-Key é sua: gere uma por nota, guarde junto do pedido e
// reaproveite a MESMA se precisar repetir a chamada. Assim nunca sai nota dobrada.
public static async Task<string> EmitirAsync(string empresaId, string idempotencyKey)
{
using var http = new HttpClient { BaseAddress = new Uri("https://api.sudrel.com.br/api/") };
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("SUDREL_API_KEY"));
var pedido = new HttpRequestMessage(HttpMethod.Post, "v1/nfse")
{
Content = JsonContent.Create(new
{
empresa_id = empresaId,
referencia = "PED-1001",
tomador = new { documento = "11222333000181" },
valor = "1500.00",
servico = new { descricao = "Consultoria em sistemas" },
}),
};
pedido.Headers.Add("Idempotency-Key", idempotencyKey);
pedido.Headers.Add("Prefer", "wait=10");
var resposta = await http.SendAsync(pedido);
var corpo = await resposta.Content.ReadAsStringAsync();
// 201: autorizada. 202: ainda transmitindo (acompanhe por webhook ou GET /v1/nfse/PED-1001).
// 422: veja "codigo" e "erros" (ou a nota rejeitada em "nfse"). Todo erro traz "requisicao_id".
return $"{(int)resposta.StatusCode} {corpo}";
}
}
Delphi (10.3 ou mais novo, System.Net.HttpClient):
uses
System.SysUtils, System.Classes, System.Net.HttpClient, System.Net.URLClient;
// A Idempotency-Key é sua: gere uma por nota, guarde junto do pedido e
// reaproveite a MESMA se precisar repetir a chamada. Assim nunca sai nota dobrada.
function EmitirNota(const EmpresaId, IdempotencyKey: string): string;
var
Cliente: THTTPClient;
Corpo: TStringStream;
Resposta: IHTTPResponse;
begin
Cliente := THTTPClient.Create;
Corpo := TStringStream.Create(
'{"empresa_id":"' + EmpresaId + '","referencia":"PED-1001",' +
'"tomador":{"documento":"11222333000181"},"valor":"1500.00",' +
'"servico":{"descricao":"Consultoria em sistemas"}}', TEncoding.UTF8);
try
Cliente.ContentType := 'application/json';
Cliente.CustomHeaders['Authorization'] := 'Bearer ' + GetEnvironmentVariable('SUDREL_API_KEY');
Cliente.CustomHeaders['Idempotency-Key'] := IdempotencyKey;
Cliente.CustomHeaders['Prefer'] := 'wait=10';
Resposta := Cliente.Post('https://api.sudrel.com.br/api/v1/nfse', Corpo);
// 201: autorizada. 202: ainda transmitindo (acompanhe por webhook ou GET /v1/nfse/PED-1001).
// 422: veja "codigo" e "erros" (ou a nota rejeitada em "nfse"). Todo erro traz "requisicao_id".
Result := IntToStr(Resposta.StatusCode) + ' ' + Resposta.ContentAsString(TEncoding.UTF8);
finally
Corpo.Free;
Cliente.Free;
end;
end;
Há também SDKs de TypeScript e PHP: veja SDKs.
6. Acompanhe. Objetivo: saber o resultado de uma nota que voltou 202. Consulte pela sua referência:
curl https://api.sudrel.com.br/api/v1/nfse/PED-1001 \
-H "Authorization: Bearer $SUDREL_API_KEY"
Próximo passo: status diz onde a nota está (veja
Estados da NFS-e). Consulte com calma (a cada 30
segundos, por exemplo); em produção, prefira o webhook.
7. Webhook. Objetivo: ser avisado sem consultar. Cadastre um endereço seu, com a chave de teste (ele recebe só eventos de teste):
curl https://api.sudrel.com.br/api/v1/webhooks \
-H "Authorization: Bearer $SUDREL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://erp.exemplo.com.br/webhooks/sudrel","eventos":["NFSE_AUTORIZADA","NFSE_REJEITADA","NFSE_FALHA_TRANSMISSAO"]}'
Guarde o segredo da resposta: ele só aparece aqui. Teste com
POST /v1/webhooks/{id}/teste. Como conferir a assinatura de cada entrega
está em Webhooks.
8. Provoque as falhas. Com o cabeçalho X-Sudrel-Simular (seção
Simulador de falhas) você vê timeout, Sefin fora,
trava de competência e falha_transmissao sem tocar na Sefin.
Deu erro? Toda resposta traz o cabeçalho X-Request-Id, e os erros de
emissão, lote, webhooks e eventos repetem o valor em requisicao_id. Procure
por ele no painel, em Integrações › Log da API: está lá o que o seu
sistema mandou e o que a Sudrel respondeu, por 30 dias. Veja também
Problemas comuns.