Referencia de la API
Todos los endpoints están bajo /organizations/{tenant}/ en el host de la API de wallet (https://{FQDN}). Todas las solicitudes requieren el header X-API-KEY. Todos los POST requieren un header Idempotency-Key.
Billeteras
| Método | Ruta | Descripción |
|---|---|---|
GET | /wallets | Lista las billeteras de tu tenant |
POST | /wallets | Crea una billetera (owner_type, owner_ref, name) |
GET | /wallets/{id} | Obtiene una billetera |
GET | /wallets/{id}/balance | Saldos por activo (?asset=USD opcional) |
GET | /wallets/{id}/entries | Movimientos del libro contable — paginados (50 por página), filtrables por asset, journal_kind y rango de fechas |
Las billeteras creadas a través de la API siempre tienen kind: operational. Los demás tipos de cuenta (subcuentas de retención, suspense, origen externo) son gestionados por el sistema y solo aparecen en los movimientos del libro contable.
Movimiento de Dinero
| Método | Ruta | Descripción |
|---|---|---|
POST | /deposits | Registra un origen externo y lo divide entre billeteras de forma atómica |
POST | /holds | Preautoriza (coloca una retención) |
GET | /holds/{id} | Obtiene una retención junto con su historial de capturas |
POST | /holds/{id}/capture | Captura parte o la totalidad de una retención hacia una cuenta de destino |
POST | /holds/{id}/void | Anula la porción restante (no capturada) de una retención |
POST | /captures/{captureJournalUuid}/refund | Reembolsa contra una captura específica (se permite parcial) |
POST | /transfers | Transferencia del mismo activo entre billeteras |
POST | /fx-conversions | Conversión entre activos con rate y rate_source explícitos |
Tipos de journal: deposit, preauth, capture, void, refund, transfer, fx_conversion.
Estados de retención: open, partially_captured, captured, voided. (expired está reservado; la expiración actualmente no se aplica automáticamente — anula las retenciones expiradas de forma explícita.)
Tipos de origen de depósito: wire, ach_debit, card, stablecoin_deposit.
Montos y Activos
- Todos los montos son strings JSON, decimales con hasta 8 posiciones. Los campos
amountde las respuestas también son strings — nunca los parsees como números JSON (pérdida de precisión). - Activos soportados:
USD,USDC,EUR,MXN. - Los saldos se actualizan atómicamente con la escritura del journal — una respuesta exitosa significa que el saldo refleja la operación.
Manejo de Errores
Todos los errores devuelven un cuerpo JSON:
{
"error": "ERROR_CODE",
"message": "Human-readable explanation."
}
| HTTP | error | Cuándo ocurre |
|---|---|---|
| 400 | MISSING_IDEMPOTENCY_KEY | POST sin header Idempotency-Key |
| 401 | UNAUTHORIZED | X-API-KEY faltante o inválida |
| 403 | FORBIDDEN | La API key no coincide con el {tenant} de la URL |
| 404 | NOT_FOUND | La billetera, retención o captura referenciada no existe (o no está en tu tenant) |
| 409 | INVALID_HOLD_STATE | Capturar una retención anulada, anular una capturada, etc. |
| 422 | VALIDATION_ERROR | El payload falló la validación — el campo errors lista los problemas por campo |
| 422 | INSUFFICIENT_FUNDS | La preautorización o transferencia excede el saldo available de la billetera |
| 422 | INVALID_ASSET | asset_code desconocido o no soportado |
| 422 | INVALID_ACCOUNT | La cuenta referenciada no es válida para la operación |
| 422 | LEDGER_IMBALANCE | Las divisiones no suman el monto del origen, u otra violación de la partida doble |
| 500 | INTERNAL_ERROR | Error del lado del servidor — contacta a soporte con el timestamp y los detalles de la solicitud |
Para VALIDATION_ERROR, la respuesta incluye un desglose por campo:
{
"error": "VALIDATION_ERROR",
"message": "The wallet id field must be a uuid.",
"errors": {
"wallet_id": ["The wallet id field must be a uuid."]
}
}
Idempotencia
Cada endpoint POST requiere un header Idempotency-Key. Si envías dos solicitudes con la misma clave, la segunda devuelve exactamente la respuesta de la primera — no se crea un journal duplicado.
Por qué importa: las fallas de red son silenciosas. Una solicitud que expira después de enviarse pero antes de recibir la respuesta te deja sin saber si la operación tuvo éxito. Reintentar con la misma clave siempre es seguro.
Cómo nombrar las claves: cualquier string único de hasta 191 caracteres. La mejor práctica es un identificador estable y significativo por operación:
deposit-BANK-WIRE-98765432para una transferencia bancaria específicacapture-INV-4521para una factura específicarefund-INV-4521-partial-1para un reembolso específico
Nunca reutilices una clave para operaciones diferentes. Reutilizar
invoice-4521-refundpara un reembolso de $50 y luego para uno de $100 devuelve la respuesta de $50 la segunda vez — el reembolso de $100 nunca ocurre.
Las claves se almacenan por journal, con alcance limitado a tu tenant, y nunca expiran.
Trazabilidad
- Cada respuesta de journal incluye
parentJournalIdcuando revierte o continúa otra operación — sigue la cadena reembolso → captura → preautorización para obtener un rastro de auditoría completo. - Cada movimiento incluye
lineageRef— los IDs de origen (consumidos por FIFO) que financiaron ese movimiento específico. - Los journals de depósito incluyen el UUID del origen creado en
metadata.source_uuidpara referencia cruzada.
Notas de Roadmap
- Los webhooks para cambios de saldo están en el roadmap — mientras tanto, consulta los saldos o los movimientos mediante polling.
- El escrow estilo marketplace (visible para ambas partes) está planeado como una variante separada de las retenciones estilo tarjeta — contacta a Inyo si lo necesitas.
