Manejo de errores
La Public API usa un formato de error consistente en cada endpoint y códigos de estado HTTP estándar. Construye tu cliente para ramificar según el código de estado y leer el cuerpo de error compartido.
Esquema de errores
Cada respuesta de error es un objeto JSON con los mismos tres campos:
{
"statusCode": 403,
"error": "Forbidden",
"message": "You are not allowed to access boards"
}
| Campo | Tipo | Descripción |
|---|---|---|
statusCode | number | El código de estado HTTP, repetido en el cuerpo. |
error | string | Una etiqueta corta y legible por máquina para el estado (p. ej. Bad Request, Forbidden). |
message | string | Una descripción legible por humanos de lo que salió mal. |
La respuesta 429 (límite de tasa) usa la misma forma más un campo adicional retryAfter — consulta más abajo.
Códigos de estado
400 — Bad Request
La solicitud fue inválida o no se puede atender. Causas comunes:
- Un parámetro mal formado (por ejemplo, un ID que no es una cadena hexadecimal de 24 caracteres).
- Falta un campo requerido.
- Un valor de parámetro de consulta inválido.
{
"statusCode": 400,
"error": "Bad Request",
"message": "Invalid parameter: boardId"
}
Recuperación: Corrige la solicitud y reintenta. Estas no tendrán éxito al reintentar sin cambios.
401 — Unauthorized
La autenticación falló. Falta el encabezado Authorization, el token está mal formado o el token expiró.
{
"statusCode": 401,
"error": "Unauthorized",
"message": "Invalid token"
}
Recuperación: Verifica el encabezado Authorization: Bearer <token> y la validez del token. Si el token expiró, crea uno nuevo. Consulta Autenticación.
403 — Forbidden
El token es válido pero carece de permiso para este recurso — típicamente un scope faltante, o una integración que no ha sido agregada al channel o board que intenta alcanzar.
{
"statusCode": 403,
"error": "Forbidden",
"message": "You are not allowed to access boards"
}
Recuperación: Otorga el scope requerido al token, o agrega la integración como participante del recurso. No reintentes a ciegas — la solicitud seguirá fallando hasta que se otorgue el acceso.
404 — Not Found
El recurso solicitado no existe o no se puede acceder con este token.
{
"statusCode": 404,
"error": "Not Found",
"message": "Not Found - The requested resource was not found"
}
Algunos endpoints devuelven 400 con un mensaje descriptivo (por ejemplo, "Channel not found") en lugar de 404 cuando falta un recurso referenciado. Maneja ambos casos al validar IDs.
Recuperación: Verifica el ID del recurso y que el Workspace de tu token lo contenga.
429 — Too Many Requests
Excediste el límite de tasa para ese endpoint. La respuesta lleva un encabezado Retry-After (segundos hasta que la ventana se reinicia) y un campo retryAfter en el cuerpo.
{
"statusCode": 429,
"error": "Too Many Requests",
"message": "Too many requests, please try again later",
"retryAfter": 27
}
Encabezados de respuesta en 429 (y en cada respuesta):
Retry-After— segundos a esperar antes de reintentar (solo en429).X-RateLimit-Limit— el tope por ventana del endpoint.X-RateLimit-Remaining— solicitudes restantes en la ventana actual.X-RateLimit-Reset— cuándo se reinicia la ventana.
Recuperación: Espera el período indicado en Retry-After y luego reintenta. Consulta Límites de tasa para orientación sobre backoff.
500 — Internal Server Error
Algo salió mal del lado de Copera.
{
"statusCode": 500,
"error": "Internal Server Error",
"message": "Internal Server Error - Something went wrong on the server"
}
Recuperación: Reintenta con backoff exponencial. Si persiste, la solicitud en sí está bien — la falla es del lado del servidor.
Manejo de errores en código
Ramifica según el código de estado y reintenta solo los códigos que pueden tener éxito al reintentar (429 y 5xx):
async function callApi(url, init, attempt = 0) {
const res = await fetch(url, init);
if (res.ok) return res.json();
// Retry rate limits and server errors with backoff.
if ((res.status === 429 || res.status >= 500) && attempt < 5) {
const retryAfter = Number(res.headers.get("Retry-After"));
const waitMs = Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: 2 ** attempt * 1000; // exponential backoff fallback
await new Promise((r) => setTimeout(r, waitMs));
return callApi(url, init, attempt + 1);
}
const error = await res.json();
throw new Error(`${error.statusCode} ${error.error}: ${error.message}`);
}
No reintentes 400, 401, 403 ni 404 — indican un problema con la solicitud, el token o los permisos que un reintento no resolverá. En su lugar, expón el message a quien llama.