Saltar al contenido principal

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"
}
CampoTipoDescripción
statusCodenumberEl código de estado HTTP, repetido en el cuerpo.
errorstringUna etiqueta corta y legible por máquina para el estado (p. ej. Bad Request, Forbidden).
messagestringUna 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"
}
nota

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 en 429).
  • 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}`);
}
consejo

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.