Paginación, idempotencia y manejo de errores
La API de Ody utiliza paginación por cursor opaco en sus puntos finales de lista, un encabezado Idempotency-Key para reintentos seguros de envío de mensajes, y un sobre de error uniforme con un ID de solicitud en cada respuesta — esta guía cubre los tres.
Paginación por cursor
GET /v1/api/contacts y GET /v1/api/conversations se paginan con ?limit= y ?cursor=:
curl "https://api.ody.co/v1/api/contacts?limit=100" \
-H "Authorization: Bearer ody_live_…"
La respuesta incluye un nextCursor — pásalo de vuelta como ?cursor= para obtener la siguiente página, y detente cuando sea null:
{ "contacts": [ … ], "nextCursor": "eyJ…" }
- Los cursores son opacos — siempre pásalos textualmente; un cursor modificado o caducado devuelve
400 invalid_argument. - Límites de tamaño de página: contactos predeterminado 50, máximo 200; conversaciones predeterminado 50, máximo 100.
GET /v1/api/messages/search(predeterminado 25, máximo 100) yGET /v1/api/calls(predeterminado 50, máximo 200) solo aceptan?limit=, sin cursores. - Los SDK oficiales siguen
nextCursorpor ti conlistAll()/list_all()— consulta Inicio rápido del SDK: TypeScript y Python.
Envíos de mensajes idempotentes
Una falla de red después de POST /v1/api/messages te deja sin saber si el mensaje se envió — reintentar a ciegas conlleva el riesgo de un doble envío. Envía un encabezado Idempotency-Key (cualquier cadena de hasta 200 caracteres, única por envío lógico) y los reintentos se vuelven seguros:
curl https://api.ody.co/v1/api/messages \
-H "Authorization: Bearer ody_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-shipped" \
-d '{"to":"+15125550123","body":"Your order shipped!"}'
- La primera respuesta exitosa se almacena durante 24 horas; cualquier reintento con la misma clave en ese período la reproduce textualmente en lugar de enviar de nuevo, con un encabezado de respuesta
Idempotency-Replayed: true. - Deriva la clave de tu propio evento de negocio ("order-1042-shipped"), no de un valor aleatorio por intento — el objetivo es que los reintentos la compartan.
El sobre de error
Cada respuesta de error utiliza la misma forma:
{ "error": { "code": "permission_denied", "message": "This API key is missing the 'messages:send' scope", "requestId": "req_…" } }
| Estado | Código | Qué hacer |
|---|---|---|
400 |
invalid_argument |
Corrige la solicitud — el mensaje indica qué está mal |
401 |
unauthenticated |
La clave falta, es inválida o ha sido revocada. No reintentes; alerta al propietario de la integración |
403 |
permission_denied |
El mensaje nombra el alcance faltante — crea una clave que lo tenga |
404 |
not_found |
El recurso no existe en este espacio de trabajo |
409 |
failed_precondition |
El espacio de trabajo aún no puede hacer esto (por ejemplo, no hay un número activo desde el cual enviar). Muéstralo, no reintentes |
429 |
resource_exhausted |
Límite de tasa alcanzado — espera Retry-After segundos, luego reintenta con retroceso exponencial |
500 |
internal |
Reintenta con retroceso exponencial y fluctuación; limita los reintentos |
ID de solicitud
Cada respuesta — exitosa o con error — lleva un encabezado X-Request-Id, replicado como requestId en los cuerpos de error. Regístralo junto con tus propios registros de solicitud, y cítalo cuando contactes a soporte: esto localiza la solicitud exacta de nuestro lado. También puedes proporcionar tu propio X-Request-Id (hasta 64 caracteres, letras/dígitos/_/-) y Ody lo replicará, lo que facilita la correlación de los reintentos.
Artículos relacionados
Preguntas frecuentes
¿Cómo obtengo la siguiente página de resultados?
Pasa el `nextCursor` de la respuesta anterior como `?cursor=` en la siguiente solicitud. Un `nextCursor` nulo significa que has llegado al final.
¿Qué sucede si reintento un envío con la misma Idempotency-Key?
Dentro de las 24 horas, Ody reproduce la primera respuesta almacenada en lugar de enviar de nuevo, y añade un encabezado `Idempotency-Replayed: true`.
¿Qué debo enviar al soporte cuando algo falla?
El `requestId` del cuerpo del error (también el encabezado de respuesta `X-Request-Id`) — nos permite encontrar la solicitud exacta en nuestros registros.