Errores y límites
Vincent Depassier · 17 de septiembre de 2026
Las tres formas de error
POST /query devuelve un sobre estructurado:
{
"error": {
"code": "SCOPE_VIOLATION",
"message": "No access to table 'invoices'.",
"details": ["..."]
}
}details aparece sólo cuando hay más de una cosa que decir — típicamente una lista de fallas de validación. Programa tu cliente contra code; el mensaje es para un humano leyendo un log y puede reescribirse.
Casi todo /auth/* —registro, login, refresh, las rutas de contraseña, las de proveedores— devuelve en cambio el sobre de servicio, tanto en éxito como en error:
{
"isSuccess": false,
"statusCode": 400,
"message": "Password must be at least 8 characters.",
"data": null,
"errors": ["Password must be at least 8 characters."]
}Todo lo demás —la capa de autenticación, archivos, esquema, endpoints— devuelve un texto plano:
{ "error": "Origin not allowed for this credential." }En estas dos últimas no hay code. Ramifica por el estado HTTP.
Las rutas de players son una variante chica de la forma plana, con un code al lado del mensaje: { "code": "PLAYER_NOT_FOUND", "message": "…" }. El endpoint MCP es distinto otra vez: responde en JSON-RPC.
Códigos que devuelve /query
HTTP | Código | Qué pasó |
400 |
| Ni |
400 |
|
|
400 |
| El cuerpo parsea pero no tiene sentido contra el esquema |
401 |
| Sin credencial, o con una que no vale para este workspace |
403 |
| La credencial pertenece a otro workspace |
403 |
| Una tabla del pedido está fuera de los permisos, o no se permiten agregaciones sobre ella |
403 |
| La mutación pidió anunciar en el Event Bus y la credencial no puede |
408 |
| La operación pasó el tiempo máximo de ejecución |
429 |
| Demasiadas llamadas en este minuto |
429 |
| Se agotó el cupo mensual de llamadas |
429 |
| Se agotaron los bytes de respuesta incluidos en el mes |
500 |
| Falla interna; el detalle queda registrado del lado del servidor |
Los tres 429 vale la pena distinguirlos en tu cliente. Un límite de tasa se despeja solo dentro del minuto y merece un reintento con backoff. Una cuota o un límite de egreso no se despeja hasta que cambia el período de facturación o alguien cambia el plan — reintentar no sirve, y lo correcto es mostrarlo.
Límites
Se miden dos cupos por workspace y por mes: llamadas a la API y egreso, los bytes que cargan tus respuestas. Los dos se ven en API Gateway → Consumo, y los dos se pueden levantar por plan o habilitando pago por uso en la configuración del gateway.
Cuando un workspace pasó sus llamadas incluidas y el pago por uso está activo, las respuestas exitosas traen tres cabeceras más para que puedas verlo:
X-Api-Usage-Overage: true
X-Api-Usage-Current: 120431
X-Api-Usage-Included: 100000Aparte, un límite de tasa por minuto protege al workspace de un cliente desbocado. Es una propiedad del workspace, no de la clave individual.
Límites estructurales de un pedido
Esto no es facturación. Son techos fijos del gateway, y pasarse de uno es 400:
Límite | Valor |
Filas que devuelve una consulta | 1000 (un permiso de tabla puede bajarlo) |
| 50 |
Tablas en | 20 |
Profundidad de relaciones anidadas | 5 |
Columnas en | 100 |
Condiciones en | 50 |
Profundidad de condiciones anidadas | 5 |
Cuerpo de una llamada a un endpoint personalizado | 10 MB |
Pagina con limit y offset. Lee meta.limit de la respuesta en vez de asumirlo: el límite efectivo puede ser menor que el que pediste.
Caché
Una credencial se puede configurar para cachear respuestas de POST /query — sólo lecturas; un cuerpo con mutation no se cachea nunca. Con la caché activa, las respuestas traen:
Cabecera | Significado |
|
|
| Qué clave respondió desde su caché — sólo en |
| Un validador que puedes devolver |
| El modo y el TTL configurados para esa credencial |
Devuelve el ETag como If-None-Match y una entrada cacheada que siga vigente responde 304 Not Modified sin cuerpo, que es la lectura más barata que hay y no gasta egreso.
Cache-Control te dice en qué modo está la credencial:
Modo |
|
Por tiempo |
|
Invalidada por escritura |
|
Híbrido |
|
Apagado |
|
La caché se llavea por credencial —dos claves con permisos distintos nunca comparten una entrada, que es lo que hace seguro encenderla— y, en los modos que invalidan, por tabla: una escritura sobre una tabla tira las respuestas cacheadas que leían de esa tabla, y sólo esas.
Seguir
Query —
POST /queryEsquema —
GET /schema