Saltar al contenido principal
StudioMeyer
Seguridad AI-Ready: Rate Limiting, validación y anti-spam
Volver al Blog
IA y Automatización 15 de febrero de 2026 9 min de lecturapor Matthias Meyer

Seguridad AI-Ready: Rate Limiting, validación y anti-spam

Los endpoints de API públicos son puerta para spam. Cómo Zod, rate limiting y sanitización de errores aseguran sitios AI-Ready desde el día uno.

Los sitios web AI-Ready tienen endpoints de API publicos. Ese es todo el punto -- los agentes de IA deben poder usar servicios sin intervencion humana. Pero endpoints publicos tambien significa: cualquiera puede llamarlos. No solo agentes de IA utiles, sino tambien bots, scrapers y atacantes.

Quien construye un sitio web AI-Ready y no piensa en la seguridad desde el dia uno, esta construyendo una puerta abierta.

El problema: Publico significa atacable

Un sitio web clasico tiene un formulario de contacto. Proteccion contra spam? reCAPTCHA, campos honeypot, quizas un rate limit. Eso funciona porque los humanos rellenan formularios -- y la mayoria de los bots no pueden resolver CAPTCHAs.

Un sitio web AI-Ready tiene endpoints de API como /api/v1/quote o /api/v1/consultation. Estos endpoints estan disenados para uso automatizado. Un CAPTCHA destruiria todo el proposito -- los agentes de IA deben acceder programaticamente a ellos.

Esto crea un dilema: La puerta debe estar abierta para agentes legitimos, pero cerrada para el abuso. La solucion no es un unico mecanismo, sino multiples capas.

Capa 1: Validacion de entrada con Zod

La primera linea de defensa es la mas simple: verificar si los datos entrantes son validos antes de que activen cualquier cosa.

Zod es una biblioteca de validacion para TypeScript que verifica datos contra un esquema definido. Sin magia, sin IA -- pura validacion estructural.

Por que no simplemente sentencias if?

Se podria. Pero con estructuras de datos complejas, esto rapidamente se vuelve inmanejable y propenso a errores. Zod impone una estructura clara:

import { z } from "zod";

const quoteSchema = z.object({
  projectType: z.enum(["website", "webshop", "webapp", "redesign"]),
  pages: z.string().optional(),
  features: z.string().optional(),
});

// En la ruta de la API:
const parsed = quoteSchema.safeParse(body);
if (!parsed.success) {
  return ApiError.validation(
    "Datos de entrada invalidos",
    parsed.error.issues
  );
}

Que previene Zod concretamente

  • Campos obligatorios faltantes: Una solicitud sin projectType se rechaza inmediatamente
  • Tipos incorrectos: Un valor de pages como true en lugar de un string se detecta
  • Valores inesperados: Un projectType de "hacking" se bloquea por el enum
  • Intentos de inyeccion: La inyeccion SQL o NoSQL a traves de campos manipulados se dificulta por la tipificacion estricta

Suena basico -- y lo es. Pero la mayoria de las vulnerabilidades de seguridad no surgen de ataques sofisticados, sino de la falta de validacion de entrada.

Practica: Validar una solicitud de consulta

const consultationSchema = z.object({
  name: z.string().min(2).max(100),
  email: z.string().email(),
  phone: z.string().optional(),
  topic: z.string().min(5).max(500),
});

Esta validacion de esquema asegura:

  • Nombre tiene al menos 2 y maximo 100 caracteres (sin cadenas vacias, sin entradas de longitud novelistica)
  • Email es un formato de email valido (sin inyeccion de texto libre)
  • Tema tiene 5-500 caracteres (sin envio vacio, sin payload de 10MB)

Capa 2: Rate Limiting

La validacion protege contra datos incorrectos. El rate limiting protege contra demasiadas solicitudes.

Como funciona el Rate Limiting

El principio es simple: contar cuantas solicitudes hace una direccion IP dentro de una ventana de tiempo. Si supera el limite, recibe un estado 429 Too Many Requests.

IP 192.168.1.1:
  Ventana: 60 segundos
  Limite: 60 solicitudes
  Actual: 47
  → Permitido

IP 10.0.0.5:
  Ventana: 60 segundos
  Limite: 60 solicitudes
  Actual: 61
  → Bloqueado (Retry-After: 23s)

Diferentes limites para diferentes endpoints

No todos los endpoints necesitan el mismo limite:

Tipo de endpointLimiteRazon
Endpoints GET (Portfolio, Services)60/minuto por IPLeer es barato, mayor tolerancia
Endpoints POST (Quote, Consultation)10/minuto por IPEscribir es costoso, control mas estricto
Endpoints de llamadas externas (AI-Ready Check)10/minuto por IPHacen llamadas HTTP externas, alto riesgo de abuso

Por que la diferencia? Un endpoint GET lee datos de la base de datos -- eso es rapido y barato. Un endpoint POST escribe datos, potencialmente envia emails o dispara otras acciones. Y un endpoint que llama a sitios web externos (como nuestro AI-Ready Check) podria ser abusado para ataques DDoS contra terceros.

La respuesta en Rate Limiting

Cuando se alcanza un limite, el cliente recibe una respuesta clara:

{
  "error": "Rate limit exceeded. Max 60 requests per minute.",
  "retryAfterMs": 23000
}

Ademas de headers HTTP que le dicen al cliente (o agente) donde esta:

HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1739654400

Un agente de IA bien construido lee estos headers y espera automaticamente. Un atacante al menos recibe un freno.

Capa 3: Sanitizacion de errores

Cuando algo sale mal -- y siempre sale mal eventualmente -- el mensaje de error no debe revelar detalles internos.

Que aprende un atacante de los mensajes de error

Un error sin sanitizar podria verse asi:

{
  "error": "PrismaClientKnownRequestError: Invalid `prisma.client.create()` invocation in /home/user/app/lib/db.ts:47:3",
  "stack": "at Object.create (/home/user/node_modules/@prisma/client/runtime/library.js:123:45)"
}

Que revela esto? El ORM (Prisma), la ruta del archivo, la linea en el codigo, la version de Node.js. Un atacante ahora sabe donde buscar.

Como devolvemos errores

Nuestra API siempre devuelve el mismo formato:

{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error"
  }
}

En modo desarrollo, los desarrolladores ven el mensaje de error completo. En produccion, cada llamante ve solo "Internal server error". Sin stack trace, sin ruta de archivo, sin nombre de ORM.

Los codigos de error

Usamos seis codigos de error definidos:

CodigoEstado HTTPSignificado
UNAUTHORIZED401API key faltante o invalida
FORBIDDEN403La key no tiene el permiso necesario
RATE_LIMITED429Demasiadas solicitudes
VALIDATION_ERROR400Datos de entrada invalidos
NOT_FOUND404Recurso no encontrado
INTERNAL_ERROR500Error del servidor (sin detalles)

Un agente de IA puede leer estos codigos y reaccionar: esperar en 429, corregir la solicitud en 400, autenticarse en 401.

Capa 4: Configuracion CORS

CORS (Cross-Origin Resource Sharing) controla quien puede acceder a la API y desde donde.

Para endpoints de discovery AI-Ready (como agents.json), CORS debe estar abierto -- los agentes de IA vienen de todas partes. Pero hay matices:

Endpoints de Discovery (solo GET):
  Access-Control-Allow-Origin: *
  Access-Control-Allow-Methods: GET
  → Cualquiera puede leer, pero solo leer.

Endpoints de API:
  Access-Control-Allow-Methods: GET, POST, OPTIONS
  Access-Control-Allow-Headers: Content-Type, Authorization
  → Acceso completo, pero solo con headers permitidos.

El metodo OPTIONS es para solicitudes preflight -- los navegadores primero preguntan "Puedo?" antes de enviar la solicitud real. Cacheamos esta respuesta preflight por 24 horas (Access-Control-Max-Age: 86400) para evitar solicitudes innecesarias.

Capa 5: Lo que no se expone

Igual de importante que asegurar los endpoints publicos es la pregunta: Que permanece privado?

En nuestro caso, eso incluye:

  • Herramientas MCP internas (242 herramientas para desarrollo web -- no publicas)
  • IDs y estructuras de base de datos (sin IDs de Prisma en las respuestas de la API)
  • Tokens de autenticacion (nunca en logs ni en respuestas)
  • Configuracion del servidor (sin numeros de version, sin rutas)
  • Datos personales de usuarios (RGPD de todos modos, pero tambien aislados tecnicamente en la API)

Suena obvio, pero no lo es. Muchas APIs devuelven IDs de base de datos ("id": 47), de los que se puede deducir el numero total de registros. O registran stack traces en logs que son legibles publicamente a traves de herramientas de error-tracking.

Conceptos de autenticacion: Hoy y manana

Lo que tenemos hoy

Para los endpoints publicos de negocio (Portfolio, Services, Quote), deliberadamente no hay autenticacion. La razon: estos endpoints entregan informacion que tambien es visible publicamente en el sitio web. Una calculadora de precios no es un secreto.

Para endpoints avanzados (API de Animaciones, Analytics), usamos API keys con permisos con alcance definido:

Bearer sk_live_abc123...

Scopes: animations:read, animations:generate
Rate Limit: 100/min (configurable por key)

Lo que trae el futuro

A medida que A2A y protocolos similares ganen adopcion mas amplia, la cuestion de la autenticacion de agentes se volvera central. Como demuestra un agente de IA que actua en nombre de un usuario especifico?

Posibles enfoques:

  • OAuth 2.0 Token Relay: El agente recibe un token del usuario y lo reenvie
  • Certificados de identidad de agente: Certificados digitales para agentes verificados
  • DID (Identificadores Descentralizados): Identidades auto-soberanas para agentes

A dia de hoy, ninguno de estos enfoques esta estandarizado para comunicacion entre agentes. Pero los fundamentos (OAuth, certificados) existen -- lo que falta es la estandarizacion en el contexto A2A.

La regla de oro: La seguridad no es una funcionalidad, es un prerrequisito

El error mas comun con sitios web AI-Ready: construir primero los endpoints, asegurarlos "despues". En nuestra experiencia, "despues" nunca llega -- o llega solo despues del primer incidente.

Nuestra checklist para cada nuevo endpoint

[ ] Esquema Zod definido?
[ ] Rate limit configurado (GET: 60/min, POST: 10/min)?
[ ] Respuestas de error sanitizadas (sin stack traces)?
[ ] Headers CORS configurados?
[ ] Sin IDs de base de datos en la respuesta?
[ ] Sin datos personales sin autenticacion?
[ ] Logging sin datos sensibles?

Esta checklist no es sobrecarga. Es la diferencia entre un endpoint que es util y uno que se convierte en un problema.

Resumen

CapaProtege contraMecanismo
Validacion de entradaDatos incorrectos/manipuladosEsquemas Zod con tipos estrictos
Rate LimitingSobrecarga y fuerza brutaContadores por IP con ventanas de tiempo
Sanitizacion de erroresFuga de informacionMensajes de error genericos en produccion
CORSAcceso cross-origin no autorizadoControl de acceso basado en headers
Auth (API Keys)Acceso no autorizado a endpoints premiumBearer tokens con permisos con alcance
No exposicionDivulgacion accidental de datosDecisiones conscientes sobre que permanece privado

La seguridad para sitios web AI-Ready no es un tema especial. Sigue los mismos principios fundamentales que cualquier API -- validacion, rate limiting, manejo limpio de errores. La diferencia es que los endpoints estan disenados para acceso automatizado, lo que hace la superficie de ataque mas grande desde el dia uno.

Quien piensa en esto desde el principio no tiene problemas. Quien lo anade despues tiene trabajo por delante.

Matthias Meyer

Matthias Meyer

Founder & AI Director

Founder & AI Director de StudioMeyer. Construye sitios web y sistemas de IA desde hace más de 10 años. Vive en Mallorca desde hace 15 años y dirige un estudio digital AI-First con su propia flota de agentes, más de 680 herramientas MCP y 5 productos SaaS para PYMES y agencias en DACH y España.

securityrate-limitingzodvalidationapiai-ready
Seguridad AI-Ready: Rate Limiting, validación y anti-spam