De zero ao primeiro 200 OK em 60 segundos.
Uma API. Um schema JSON. Um único formato de erro pra todos os identificadores da América do Sul. Este é o guia mínimo pra sair do zero até a primeira resposta.
Seu primeiro request
Mande country e value para /v1/validate/tax-ids dentro de um array items. Receba um array results com um objeto por item: source, normalized, formatted, country, type e valid. Quando valid for false, leia a resposta — é sempre acionável.
$ curl -X POST https://api.normadata.io/v1/validate/tax-ids \
-H "X-API-Key: nd_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": "a", "value": "20-12345678-6", "country": "AR", "type": "cuit" },
{ "id": "b", "value": "123.456.789-09", "country": "BR" }
]
}'{
"results": [
{
"id": "a",
"country": "AR",
"type": "cuit",
"valid": true,
"normalized": "20123456786",
"formatted": "20-12345678-6"
},
{
"id": "b",
"country": "BR",
"type": "cpf",
"valid": true,
"normalized": "12345678909",
"formatted": "123.456.789-09"
}
]
}const res = await fetch("https://api.normadata.io/v1/validate/tax-ids", {
method: "POST",
headers: {
"X-API-Key": process.env.ND_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
items: [
{ id: "a", value: "20-12345678-6", country: "AR", type: "cuit" },
{ id: "b", value: "123.456.789-09", country: "BR" },
],
}),
});
const { results } = await res.json();
// Same endpoint for 1 or N items — one result per item, by id.
for (const r of results) console.log(r.id, r.valid, r.normalized);import os
import requests
res = requests.post(
"https://api.normadata.io/v1/validate/tax-ids",
headers={
"X-API-Key": os.environ["ND_KEY"],
"Content-Type": "application/json",
},
json={
"items": [
{"id": "a", "value": "20-12345678-6", "country": "AR", "type": "cuit"},
{"id": "b", "value": "123.456.789-09", "country": "BR"},
],
},
)
# Same endpoint for 1 or N items — one result per item, by id.
for r in res.json()["results"]:
print(r["id"], r["valid"], r.get("normalized"))Qualquer cliente HTTP serve
A gente ainda não shippa SDKs. A API é REST + JSON estrito, então cURL, fetch, requests ou net/http funcionam out of the box. Os exemplos abaixo cobrem os casos mais comuns.
API keys
Mande o header X-API-Key em cada request. As keys começam com nd_ seguido de 30 chars base62 (33 chars no total). Nunca exponha sua key em código do cliente — use só a partir de um servidor, função ou infra de confiança.
X-API-Key: nd_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5nd_ prefix (3 chars)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx base62 random (30 chars)
──────────────────────────────
nd_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5 (33 chars total)Anatomia do payload
Cada endpoint de Validate aceita um shape plano. Campos extras são ignorados. Algo inválido vira 422 com os campos que falharam listados.
{
"items": [ // 1..1000 items (500 for /records)
{
"id": "a", // your correlation id, returned verbatim
"value": "20-12345678-6", // raw input
"country": "AR", // ISO 3166-1 alpha-2 (required)
"type": "cuit" // optional — deduced within the country
}
]
}- countrystring · ISO 3166-1 alpha-2Exceto IBAN / Domain — esses são padrões globais.
- typestring · enumVer cobertura · tipos suportados.
- valuestring · raw inputEspaços, pontos e hífens permitidos — limpamos e canonicalizamos.
Tax IDs
Contas
Emails
Telefones
Records
Códigos possíveis
HTTP padrão mais códigos de warning do produto dentro da resposta. valid: false não é um erro HTTP — devolvemos 200 com valid: false e uma razão legível.
Toda resposta inclui um header X-Request-Id, também devolvido nos bodies de erro. Quando reportar um problema em hello@normadata.io, inclua-o — isso permite que a gente rastreie a request exata nos nossos logs.
| Status | Code | Significado |
|---|---|---|
| 200 | results[] | Lote processado. Leia results[]: cada resultado traz seu próprio valid e um error quando valid é false. |
| 400 | empty_batch | JSON mal formado ou array items vazio. O code indica a causa (empty_batch, batch_too_large). |
| 401 | invalid_api_key | Header X-API-Key ausente ou inválido. |
| 429 | quota_exceeded | Cota mensal ou rate por key excedido. Leia Retry-After em segundos. |
| 5xx | internal_error | Erro inesperado do servidor. Tente de novo em 5s com jitter. |
| 200 | valid: false | Estrutura ou dígito verificador inválido. O motivo vai no campo error desse item; o resto do lote não para. |
| 400 | empty_batch | O array items veio vazio. |
| 400 | batch_too_large | Mais de 1.000 itens (500 em /records). Pagine o lote. |
| 429 | quota_exceeded | O lote ultrapassa a cota mensal restante. Leia Retry-After. |
Por key durante o acesso antecipado
Os rate limits são configurados por API key durante o acesso antecipado. Os números concretos vão na conta quando você for onboardado. A resposta inclui os headers padrão X-RateLimit-* pro seu cliente fazer back-off limpo.
X-RateLimit-Limit: 60000
X-RateLimit-Remaining: 55872
X-RateLimit-Reset: 2026-07-01T00:00:00Z
Retry-After: 1Os limites são negociados por workload. Se precisar de mais burst ou quota, menciona no formulário do waitlist e a gente seta antes de emitir sua key.
Tem uma dúvida específica?
Email pra hello@normadata.io — respondemos em 24h ou antes.