Errores
Estados HTTP, códigos y diagnóstico de peticiones a la API de Fluyio.
La API combina estados HTTP con un cuerpo JSON estructurado. Guarda el request_id para identificar la petición al solicitar ayuda.
Formato
{
"error": {
"type": "invalid_request_error",
"code": "invalid_param",
"message": "limit must be a positive integer.",
"param": "limit",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}| Campo | Tipo | Descripción |
|---|---|---|
error.type | string | Categoría general para el tratamiento del error. |
error.code | string | Motivo específico que puede interpretar el cliente. |
error.message | string | Descripción para diagnóstico; no es texto final de tu aplicación. |
error.param | string, opcional | Parámetro relacionado, si se conoce. |
error.request_id | string | Coincide con Fluyio-Request-Id. |
Los errores de versión añaden supported_versions. Los de permisos pueden incluir required_scope y granted_scopes; su comprobación ya está activa.
Estados HTTP
| Estado | Significado | Siguiente paso |
|---|---|---|
| 200 | Lectura, actualización, eliminación o acción completada. | Procesa la respuesta. |
| 201 | Suscriptor creado. | Guarda el ID. |
| 400 | Parámetro, campo, cursor, versión o clave de idempotencia no válido. | Corrige la petición. |
| 401 | Credencial ausente o no válida. | Revisa la clave. |
| 403 | Permiso insuficiente, modo test no disponible o límite del plan. | Resuelve el motivo antes de repetir. |
| 404 | Suscriptor no encontrado en la marca. | Revisa el ID. |
| 409 | Conflicto de email, idempotencia o canal suprimido. | Resuelve el conflicto. |
| 422 | Falta un dato necesario para aplicar la operación. | Corrige la identidad del canal. |
| 429 | Límite de peticiones por clave. | Espera Retry-After. |
| 5xx | Error del servidor; una escritura puede tener resultado incierto. | Consulta el estado y la política de idempotencia. |
Tipos y códigos
| Tipo | Códigos principales |
|---|---|
invalid_request_error | invalid_param, invalid_cursor, invalid_version_header, unknown_version, invalid_idempotency_key, profile_limit, resource_not_found, resource_already_exists, channel_unavailable, missing_required_field. |
authentication_error | missing_api_key, invalid_api_key, missing_tenant. |
authorization_error | missing_scope, test_mode_unavailable. |
idempotency_error | Conflictos de la reserva; consulta idempotencia. |
rate_limit_error | rate_limit_exceeded. |
api_error | database_error, auth_lookup_failed y errores internos. |
Petición o datos no válidos
invalid_param(400): campo desconocido, requerido ausente, tipo o valor incorrectos; incluye propiedades reservadas con prefijo__.invalid_cursor(400): cursor mal formado o no compatible con los parámetros; reinicia la paginación.invalid_version_header/unknown_version(400): formato o versión no admitidos.invalid_idempotency_key(400): debe tener entre 8 y 128 caracteresA-Z a-z 0-9 _ -.profile_limit(403): la creación superaría el límite de perfiles aplicable.resource_not_found(404): el suscriptor no existe en esta marca.resource_already_exists(409): el email ya existe al crear. No presupongas que un conflicto al actualizar utiliza el mismo código.channel_unavailable(409): el canal está suprimido por rebote, queja o bloqueo, o el número WhatsApp pertenece a otro suscriptor.missing_required_field(422): falta email o teléfono según el canal.
Autenticación y permisos
missing_api_key(401): cabecera ausente, vacía o mal formada.invalid_api_key(401): clave desconocida, caducada o revocada.missing_tenant(401): comprobación defensiva si no se puede resolver la marca; comunica el ID de petición.missing_scope(403): falta el permiso de lectura o escritura requerido. Su aplicación está activa.test_mode_unavailable(403): las claves test no pueden acceder a datos reales y no existe un sandbox.
Idempotencia y errores internos
idempotency_key_reuse devuelve 409 si reutilizas una clave para otro cuerpo. Una clave nueva corresponde a una operación nueva, no sirve para forzar la repetición de una escritura incierta.
Ante 5xx, distingue una lectura que puedes repetir de una escritura cuyo resultado debes revisar. Con Idempotency-Key, la reserva incierta dura 24 horas y no se reejecuta automáticamente. Guarda request_id y consulta idempotencia.
Un 503 idempotency_unavailable indica que no se inició la operación; no garantiza una reserva creada. Reintenta la misma operación con la misma clave, sin generar otra para eludir la protección.
Respuestas fuera del formato habitual
Un JSON mal formado o un error de un intermediario puede devolver una respuesta no JSON. Las rutas no publicadas tampoco tienen un contrato v1 garantizado; no las invoques hasta que aparezcan en la referencia.
Ejemplos
400: parámetro no válido
curl -X POST https://fluyio.com/api/v1/subscribers \
-H "Authorization: Bearer $FLUYIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "first_name": "Ada" }'401: clave no válida
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "The provided API key is invalid, revoked, or expired.",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}403: límite de perfiles
{
"error": {
"type": "invalid_request_error",
"code": "profile_limit",
"message": "Límite de perfiles alcanzado (250/250).",
"param": "profile_limit",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}404: ID desconocido
{
"error": {
"type": "invalid_request_error",
"code": "resource_not_found",
"message": "No subscriber found with id sub_00000000000000000000000000000000.",
"param": "id",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}409: email duplicado
{
"error": {
"type": "invalid_request_error",
"code": "resource_already_exists",
"message": "A subscriber with this email already exists in this account.",
"param": "email",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}422: identidad de canal ausente
{
"error": {
"type": "invalid_request_error",
"code": "missing_required_field",
"message": "Cannot subscribe an SMS channel for a subscriber without a phone number.",
"param": "phone",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}429: límite de peticiones
HTTP/1.1 429 Too Many Requests
Retry-After: 4
Ratelimit-Limit: 150
Ratelimit-Remaining: 0
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Burst limit reached (150 req / 10s). Retry after 4 seconds.",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}500: error interno
{
"error": {
"type": "api_error",
"code": "database_error",
"message": "Failed to create subscriber.",
"request_id": "req_3f9a1c7e5b2d8f4a6c0e9b1d3f"
}
}Tratar errores en tu código
class FluyioError extends Error {
constructor(
public status: number,
public type: string,
public code: string,
public requestId: string,
message: string,
) {
super(message);
}
}
async function fluyio(path: string, init: RequestInit = {}) {
const res = await fetch(`https://fluyio.com/api/v1${path}`, {
...init,
headers: {
Authorization: `Bearer ${process.env.FLUYIO_API_KEY}`,
'Fluyio-Version': '2026-05-15',
'Content-Type': 'application/json',
...(init.headers ?? {}),
},
});
if (res.ok) return res.json();
let body: any = null;
try { body = await res.json(); } catch { /* non-JSON 400 or proxy error */ }
const err = body?.error ?? {};
throw new FluyioError(
res.status,
err.type ?? 'api_error',
err.code ?? 'unknown',
err.request_id ?? res.headers.get('fluyio-request-id') ?? '',
err.message ?? res.statusText,
);
}
try {
await fluyio('/subscribers', { method: 'POST', body: JSON.stringify({ email: '[email protected]' }) });
} catch (e) {
if (e instanceof FluyioError) {
if (e.type === 'rate_limit_error') {
// wait for Retry-After and retry
} else if (e.code === 'resource_already_exists') {
// look the subscriber up with filter[email] and PATCH instead
} else {
console.error(e.status, e.type, e.code, e.requestId, e.message);
}
}
throw e;
}Los ejemplos de creación que omiten consentimiento devuelven el email como never_subscribed; no dan de alta al contacto automáticamente.
Compartir un diagnóstico
Al escribir a [email protected], incluye el request_id, la hora aproximada en UTC, la versión y una respuesta depurada de datos privados. No compartas la clave API.
Consulta autenticación, límites, idempotencia y versionado.