Zafirox SDK
SDK 1.1.0 Cuentas Empezar

Errores y reintentos

Catálogo estable de códigos de error, forma del envelope de error, qué se puede reintentar y cómo lo hace el SDK.

Forma de un error

Toda respuesta de error (salvo el token endpoint, que usa el formato RFC 6749) lleva data: null y un elemento en errors:

{
  "data": null,
  "meta": { "api_version": "1", "request_id": "req_…" },
  "errors": [
    {
      "code": "VALIDATION_ERROR",
      "message": "El campo owner_uid no forma parte del contrato v1.",
      "field": "owner_uid",
      "retryable": false
    }
  ]
}
  • Decide siempre por code; el message es diagnóstico y puede cambiar.
  • field señala el campo, cabecera o parámetro rechazado (jewel.stones.0.quantity, Idempotency-Key, cursor).
  • diagnostic_id aparece en fallos técnicos para que Zafirox localice la causa sin exponerla.
  • Guarda meta.request_id (también en la cabecera X-Request-Id) en tus registros: es la referencia para soporte.
CódigoHTTPReintentableCausa
AUTHENTICATION_REQUIRED401noToken ausente, mal formado, con firma inválida o vencido
TOKEN_AUDIENCE_MISMATCH401noToken emitido para otro recurso
CLIENT_CREDENTIALS_INVALID401noCredenciales incorrectas al pedir el token
INVALID_GRANT400nocode o refresh_token inválido, expirado, ya usado, de otro cliente o con code_verifier/redirect_uri distintos (token endpoint, error: invalid_grant)
ACCOUNT_LOGIN_REJECTED401noLa persona no pudo iniciar sesión en «Acceder con Zafirox» (field: INVALID_CREDENTIALS, ACCOUNT_SUSPENDED, ACCOUNT_BLOCKED); sólo lo ve la pantalla de cuentas
GATEWAY_KEY_INVALID403noPaso reservado a la pantalla de cuentas invocado sin su llave; una integración nunca debería recibirlo
SCOPE_REQUIRED403noEl token no tiene el scope de la operación
CLIENT_SCOPE_INVALID403noActor fuera de la empresa, master inactivo o sujeto de escritura fuera del alcance
CLIENT_ORIGIN_NOT_ALLOWED403noOrigin no registrado para el cliente
RESOURCE_NOT_FOUND404noEl recurso no existe o no pertenece al alcance
VALIDATION_ERROR422noPayload, parámetro, cursor o cabecera inválidos
BUSINESS_RULE_VIOLATION422noRegla de negocio de órdenes (fecha no hábil, urgente sin autorización…)
IDEMPOTENCY_CONFLICT409noMisma Idempotency-Key con otro payload
CREATION_IN_PROGRESS409síLa misma creación sigue en curso
ORDER_CREATE_VERSION_RETIRED410noCreación v1 retirada al publicar v2; cambia al contrato v2
order_policy.version409noVersión o SHA-256 de política no reconocido
order_policy.field, order_policy.required422noCampo fuera del perfil o dato requerido ausente
order_policy.weight, order_policy.measurement, order_policy.design422noPeso, medida o referencia de diseño inválidos
order_policy.catalog, order_policy.text, order_policy.delivery422noOpción de catálogo, límite de texto o entrega inválida
RATE_LIMITED429síLímite por cliente superado; respeta Retry-After
CLIENT_API_DISABLED503noLa API está apagada por mantenimiento; no reintentes automáticamente, vuelve a intentarlo más tarde
UPSTREAM_UNAVAILABLE503síDependencia técnica no disponible; lleva diagnostic_id

Qué reintentar

  • Reintenta sólo errores retryable: true, timeouts y fallos de red, y únicamente en operaciones idempotentes: todas las lecturas y POST /api/v2/client/orders **con la misma Idempotency-Key**.
  • Espera Retry-After segundos cuando el servidor lo envía (429, 503); si no, usa una espera creciente.
  • Nunca reintentes 401, 403, 404, 409 IDEMPOTENCY_CONFLICT ni 422: el resultado será el mismo.

Cómo lo hace el SDK

Cada clase de error extiende ZafiroxApiError y conserva code, status, requestId, retryable, field, diagnosticId y retryAfterSeconds:

ClaseHTTP
AuthenticationError401
AuthorizationError403
NotFoundError404
ConflictError409
ValidationError422
RateLimitError429
UpstreamError5xx
TransportErrorred (NETWORK_ERROR), timeout (TIMEOUT) o envelope inválido (INVALID_ENVELOPE)
import { ValidationError, RateLimitError, ZafiroxApiError } from '@zafirox/client-sdk';

try {
  await client.orders.create(entradaV2, { idempotencyKey: 'pedido-77' }); // SDK v2, pendiente de publicación
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Corrige el campo', error.field, error.message);
  } else if (error instanceof RateLimitError) {
    console.warn('Espera', error.retryAfterSeconds, 's');
  } else if (error instanceof ZafiroxApiError) {
    console.error(error.code, error.status, error.requestId);
  } else {
    throw error;
  }
}

Por defecto el SDK hace dos intentos con 250 ms de espera (o el Retry-After del servidor, tope 5 s). Ajusta retry: { maxAttempts, backoffMs, maxRetryAfterMs } en las opciones del cliente; maxAttempts: 1 desactiva los reintentos.