Zafirox SDK
SDK 1.1.0 Cuentas Empezar

Referencia del SDK

API del SDK: lecturas v1 y creación v2 gobernada por la política de pedidos generada.

Paquete @zafirox/client-sdk (ESM, TypeScript). Todo se importa desde index.js. Esta página describe el SDK actualizado en el repositorio; el CDN 1.1.0 actualmente publicado todavía contiene la antigua creación v1. La versión nueva se publicará después del backend v2.

ZafiroxClient

new ZafiroxClient(options: ZafiroxClientOptions)
OpciónTipoPor defectoDetalle
baseUrlstring—Origen de la API, https://datacenterv2.joyeriazafirox.com
tokenProviderTokenProvider—Quien entrega el access token
fetchFetchLikeglobalThis.fetchImplementación de fetch a usar
timeoutMsnumber15000Timeout por petición (AbortController)
apiVersionstring'1'Versión esperada para lecturas v1; orders.create() valida v2 por separado
retry{ maxAttempts?, backoffMs?, maxRetryAfterMs? }2, 250, 5000Política de reintentos
maxResponseBytesnumber1048576Tamaño máximo aceptado de respuesta
onRequestId(id: string) => void—Recibe el X-Request-Id de cada respuesta

Propiedades: orders, account, portfolio, apiVersion.

Proveedores de token

createClientCredentialsProvider({
  tokenUrl, clientId, clientSecret, scope?, fetch?, timeoutMs?, refreshSkewSeconds?,
}): TokenProvider

createStaticTokenProvider(accessToken: string): TokenProvider

createAuthorizationCodeProvider({
  apiUrl, clientId, redirectUri, scope, clientSecret?, storage?, storageKey?,
  fetch?, timeoutMs?, refreshSkewSeconds?, now?, randomBytes?, sha256?,
}): AuthorizationCodeProvider

interface TokenProvider { getAccessToken(): Promise<string>; }

interface AuthorizationCodeProvider extends TokenProvider {
  createAuthorizationUrl(options?: { state?, loginHint?, prompt?: 'select_account' | 'login' }): Promise<string>;
  login(options?): Promise<void>;                       // sólo navegador: redirige
  completeLogin(callbackUrl: string | URL): Promise<AuthorizationCodeSession>;
  isAuthenticated(): boolean;
  session(): AuthorizationCodeSession | null;           // { scope, expiresAt, hasRefreshToken }
  logout(): void;
}

createClientCredentialsProvider es sólo para backends; cachea el token, lo renueva refreshSkewSeconds (30) antes de expirar y mantiene una única renovación en vuelo. Un rechazo del token endpoint lanza AuthenticationError con el error_code del catálogo.

createAuthorizationCodeProvider implementa «Acceder con Zafirox» (Authorization Code + PKCE S256): genera code_verifier y state, los guarda en storage (sessionStorage en el navegador, memoria en Node), redirige a GET /oauth/authorize, canjea el code en completeLogin y renueva con refresh_token (rotación) cuando el access token expira. Errores de completeLogin: access_denied, STATE_MISMATCH, AUTHORIZATION_NOT_PENDING, INVALID_CALLBACK; un refresh rechazado (INVALID_GRANT) borra la sesión local. clientSecret sólo en servidores (cliente confidencial, HTTP Basic). También se exportan generatePkce(), base64UrlEncode() y requestToken() para flujos a medida.

client.orders

orders.create(input: CreateOrderInput, options?: { idempotencyKey?: string }): Promise<OrderCreationResult> // POST /api/v2/client/orders
orders.list(query?: OrderListQuery): Promise<Page<Order>>

CreateOrderInput: initialDate, deliveryDate, jewel, performedBy?, orderSubjectUid?, urgentAuthorizationCode?. JewelInput: campos requeridos customerId, customer, phone, type, material, designRefs; opcionales invoiceName, goldType, goldQuality, style, observations, details, requires3dDesign, nona, individualWeight, nonaGender, measurementSystem, measurements, widths, marking, weight, stones. Los pesos y anchos decimales son cadenas exactas. designRefs contiene de 1 a 5 referencias opacas devueltas por POST /api/v2/client/order-designs; el SDK no ofrece carga de archivos ni edición de órdenes.

orders.create() mapea camelCase a snake_case, aplica el perfil generado external-create-v2, adjunta policy_version y policy_sha256, y compara esa identidad con meta de la respuesta. Si el payload infringe el contrato, lanza OrderPolicyInputError con violations, field, code y ruleId antes de enviar. Una versión de política no conocida por el backend responde 409 order_policy.version. orders.list() sigue en GET /api/v1/client/orders.

// Para la nueva versión del SDK, después de publicar backend v2 y obtener una referencia autorizada:
const receipt = await client.orders.create({
  initialDate: '2026-10-01', deliveryDate: '2026-10-15',
  jewel: {
    customerId: '123456789', customer: 'Cliente Demo', phone: '3000000000',
    type: 'Anillo', material: 'Plata', designRefs: [authorizedDesignRef],
  },
}, { idempotencyKey: 'erp-orden-123' });
console.log(receipt.serial, receipt.policyVersion, receipt.policySha256);

ORDER_POLICY_VERSION, ORDER_POLICY_SHA256, ORDER_POLICY_MANIFEST y los evaluadores generados también se exportan para inspección. Su versión es independiente de la versión HTTP y del dataSchemaVersion histórico de Angular. OrderListQuery: cursor?, limit?, status?, category?, search?, startDate?, endDate?, subjectUid?.

client.account

account.get(): Promise<Account>
account.transactions(query?: TransactionQuery): Promise<Page<AccountTransaction>>

TransactionQuery: cursor?, limit?, type?, from?, to?.

client.portfolio

portfolio.get(query?: PortfolioQuery): Promise<Page<PortfolioItem>>
portfolio.payments(query?: PaymentQuery): Promise<Page<Payment>>

PortfolioQuery: cursor?, limit?, status?, orderSerial?, subjectUid?. PaymentQuery: cursor?, limit?, orderSerial?, from?, to?, subjectUid?.

Tipos de resultado

interface Page<T> { items: readonly T[]; nextCursor: string | null; hasMore: boolean; requestId: string; }

type DecimalString = string;   // "150000.00" histórico o "0.0001" COP operativo
type CivilDate = string;       // "2026-09-20"
type Rfc3339Instant = string;  // "2026-09-15T17:00:00-05:00"

interface Order { serial; subjectUid; status; customer; invoiceName; jewelType; initialDate; deliveryDate; price: DecimalString; currency; performedBy }
interface OrderCreationResult { serial; subjectUid; status; replayed: boolean; initialDate; deliveryDate; requestId; policyVersion; policySha256 }
interface Account { accountId; uid; balance: DecimalString; currency; status; createdAt: Rfc3339Instant | null; updatedAt }
interface AccountTransaction { transactionId; accountId; subaccountId; type; amount; balanceBefore; balanceAfter; description; reference; occurredAt; currency }
interface PortfolioItem { orderSerial; subjectUid; status; customer; description; orderTotal; paidTotal; balance; currency; updatedAt }
interface Payment { paymentId; subjectUid; orderSerials: readonly string[]; amount; currency; paymentType; reference; occurredAt }

Los campos camelCase del SDK corresponden uno a uno a los snake_case del contrato HTTP.

Errores

ZafiroxApiError y sus subclases (AuthenticationError, AuthorizationError, NotFoundError, ConflictError, ValidationError, RateLimitError, UpstreamError, TransportError) con code, status, requestId, retryable, field, diagnosticId, retryAfterSeconds. El rechazo local de creación es OrderPolicyInputError; un rechazo de servidor conserva errors[0].code y field. Ver errores y reintentos.

Transporte de bajo nivel

ApiTransport es público para quien necesite llamar una ruta nueva antes de que el SDK la exponga:

const transport = new ApiTransport({ baseUrl, tokenProvider });
const { data, meta, requestId } = await transport.request({
  method: 'GET', path: '/api/v1/client/account', idempotent: true,
});

Valida el envelope y la api_version, aplica timeout, límite de tamaño y reintentos igual que los módulos de alto nivel.

Utilidades

generateRequestId() devuelve un identificador válido para X-Request-Id (sdk-<uuid>); CLIENT_API_BASE_PATH es '/api/v1/client' y CLIENT_ORDER_CREATE_V2_PATH es '/api/v2/client/orders'.