Skip to content

Autenticación y Rate Limiting

Todos los endpoints requieren autenticación mediante API key en el header:

Authorization: Bearer sk-normatia-xxxxx

La API B2B es un producto separado de la aplicación web. La key se solicita durante el periodo beta a través de normatia.com/es/api. El acceso se activa manualmente.

Toda API key está ligada a un api_plan que incluye exactamente un country_code (ISO 3166-1 alpha-2). No existen planes multi-país en la v1.

API key → api_plan → country_code

El middleware extrae el country_code del plan y lo inyecta en el contexto de cada request. El developer no necesita pasar el país explícitamente.

Ejemplo de plan:

CampoValor
namebeta-es
country_codees
monthly_limit500
rate_limit_pm10 req/min para /verify

Si en el futuro un cliente necesita España y Portugal, usará dos keys en dos planes distintos.

El country_code del plan filtra automáticamente todas las búsquedas:

  • /location/search — solo devuelve geografías del país de la key
  • /codes/search — solo devuelve normativas del país de la key
  • /verify — el RAG busca únicamente en los embeddings del país de la key

Si una request intenta acceder a datos de otro país (p. ej. pasando geo_id=PT-110300 con una key española), la API devuelve 403 country_mismatch.

TipoLímiteScope
Rate limit60 req/min/location y /codes
Rate limit10 req/min/verify
Quota mensualSegún api_plan.monthly_limit/verify únicamente

La quota se reinicia en la fecha aniversario de activación de la key, no el día 1 del mes. Si la key se activó el 15 de marzo, el próximo ciclo empieza el 15 de abril.

Cuando la quota está agotada, /verify devuelve 429 quota_exceeded hasta el inicio del siguiente ciclo. Los endpoints de /location y /codes no consumen quota y siguen funcionando.

Todos los errores siguen la misma estructura:

{
"error": "ambiguous_location",
"message": "Se encontraron varios municipios para 'Villanueva'. Selecciona uno de los candidatos.",
"candidates": [
{
"geo_id": "ES-28185",
"name": "Villanueva de la Cañada",
"level": "municipality"
}
]
}
CampoTipoDescripción
errorstringCódigo de error legible por máquina (snake_case)
messagestringDescripción legible por humanos
candidatesarrayOpciones de desambiguación cuando error = ambiguous_location

Códigos de error comunes:

StatusCódigoCondición
400missing_scopeNi geo_id ni codes fueron proporcionados
400invalid_codeUn slug de normativa no existe
400invalid_versionLa versión especificada no existe
403country_mismatchEl geo_id pertenece a otro país
403plan_not_allowedEl plan no tiene acceso al endpoint
404not_foundEl identificador referenciado no existe
429quota_exceededSe han agotado los créditos del plan