DOCUMENTACIÓN · v1 · 2026.05

De cero al primer 200 OK en 60 segundos.

Una API. Un schema JSON. Un único formato de error para todos los identificadores de Sudamérica. Esta es la guía mínima para llegar de cero a tu primera respuesta.

01 · QUICKSTART

Tu primer request

Mandá un array items con value, country y type a /v1/validate/tax-ids. Recibís un results con un objeto por ítem: normalized, formatted, country, type y valid. Cuando valid es false, leé el error — siempre es accionable. El mismo endpoint valida 1 o N.

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

Cualquier cliente HTTP sirve

Todavía no shippeamos SDKs. La API es REST + JSON estricto, así que cURL, fetch, requests o net/http funcionan out of the box. Los ejemplos de abajo cubren los casos más comunes.

03 · AUTH

API keys

Mandá el header X-API-Key en cada request. Las keys empiezan con nd_ seguido de 30 chars base62 (33 chars en total). Nunca expongas tu key en código del cliente — usala solo desde un servidor, función o infra de confianza.

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

Anatomía del payload

Cada endpoint de Validate acepta un shape plano. Los campos extra se ignoran. Si mandás algo inválido, recibís un 422 con los campos fallidos 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 REQUERIDOS
  • country
    string · ISO 3166-1 alpha-2
    Excepto IBAN / Domain — esos son estándares globales.
  • type
    string · enum
    Ver cobertura · todos los tipos soportados.
  • value
    string · raw input
    Espacios, puntos y guiones permitidos — los limpiamos y canonicalizamos.
POST /v1/validate/tax-idsFull reference →

Tax IDs

POST /v1/validate/accountsFull reference →

Cuentas

POST /v1/validate/emailsFull reference →

Emails

POST /v1/validate/phonesFull reference →

Teléfonos

POST /v1/validate/recordsFull reference →

Records

05 · ERRORES

Códigos posibles

HTTP estándar más códigos de warning del producto dentro de la respuesta. valid: false no es un error HTTP — devolvemos 200 con valid: false y una razón legible.

Cada respuesta incluye un header X-Request-Id, también devuelto en los bodies de error. Cuando reportes un problema a hello@normadata.io, incluilo — nos permite trazar la request exacta en nuestros logs.

StatusCodeSignificado
200results[]Lote procesado. Leé results[]: cada resultado trae su propio valid y un error cuando valid es false.
400empty_batchJSON mal formado o array items vacío. El code indica la causa (empty_batch, batch_too_large).
401invalid_api_keyHeader X-API-Key faltante o inválido.
429quota_exceededCuota mensual o rate por key excedido. Leé Retry-After en segundos.
5xxinternal_errorError inesperado del servidor. Reintentá en 5s con jitter.
200valid: falseEstructura o dígito verificador inválido. El motivo viaja en el campo error de ese ítem; el resto del lote no se interrumpe.
400empty_batchEl array items vino vacío.
400batch_too_largeMás de 1.000 ítems (500 en /records). Paginá el lote.
429quota_exceededEl lote supera la cuota mensual restante. Leé Retry-After.
06 · RATE LIMITS

Por key durante acceso anticipado

Los rate limits se configuran por API key durante acceso anticipado. Los números concretos van en la cuenta una vez que estés onboarded. La respuesta incluye los headers estándar X-RateLimit-* para que tu cliente pueda hacer back-off limpio.

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

Los límites se negocian por workload. Si necesitás más burst o quota, mencionalo en el formulario de waitlist y lo seteamos antes de emitir tu key.

¿Tenés una pregunta puntual?

Email a hello@normadata.io — respondemos en 24h o antes.