DOCUMENTAÇÃO · v1 · 2026.05

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.

01 · QUICKSTART

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.

cURLPOST /v1/validate/tax-ids
$ 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" }
      ]
    }'
Response · 200 OK
{
  "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"
    }
  ]
}
TypeScript
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);
Python
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"))
02 · CLIENTES

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.

03 · AUTH

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.

Header
X-API-Key: nd_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5
Formato da key
nd_   prefix          (3 chars)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx   base62 random  (30 chars)
──────────────────────────────
nd_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5  (33 chars total)
04 · REQUEST

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.

POST /v1/validate/tax-ids
{
  "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
    }
  ]
}
CAMPOS OBRIGATÓRIOS
  • country
    string · ISO 3166-1 alpha-2
    Exceto IBAN / Domain — esses são padrões globais.
  • type
    string · enum
    Ver cobertura · tipos suportados.
  • value
    string · raw input
    Espaços, pontos e hífens permitidos — limpamos e canonicalizamos.
POST /v1/validate/tax-idsFull reference →

Tax IDs

POST /v1/validate/accountsFull reference →

Contas

POST /v1/validate/emailsFull reference →

Emails

POST /v1/validate/phonesFull reference →

Telefones

POST /v1/validate/recordsFull reference →

Records

05 · ERROS

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.

StatusCodeSignificado
200results[]Lote processado. Leia results[]: cada resultado traz seu próprio valid e um error quando valid é false.
400empty_batchJSON mal formado ou array items vazio. O code indica a causa (empty_batch, batch_too_large).
401invalid_api_keyHeader X-API-Key ausente ou inválido.
429quota_exceededCota mensal ou rate por key excedido. Leia Retry-After em segundos.
5xxinternal_errorErro inesperado do servidor. Tente de novo em 5s com jitter.
200valid: falseEstrutura ou dígito verificador inválido. O motivo vai no campo error desse item; o resto do lote não para.
400empty_batchO array items veio vazio.
400batch_too_largeMais de 1.000 itens (500 em /records). Pagine o lote.
429quota_exceededO lote ultrapassa a cota mensal restante. Leia Retry-After.
06 · RATE LIMITS

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.

Response headers
X-RateLimit-Limit:      60000
X-RateLimit-Remaining:  55872
X-RateLimit-Reset:      2026-07-01T00:00:00Z
Retry-After:            1
DURANTE O ACESSO ANTECIPADO

Os 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.