Códigos de error
Todos los códigos de error que puede devolver la API de Bitelio, qué significan y cómo solucionarlos
Resumen
Los errores de la API de Bitelio siguen una forma consistente, diseñada para que puedas identificar el problema rápido. Cada error trae:
- Un código de error legible por máquina sobre el que tu código puede ramificar
- Un mensaje legible por humanos que describe el fallo
- Una sugerencia que apunta a la solución probable
- Un ID de solicitud para depuración y conversaciones de soporte
- Detalles de validación a nivel de campo cuando aplican
Códigos de estado HTTP
200 OK
La solicitud se procesó correctamente.
201 Created
El recurso fue creado.
400 Bad Request
Algo está mal en el formato de la solicitud o en sus parámetros — los detalles del error indican qué.
401 Unauthorized
Falta la autenticación o no tuvo éxito. Verifica tu clave de API.
402 Payment Required
Se alcanzó un límite de facturación, o la operación requiere un plan superior. Acompaña a BILLING_LIMIT_EXCEEDED y UPGRADE_REQUIRED.
403 Forbidden
No tienes permitido tocar este recurso — revisa los permisos y el estado del proyecto. También se usa cuando aún falta verificar el correo de la cuenta (EMAIL_VERIFICATION_REQUIRED) o el proyecto fue deshabilitado (PROJECT_DISABLED).
404 Not Found
No existe ningún recurso con ese ID. Confirma que el ID sea correcto.
409 Conflict
La solicitud choca con el estado existente — p. ej., crear un contacto cuyo correo ya está registrado, o renombrarlo a un correo que ya está en uso. Acompaña a CONFLICT.
422 Unprocessable Entity
La validación rechazó la solicitud. El array errors enumera los campos problemáticos.
429 Too Many Requests
Superaste un límite de tasa. Espera antes de reintentar, o pasa a un plan superior.
500 Internal Server Error
Algo se rompió de nuestro lado. Contacta a soporte con el ID de la solicitud.
Formato de respuesta de error
Todos los errores usan esta única estructura:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"statusCode": 422,
"requestId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"errors": [
{
"field": "email",
"message": "Invalid email",
"code": "invalid_string"
}
],
"suggestion": "One or more fields have incorrect types. Check that strings are quoted, numbers are unquoted, and booleans are true/false."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Campos de la respuesta
| Campo | Tipo | Descripción |
|---|---|---|
success | boolean | En errores siempre es false |
error.code | string | Identificador legible por máquina (catalogado abajo) |
error.message | string | Explicación en lenguaje llano de lo que falló |
error.statusCode | number | El estado HTTP |
error.requestId | string | Identificador por solicitud para depuración |
error.errors | array | Desglose por campo (solo fallos de validación) |
error.details | object | Contexto adicional, cuando está disponible (opcional) |
error.suggestion | string | Una pista hacia la solución (opcional) |
timestamp | string | Cuándo ocurrió el error, en ISO 8601 |
Referencia de códigos de error
El campo code está presente en todos los errores para que puedas manejarlos programáticamente. El conjunto completo:
Autenticación y autorización
| Código | Estado | Descripción |
|---|---|---|
UNAUTHORIZED | 401 | Falló la autenticación por un motivo no especificado |
INVALID_CREDENTIALS | 401 | Los datos de inicio de sesión no coinciden |
MISSING_AUTH | 401 | No hay un encabezado Authorization utilizable en la solicitud |
INVALID_API_KEY | 401 | Esa clave de API no existe o no es válida |
REVOKED_API_KEY | 401 | Esa clave era válida y se ha revocado: emite una nueva |
EXPIRED_API_KEY | 401 | Esa clave pasó su fecha de expiración: emite una nueva |
FORBIDDEN | 403 | Esta acción no está permitida |
PROJECT_ACCESS_DENIED | 403 | No tienes acceso a este proyecto |
PROJECT_DISABLED | 403 | El proyecto está actualmente deshabilitado |
EMAIL_VERIFICATION_REQUIRED | 403 | Verifica la dirección de correo de la cuenta antes de hacer esto |
Errores de validación y de entrada
| Código | Estado | Descripción |
|---|---|---|
BAD_REQUEST | 400 | Problema genérico con la solicitud |
VALIDATION_ERROR | 422 | La validación rechazó la solicitud (con errores de campo adjuntos) |
INVALID_EMAIL | 422 | La dirección de correo no tiene un formato válido |
INVALID_REQUEST_BODY | 400 | El cuerpo no se pudo interpretar |
MISSING_REQUIRED_FIELD | 422 | No se proporcionó un campo obligatorio |
Errores de recursos
| Código | Estado | Descripción |
|---|---|---|
RESOURCE_NOT_FOUND | 404 | Ningún recurso coincide (genérico) |
CONTACT_NOT_FOUND | 404 | No existe ese contacto |
TEMPLATE_NOT_FOUND | 404 | No existe esa plantilla |
CAMPAIGN_NOT_FOUND | 404 | No existe esa campaña |
WORKFLOW_NOT_FOUND | 404 | No existe ese workflow |
CONFLICT | 409 | Choca con el estado existente (p. ej., un duplicado) |
Límites de tasa y facturación
| Código | Estado | Descripción |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | La tasa de solicitudes es demasiado alta |
BILLING_LIMIT_EXCEEDED | 402 | Se alcanzó un límite de facturación |
UPGRADE_REQUIRED | 402 | La función requiere un plan superior |
Errores de servidor
| Código | Estado | Descripción |
|---|---|---|
INTERNAL_SERVER_ERROR | 500 | Fallo inesperado de nuestro lado |
DATABASE_ERROR | 500 | Una operación de base de datos no se completó |
EXTERNAL_SERVICE_ERROR | 500 | Un servicio externo no estuvo disponible |
Ejemplos comunes de error
Errores de autenticación
Clave de API inválida
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid secret API key. This endpoint requires a secret key (sk_*), not a public key.",
"statusCode": 401,
"requestId": "abc-123",
"suggestion": "Verify your API key is correct and starts with \"sk_\" for secret keys or \"pk_\" for public keys."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Solución: Confirma la clave en sí y su tipo — los endpoints que requieren una clave secreta esperan un prefijo sk_, mientras que el registro de eventos usa claves pk_.
Falta el encabezado Authorization
{
"success": false,
"error": {
"code": "MISSING_AUTH",
"message": "Authorization header is required",
"statusCode": 401,
"requestId": "abc-123",
"suggestion": "Include an Authorization header with format: \"Authorization: Bearer YOUR_API_KEY\""
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Solución: Envía tu clave como token Bearer en el encabezado Authorization.
Errores de validación
Formato de correo inválido
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"statusCode": 422,
"requestId": "abc-123",
"errors": [
{
"field": "email",
"message": "Invalid email",
"code": "invalid_string"
}
],
"suggestion": "One or more fields have incorrect types. Check that strings are quoted, numbers are unquoted, and booleans are true/false."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Solución: Envía una dirección de correo bien formada. Revisa el array errors para ver exactamente qué campos fueron rechazados.
Faltan campos obligatorios
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"statusCode": 422,
"requestId": "abc-123",
"errors": [
{
"field": "event",
"message": "Required",
"code": "invalid_type"
},
{
"field": "email",
"message": "Required",
"code": "invalid_type"
}
],
"suggestion": "Required fields are missing. Ensure all required fields are included in your request."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Solución: Añade todos los campos obligatorios al cuerpo de la solicitud.
Errores de recursos
Plantilla no encontrada
{
"success": false,
"error": {
"code": "TEMPLATE_NOT_FOUND",
"message": "Template with ID \"tpl_abc123\" was not found",
"statusCode": 404,
"requestId": "abc-123",
"details": {
"resource": "Template",
"id": "tpl_abc123"
},
"suggestion": "Ensure the template ID is correct and belongs to your project. You can list available templates via the API."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Solución: Asegúrate de que el ID de la plantilla exista y pertenezca a tu proyecto.
Límite de tasa
Límite de tasa superado
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please try again later.",
"statusCode": 429,
"requestId": "abc-123",
"suggestion": "You have exceeded the rate limit. Wait a moment before retrying, or upgrade your plan."
},
"timestamp": "2025-11-30T10:30:00.000Z"
}Solución: Añade lógica de reintento con backoff exponencial. Si sueles chocar con el techo, un cambio de plan lo eleva.
Formato de respuesta de éxito
Cuando una solicitud tiene éxito, la respuesta llega como success: true con un objeto data:
{
"success": true,
"data": {
"contact": "cnt_abc123",
"event": "evt_xyz789",
"timestamp": "2025-11-30T10:30:00.000Z"
}
}Campos de la respuesta
| Campo | Tipo | Descripción |
|---|---|---|
success | boolean | En éxito siempre es true |
data | object | Payload específico del endpoint |
Manejo de errores en tu código
Ejemplo en JavaScript/TypeScript
try {
const response = await fetch('https://api.bitelio.com/v1/track', {
method: 'POST',
headers: {
'Authorization': `Bearer ${publicKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'purchase',
email: 'user@example.com'
})
});
const data = await response.json();
if (!data.success) {
// Algo salió mal
console.error(`Error [${data.error.code}]:`, data.error.message);
// Muestra la solución sugerida por la API
if (data.error.suggestion) {
console.log('Suggestion:', data.error.suggestion);
}
// Conserva el ID de la solicitud para soporte
console.log('Request ID:', data.error.requestId);
// Ramifica según el código específico
switch (data.error.code) {
case 'VALIDATION_ERROR':
// Imprime cada campo que falló
data.error.errors?.forEach(err => {
console.log(`${err.field}: ${err.message}`);
});
break;
case 'INVALID_API_KEY':
// Pide al usuario que revise su clave
break;
case 'REVOKED_API_KEY':
case 'EXPIRED_API_KEY':
// La clave ERA válida: rótala, en vez de pedir que busquen una errata
break;
case 'RATE_LIMIT_EXCEEDED':
// Reintenta más tarde con backoff
break;
}
return;
}
// Camino de éxito
console.log('Event tracked:', data.data);
} catch (error) {
console.error('Network error:', error);
}Ejemplo en Python
import requests
response = requests.post(
'https://api.bitelio.com/v1/track',
headers={
'Authorization': f'Bearer {public_key}',
'Content-Type': 'application/json'
},
json={
'event': 'purchase',
'email': 'user@example.com'
}
)
data = response.json()
if not data.get('success'):
error = data['error']
print(f"Error [{error['code']}]: {error['message']}")
# Muestra la solución sugerida
if 'suggestion' in error:
print(f"Suggestion: {error['suggestion']}")
# Conserva el ID de la solicitud
print(f"Request ID: {error['requestId']}")
# Imprime los fallos a nivel de campo
if error['code'] == 'VALIDATION_ERROR':
for err in error.get('errors', []):
print(f"{err['field']}: {err['message']}")
else:
print(f"Event tracked: {data['data']}")Guía de resolución de problemas
Uso de los IDs de solicitud
Cada error viene con un requestId que sigue la solicitud a través de todo nuestro stack. Eso lo hace valioso en dos frentes:
Para desarrolladores:
- El ID queda grabado en cada línea de log de esa solicitud
- Busca por ID en tus logs y aparece de golpe cada entrada relacionada
- Sigue una solicitud a través de API → Base de datos → Cola → Worker
Para soporte:
- Pega el ID de la solicitud en tu mensaje
- Explica qué estabas intentando hacer
- Adjunta la respuesta de error completa cuando puedas
Ejemplo: Dado el ID de solicitud f47ac10b-58cc-4372-a567-0e02b2c3d479, una búsqueda en los logs de nuestro lado revela:
- El cuerpo de la solicitud tal como llegó
- Las consultas de base de datos que se ejecutaron
- Cualquier job en segundo plano que haya generado
- El stack trace completo, si existe alguno
Eso significa que normalmente podemos diagnosticar el problema de inmediato, sin ida y vuelta pidiéndote más detalles.
Cómo encontrar los IDs de solicitud
El ID de solicitud aparece en tres lugares:
- Respuestas de error: el campo
error.requestId - Encabezados de respuesta: el encabezado
X-Request-ID(presente también en éxitos) - Los logs de tu aplicación: escribe el encabezado en tus propios logs para poder correlacionar
// Captura el ID de la solicitud en tu propio logging
const response = await fetch('https://api.bitelio.com/v1/send', {
// ... tu solicitud
});
const requestId = response.headers.get('X-Request-ID');
console.log('Request ID:', requestId); // Guárdalo para correlación
const data = await response.json();
if (!data.success) {
console.error('Error:', data.error.message);
console.error('Request ID:', data.error.requestId); // Coincide con el encabezado
}Problemas comunes y soluciones
Buenas prácticas
- Revisa
successprimero, antes de tocar el resto de la respuesta - Registra los IDs de solicitud para que la depuración y las solicitudes de soporte vayan más rápido
- Falla con elegancia, traduciendo los errores en mensajes que tus usuarios entiendan
- Reintenta los fallos transitorios usando backoff exponencial
- Vigila tus tasas de error para que los problemas salgan a la luz temprano
- Ramifica según los códigos de error, no solo según los estados HTTP, en tu manejo
Obtener ayuda
¿Sigues atascado? Recorre esta lista:
- Empieza por el campo
suggestiondel propio error - Compara tu solicitud contra la Referencia de la API
- Busca tu código de error exacto en esta documentación
- Escribe a soporte e incluye tu ID de solicitud
- Pregunta a la comunidad — otros desarrolladores a menudo se han topado con lo mismo