Cómo responde la API cuando algo sale mal, cuántas llamadas caben por minuto, cómo recorrer listas grandes y cómo repetir una solicitud sin duplicar nada.
Formato de los errores
Todo error de /api/v1 viene en application/problem+json (RFC 9457):
{
"type": "about:blank",
"title": "Unprocessable Content",
"status": 422,
"detail": "Algunos campos no son válidos.",
"code": "validation_failed",
"errors": { "address.line": ["El campo dirección es obligatorio."] },
"request_id": "9a6c1f2e-3b4d-4e5f-8a9b-0c1d2e3f4a5b"
}
codees estable: no cambia entre versiones. Decida por él.detailes para que lo lean las personas, en el idioma pedido enAccept-Language(pt-BR,enoes). El texto puede cambiar.errorssolo envalidation_failed: mensajes por campo.scopessolo eninsufficient_scope: los permisos que faltan.request_ides el mismo del encabezadoX-Request-Id. Infórmelo al soporte.
Códigos
code |
Estado | Significa |
|---|---|---|
unauthenticated |
401 | Clave ausente, incorrecta, vencida o revocada |
api_disabled |
403 | La API está desactivada en la escuela |
insufficient_scope |
403 | La clave no tiene el permiso de la ruta |
forbidden |
403 | Acceso denegado |
student_limit_reached |
403 | El plan de la escuela llegó al límite de alumnos |
not_found |
404 | El registro no existe en esta escuela |
method_not_allowed |
405 | Método HTTP no aceptado en la dirección |
bad_request |
400 | Solicitud mal formada |
invalid_cursor |
400 | Cursor de página inválido: reinicie la lista |
idempotency_key_required |
400 | La ruta exige el encabezado Idempotency-Key |
idempotency_key_invalid |
400 | Idempotency-Key fuera del formato |
conflict |
409 | La solicitud entra en conflicto con el estado actual del registro |
idempotency_in_progress |
409 | Otra solicitud con la misma Idempotency-Key todavía está en curso |
enrollment_conflict |
409 | El alumno ya tiene una matrícula vigente en el curso o trayecto (vea existing_enrollment_id) |
enrollment_not_cancellable |
409 | La matrícula ya está cancelada o concluida |
installment_not_payable |
409 | La cuota no puede tener segunda copia (pagada, cancelada o dispensada) |
boleto_still_valid |
409 | El boleto actual todavía vale y no se puede cancelar en el banco |
gateway_not_connected |
409 | La escuela no conectó la cuenta de cobro |
student_inactive |
409 | El alumno está inactivo |
student_without_portal_access |
409 | El alumno no tiene e-mail o cuenta en el portal |
portal_not_configured |
409 | El portal del alumno de la escuela no tiene dirección |
portal_link_ambiguous_email |
409 | Dos alumnos de la escuela usan el mismo e-mail |
validation_failed |
422 | Campos inválidos (detalle en errors) |
idempotency_key_reused |
422 | La Idempotency-Key ya se usó con otros datos |
rate_limited |
429 | Límite de llamadas alcanzado |
internal_error |
500 | Error interno en EduPay |
gateway_error |
502 | El banco rechazó o no respondió |
http_error |
otros | No fue posible atender la solicitud |
Límites de llamadas
| Límite | Por minuto |
|---|---|
Consultas (GET) por clave |
120 |
Escrituras (POST, PATCH, DELETE) por clave |
30 |
| Todas las claves de la escuela sumadas | 300 |
Toda respuesta trae X-RateLimit-Limit y X-RateLimit-Remaining. Si pasa el límite, la respuesta es 429 con Retry-After (segundos). Espere ese tiempo y repita.
Las rutas del plugin de Moodle tienen su propio límite y no entran en esa cuenta.
Listas en páginas
Las listas devuelven hasta limit elementos (de 1 a 200; sin él, 50), en orden de creación:
{
"data": [ { "id": 101, "...": "..." }, { "id": 102, "...": "..." } ],
"meta": { "next_cursor": "eyJpZCI6MTAyfQ", "has_more": true }
}
Para la página siguiente, repita la llamada con cursor= igual a meta.next_cursor, manteniendo los demás filtros. Pare cuando has_more sea false. El cursor no salta ni repite registros, aunque entren registros nuevos en el medio.
Para sincronizar solo lo que cambió, use updated_since (fecha y hora en ISO 8601).
Repetir con seguridad
Las escrituras (POST y PATCH) aceptan el encabezado Idempotency-Key; crear una matrícula lo exige. Envíe un código único por solicitud, de 1 a 255 caracteres visibles (un UUID o el número del pedido en su sistema).
| Situación | Qué ocurre |
|---|---|
| Misma clave, misma solicitud, en hasta 24 horas | Vuelve la primera respuesta, con Idempotent-Replayed: true. No se graba nada de nuevo |
| Misma clave, datos diferentes | 422 con code idempotency_key_reused |
| Misma clave mientras la primera solicitud todavía está en curso | 409 con code idempotency_in_progress: espere unos segundos y repita |
| La primera solicitud dio error | La clave queda libre: corrija y repita con la misma clave |
La clave vale por escuela y por 24 horas. "Misma solicitud" significa el mismo método, la misma dirección y los mismos datos, en cualquier orden de los campos.
Cuándo repetir
429: después delRetry-After.500,502,503o tiempo agotado: con espera creciente (1 s, 2 s, 4 s...) y la mismaIdempotency-Key.400,401,403,404,409y422: no sirve repetir igual. Corrija la solicitud, la clave o el permiso.