Límites
La Partner API limita la tasa de solicitudes por credencial, con una ventana configurable por el colegio. Cada respuesta te dice cuánto presupuesto queda, y un exceso responde 429 con instrucciones precisas de espera — nunca con un corte silencioso.
Límite de tasa por credencial
Cada credencial de partner tiene una ventana de tasa propia. Por defecto: 600 solicitudes cada 60 segundos. La ventana es fija (no deslizante): parte con la primera solicitud y, cumplidos los segundos de la ventana, el contador vuelve a cero.
El colegio puede ajustar ambos valores por credencial — la ventana entre 1 y 86.400 segundos, el máximo entre 1 y 1.000.000 de solicitudes — desde la consola o vía API:
curl -X PATCH "https://app.edugoverna.com/api/integrations/partner-credentials/{partnerCredentialId}" \
-H "x-api-key: {api_key_de_organizacion}" \
-H "Content-Type: application/json" \
-d '{ "rateLimitWindowSeconds": 60, "rateLimitMaxRequests": 1200 }'
Esta ruta es de la API de organización (requiere el permiso integrations.write con sesión de miembro o API key del colegio): los límites los administra quien responde por los datos, no quien los consume. Valores fuera de rango responden PARTNER_RATE_LIMIT_WINDOW_INVALID o PARTNER_RATE_LIMIT_MAX_INVALID (422).
Tolerancia documentada. El contador se lee y se escribe en dos pasos sin
transacción (la base de datos no las ofrece). Bajo ráfagas muy concurrentes
sobre una misma credencial, unas pocas solicitudes pueden colarse por encima
del máximo antes de que el 429 cierre la ventana; el exceso es de unidades,
nunca de órdenes de magnitud, y se corrige al reiniciar la ventana. Diseña tu
cliente para respetar X-RateLimit-Remaining, no para probar el borde.
Encabezados de estado
Superadas las tres primeras puertas de acceso (credencial, conexión y contrato), toda respuesta de la Partner API — incluido el propio 429 y los 403 de permiso o alcance — trae el estado de tu ventana. Un rechazo anterior a esas puertas (un 401 de credencial, por ejemplo) no consume presupuesto y llega sin estos encabezados:
- Nombre
X-RateLimit-Limit- Tipo
- integer
- Descripción
El máximo de solicitudes de la ventana vigente.
- Nombre
X-RateLimit-Remaining- Tipo
- integer
- Descripción
Cuántas solicitudes te quedan en la ventana.
- Nombre
X-RateLimit-Reset- Tipo
- integer
- Descripción
Cuándo se reinicia la ventana, en segundos Unix (UTC).
Cuando llegas al límite
Agotada la ventana, la API responde 429 PARTNER_RATE_LIMITED con el encabezado Retry-After (en segundos) y el mismo detalle en el cuerpo:
{
"error": {
"code": "PARTNER_RATE_LIMITED",
"message": "Demasiadas solicitudes. Espera antes de reintentar.",
"details": {
"limit": 600,
"windowSeconds": 60,
"retryAfterSeconds": 17
}
}
}
Espera exactamente lo indicado y reintenta: la solicitud rechazada no consumió presupuesto de la ventana siguiente.
Tope de audiencia por campaña
Independiente de la tasa, la creación de campañas de consentimiento tiene un tope estructural: hasta 100 estudiantes en línea por solicitud (students en POST /partner/v1/organizations/:organizationId/consents/campaigns). El endpoint crea una solicitud de consentimiento por estudiante — y de paso hace upsert del estudiante, del apoderado y del vínculo — de forma síncrona, así que el tope existe para que la respuesta llegue en segundos y no en minutos.
Para audiencias mayores, envía la campaña en lotes de hasta 100. Cada elemento acepta un idempotencyKey propio (y la campaña uno global), de modo que reenviar un lote que falló a medias no duplica solicitudes ni envíos.
Los cuerpos de solicitud tienen además límites de campo declarados en cada esquema (largos máximos de strings, tamaños de listas); un cuerpo que los excede responde 422 VALIDATION_ERROR con el detalle campo por campo — ver Errores.
Buenas prácticas
- Regula del lado del cliente. Si vas a hacer una carga masiva, fija tu propia tasa por debajo del límite (por ejemplo, al 80%) en vez de chocar con el 429 y reaccionar.
- Lee
X-RateLimit-Remainingen vuelo. Cuando se acerque a cero, desacelera antes de que la API te frene. - Respeta
Retry-Aftery agrega jitter. Si varios procesos tuyos comparten la credencial, un retraso aleatorio pequeño evita que todos reintenten en el mismo segundo. - Sincroniza incremental. Con
sincey los cursores un trabajo periódico consulta solo lo nuevo; con webhooks muchas consultas dejan de ser necesarias. - Una credencial por sistema. Como el límite es por credencial, separar sistemas en credenciales distintas evita que un proceso ruidoso deje sin presupuesto al resto — y permite pedirle al colegio un límite mayor solo donde hace falta.