Inyo

Transacción

El endpoint de Transacción es la culminación del flujo de remesas. Vincula al remitente, el destinatario, la fuente de fondos, la cuenta del destinatario y la cotización para ejecutar un pago transfronterizo.


Creación de una Transacción

Endpoint: POST /organizations/{tenant}/fx/transactions
Autenticación: A nivel de agente (x-api-key + x-agent-id + x-agent-api-key)

Cuerpo de la Solicitud

CampoTipoRequeridoDescripción
senderIdstring (UUID)El ID de participante del remitente (de POST /people)
recipientIdstring (UUID)El ID de participante del destinatario (de POST /people)
fundingAccountIdstring (UUID)La fuente de fondos del remitente (de POST /fundingAccounts)
recipientAccountIdstring (UUID)La cuenta de payout del destinatario (de POST /recipientAccounts/gateway)
quoteIdstring (UUID)La cotización de FX bloqueada (de POST /payout/quotes)
externalIdstringNoSu ID de referencia interno para conciliación. Devuelto en los webhooks como externalTransactionId.
deviceDataobjectCondicionalInteligencia de dispositivo para prevención de fraude (vea abajo)
deviceData.userIpAddressstringCondicionalLa dirección IP del usuario final. Requerido cuando el fingerprinting está habilitado para su tenant (el predeterminado).
deviceData.fingerprintstringCondicionalEl requestId de la librería de fingerprint del dispositivo. Requerido cuando el fingerprinting está habilitado (el predeterminado).
deviceData.visitorstringRecomendadoEl visitorId de la librería de fingerprint del dispositivo
additionalDataobjectNoUbicación legada para fingerprint y visitor (ambos aceptados), más campos específicos por país según el esquema de transacción
sendingReasonstringNoPropósito de la transferencia (p. ej., "Family support", "Payment for services")
senderReceiverRelationshipstringNoRelación entre remitente y destinatario (p. ej., "Family member", "Business partner")
sourceOfFundsstringNoOrigen de los fondos (p. ej., "Salary", "Savings", "Business income")

Fingerprint del Dispositivo

La mayoría de los tenants tienen el fingerprinting de dispositivos habilitado (es el valor predeterminado de la plataforma). Cuando está habilitado, cada transacción debe incluir un fingerprint y la dirección IP del usuario, o la solicitud es rechazada. Integre una librería de fingerprint de dispositivo en su aplicación cliente — Inyo proporciona las claves de API para el servicio de fingerprint durante el onboarding.

Antes de enviar una transacción, invoque la librería de fingerprint del lado del cliente y pase los resultados:

  • deviceData.fingerprint — el requestId de la librería de fingerprint
  • deviceData.visitor — el visitorId de la librería de fingerprint
  • deviceData.userIpAddress — la dirección IP del usuario final

Envíe AMBOS: fingerprint y visitor. La integración de inteligencia de dispositivo del lado del servidor del gateway de pagos solo se ejecuta cuando ambos valores están presentes. Enviar solo uno elimina silenciosamente el bloque de inteligencia de dispositivo de la llamada al gateway, lo que reduce la precisión de la evaluación de fraude y puede contribuir a rechazos.

fingerprint y visitor también se aceptan dentro de additionalData (formato legado). deviceData es la ubicación preferida.

Ejemplo de Solicitud

curl --request POST \
  --url https://{FQDN}/organizations/$TENANT/fx/transactions \
  --header 'Content-Type: application/json' \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY" \
  --data '{
  "externalId": "your-internal-reference-123",
  "senderId": "422a55b2-78c3-4509-8654-16e7375d3e40",
  "recipientId": "4b9dcb4e-2e2a-4e96-b2a9-fcd868b2f4ed",
  "fundingAccountId": "3fe5f23f-65d3-41b6-b34c-33db3c4d8ef9",
  "recipientAccountId": "67203d69-dc48-41d4-b2ac-52682d39b032",
  "quoteId": "30bf05d2-b416-4e71-b8e8-1ef158a2b414",
  "deviceData": {
    "userIpAddress": "200.123.131.112",
    "fingerprint": "1727364523875.mchLfB",
    "visitor": "jkS9xp4FHlqOSfGR"
  },
  "sendingReason": "Family support",
  "senderReceiverRelationship": "Family member",
  "sourceOfFunds": "Salary"
}'

Ejemplo de Respuesta (HTTP 202)

{
  "id": "9035ee18-052b-4176-a940-ccfe599a1829",
  "sender": {
    "id": "ce06773d-6472-4c93-bdf5-8eb68ab01c7f",
    "type": "PERSON",
    "name": "Rob Dalas",
    "phoneNumber": "+1 123 456435"
  },
  "recipient": {
    "id": "156675d5-1d1b-4b4d-997e-5c15ae129b82",
    "type": "PERSON",
    "name": "Bob Danilo",
    "phoneNumber": "+55 71 91234-5678"
  },
  "tenantId": "master",
  "externalId": "your-internal-reference-123",
  "agentId": "41f55211-1eea-4747-9a03-68e99f07ede5",
  "createdAt": "2025-05-29T17:26:27.264312",
  "anchorCurrencyAmount": { "amount": "102.53", "currency": "USD" },
  "complianceStatus": "Pending",
  "payoutStatus": "Pending",
  "paymentStatus": null,
  "quoteId": "af2d55d8-1d40-426a-8d4a-7454ccdcbe8a",
  "fundingAccountId": "61bc14a1-b3a2-40b4-b395-0496e4f554a1",
  "recipientAccountId": "4fbc57a6-f673-44ba-88aa-c6e71eb9181b",
  "exchangeRate": "5.571062480000000",
  "totalAmount": { "amount": "102.53", "currency": "USD" },
  "receivingAmount": { "amount": "571.20", "currency": "BRL" },
  "fee": { "amount": "1.54", "currency": "USD" },
  "conversionAmount": { "amount": "102.53", "currency": "USD" },
  "type": "FX",
  "senderId": "ce06773d-6472-4c93-bdf5-8eb68ab01c7f",
  "recipientId": "156675d5-1d1b-4b4d-997e-5c15ae129b82",
  "sendingReason": "Family support",
  "receipt": { "..." : "regulatory disclosures" }
}

Campos de la Respuesta

CampoDescripción
idID único de la transacción
complianceStatusResultado actual de la evaluación de cumplimiento (vea el ciclo de vida abajo)
payoutStatusEstado actual de la entrega del payout (vea el ciclo de vida abajo)
paymentStatusActionRequired cuando la tarjeta requiere un desafío 3DS, de lo contrario null
redirectAcsUrlURL del desafío 3DS — presente solo cuando paymentStatus es ActionRequired
status.messagesRegistro de auditoría de las transiciones de estado con marcas de tiempo
exchangeRateLa tasa de FX aplicada
totalAmountMonto total cobrado al remitente (en la moneda de origen)
receivingAmountMonto a recibir por el beneficiario (en la moneda de destino)
feeComisión de la transacción en la moneda de origen
conversionAmountMonto que fue convertido (moneda de origen)
receiptDivulgaciones regulatorias que deben mostrarse al remitente (vea abajo)
typeTipo de transacción — FX

Errores de Validación

Los fallos de validación devuelven HTTP 400 con un desglose por campo:

{
  "errors": [
    { "fieldName": "fingerprint", "error": "A fingerprint is required (deviceData.fingerprint or additionalData.fingerprint)." },
    { "fieldName": "deviceData.userIpAddress", "error": "The device IP address is required." }
  ]
}

Manejo de 3D Secure (3DS)

Cuando la tarjeta del remitente requiere autenticación 3DS, la respuesta de creación incluye:

{
  "paymentStatus": "ActionRequired",
  "redirectAcsUrl": "https://..."
}

Flujo:

  1. Abra redirectAcsUrl en un WebView o ventana emergente.
  2. El usuario completa la verificación 3DS en la página del emisor.
  3. Escuche el evento postMessage de la interfaz de pago para determinar si el desafío tuvo éxito.
  4. Si tuvo éxito: cierre el WebView y sondee GET /fx/transactions/{id} — la transacción se reanuda automáticamente (integración de payout, revisión de cumplimiento, etc.). paymentStatus vuelve a null una vez que el desafío se resuelve.
  5. Si falló: cierre el WebView y muestre un error — la transacción pasa a PaymentDeclinedCancelled.

Si la tarjeta no recibe un desafío, la transacción procede de inmediato y redirectAcsUrl está ausente. Mientras el desafío está pendiente, la transacción permanece en el estado WaitingChallenge3ds.

Nunca omita el desafío 3DS. Una transacción atascada en WaitingChallenge3ds no progresará hasta que el desafío se complete o la transacción se cancele.


Ciclo de Vida del Estado de la Transacción

Cada transacción expone dos dimensiones de estado resumidas en GET /fx/transactions/{id}, más un estado interno detallado entregado vía webhooks.

Estado de Cumplimiento

EstadoDescripción
PendingEvaluación aún no completada
ApprovedPasó las comprobaciones de cumplimiento — la transacción puede proceder
RejectedFalló la revisión de cumplimiento — la transacción está bloqueada
CancelledLa transacción fue cancelada antes de completarse
RefundedLa transacción fue reembolsada después de la captura del pago
FailedPago rechazado u ocurrió un error irrecuperable

Estado de Payout

EstadoDescripción
PendingTransacción aceptada, la etapa de pago aún en progreso
ProcessingEntregada a la red de payout (MSB), a la espera de la entrega
CompletedFondos entregados al destinatario
CancelledLa transacción fue cancelada
FailedPayout rechazado por la red, pago rechazado o error
VoidedPayout anulado por la red de payout
RefundedLa transacción fue reembolsada

Flujos de Estado Detallados

Los estados detallados de abajo se entregan en los webhooks TransactionStatusChanged y en el endpoint de historial de estados.

Tarjeta (con 3DS):

Created → PaymentProcessing → WaitingChallenge3ds
  → [user completes 3DS] → PaymentAuthorized
  → ProcessingPayout → PayoutAccepted → ManualReview → ReviewApproved
  → PaymentCaptured → WaitingPayout
  → [payout network confirms delivery] → Paid → Completed

Tarjeta (sin 3DS):

Created → PaymentProcessing → PaymentAuthorized
  → ProcessingPayout → PayoutAccepted → ManualReview → ReviewApproved
  → PaymentCaptured → WaitingPayout
  → [payout network confirms delivery] → Paid → Completed

ACH:

Created → PaymentProcessing → PaymentAuthorized
  → ProcessingPayout → PayoutAccepted → WaitingSettlement
  → [ACH settles] → PaymentSettled → PaymentCaptured → WaitingPayout
  → [payout network confirms delivery] → Paid → Completed

Ramas de excepción:

  • PayoutHold — la red de payout aplicó una retención de cumplimiento; se libera automáticamente o por el equipo de cumplimiento (PayoutHoldPayoutReleased → el flujo se reanuda)
  • PayoutRejected — la red de payout rechazó la transacción; se cancela y el pago se revierte
  • ManualReviewReviewRejected — el equipo de cumplimiento rechazó el pago; se anula
  • BlockedPendingReview — una regla de riesgo o una coincidencia en una lista de bloqueo pausó la transacción para revisión de un operador antes de continuar
  • PendingReversalApproval — el payout fue anulado más adelante en la cadena y la reversión está a la espera de la aprobación de un operador (configurable por tenant)
  • CancelRequested — usted solicitó la cancelación; la reversión está siendo procesada

Dependiendo de la configuración de su tenant, ManualReview puede aprobarse automáticamente (todas las transacciones, solo tarjeta o solo ACH), en cuyo caso verá ManualReviewReviewApproved de forma consecutiva.


Consulta de Transacciones

Obtener Transacción por ID

curl --request GET \
  --url https://{FQDN}/organizations/$TENANT/fx/transactions/$TRANSACTION_ID \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY"

Listar Transacciones

curl --request GET \
  --url "https://{FQDN}/organizations/$TENANT/fx/transactions?page=0&size=20&senderId=$SENDER_ID" \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY"

Parámetros de Consulta:

ParámetroTipoDescripción
pageintegerNúmero de página (indexado desde 0), predeterminado 0
sizeintegerResultados por página, predeterminado 20
senderIdstring (UUID)Filtrar por participante remitente
statusstringFiltrar por estado de cumplimiento (p. ej., APPROVED)

Respuesta: { "total": <count>, "transactions": [ ... ] }, la más reciente primero.

Obtener el Historial de Estados de una Transacción

Devuelve el registro de auditoría completo de los cambios de estado de una transacción, el más reciente primero.

curl --request GET \
  --url https://{FQDN}/organizations/$TENANT/fx/transactions/$TRANSACTION_ID/status \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY"

Ejemplo de Respuesta:

[
  {
    "id": "2f6b3f12-a63f-43f7-9bb4-4e98dfc75fe5",
    "complianceStatus": "Approved",
    "payoutStatus": "Pending",
    "transactionId": "46b4c393-3768-4ba4-b6d2-a6398e17dd78",
    "tenantId": "master",
    "externalId": "GMT000648512199",
    "createdAt": "2024-01-03T12:54:09.455",
    "messages": [
      {
        "id": "0fbbddb8-283d-466d-b2e6-42dcbb3e67de",
        "message": "STANDARD - PAYMENT_RECEIVED",
        "createdBy": "system",
        "createdAt": "2025-11-19T13:29:52.221882",
        "type": "SystemUpdate"
      }
    ]
  }
]

Cancelación / Reversión de una Transacción

Existe un único endpoint de reversión. Inyo determina la operación de reversión correcta según cuánto haya progresado la transacción:

  • Pago solo preautorizado → la autorización se anula (void)
  • Pago ya capturado (pero fondos aún no entregados) → el pago se reembolsa

Endpoint: PUT /organizations/{tenant}/fx/transactions/{transactionId}/status/cancel
Autenticación: A nivel de agente

curl --request PUT \
  --url https://{FQDN}/organizations/$TENANT/fx/transactions/$TRANSACTION_ID/status/cancel \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY"

La reversión se procesa de forma asíncrona: la transacción pasa a CancelRequested, y luego a Cancelled (anulada) o Refunded una vez que el gateway confirma.

Respuestas:

EstadoDescripción
204Reversión aceptada y en cola
404Transacción no encontrada
422La transacción no está en un estado reversible

Una vez que la red de payout ha entregado los fondos al destinatario (Paid / Completed), la transacción ya no puede revertirse a través de la API — contacte al soporte de Inyo.


Actualización de Metadatos de la Transacción

Adjunte datos arbitrarios de clave-valor a una transacción para su seguimiento interno. Devuelve 204.

Endpoint: PUT /organizations/{tenant}/fx/transactions/{transactionId}/metadata
Autenticación: A nivel de agente

curl --request PUT \
  --url https://{FQDN}/organizations/$TENANT/fx/transactions/$TRANSACTION_ID/metadata \
  --header 'Content-Type: application/json' \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY" \
  --data '{
  "internalRef": "INV-2025-001",
  "department": "treasury"
}'

Transacciones en Lote

Para casos de uso de alto volumen puede enviar múltiples transacciones en una sola llamada. Cada elemento usa la misma forma que la solicitud de creación individual.

OperaciónMétodoEndpoint
Enviar lotePOST/organizations/{tenant}/fx/transactions/batch
Reintentar un elemento fallido del lotePOST/organizations/{tenant}/fx/transactions/batch/{transactionId}/retry
{ "transactions": [ { "senderId": "...", "recipientId": "...", "...": "..." } ] }

Ambos endpoints devuelven 202 Accepted; las transacciones individuales progresan de forma independiente — rastréelas vía webhooks o sondeo.


Límites de Transacción

Antes de ejecutar una transacción, verifique que el remitente no haya excedido sus límites. Los números reportados aquí se calculan con las mismas reglas que aplica el validador de transacciones, así que lo que aparece como available es lo que una transacción puede usar realmente.

Endpoint: GET /organizations/{tenant}/fx/participants/{participantId}/limits
Autenticación: A nivel de agente

curl --request GET \
  --url https://{FQDN}/organizations/$TENANT/fx/participants/$SENDER_ID/limits \
  --header "x-api-key: $API_KEY" \
  --header "x-agent-id: $AGENT_ID" \
  --header "x-agent-api-key: $AGENT_KEY"

Ejemplo de Respuesta:

{
  "oneDayLimit": {
    "limit": { "amount": "2999.00", "currency": "USD" },
    "used": { "amount": "0.00", "currency": "USD" },
    "available": { "amount": "2999.00", "currency": "USD" }
  },
  "thirtyDaysLimit": {
    "limit": { "amount": "6000.00", "currency": "USD" },
    "used": { "amount": "2959.99", "currency": "USD" },
    "available": { "amount": "3040.01", "currency": "USD" }
  },
  "oneHundredAndEightyDaysLimit": {
    "limit": { "amount": "9999.00", "currency": "USD" },
    "used": { "amount": "5000.00", "currency": "USD" },
    "available": { "amount": "4999.00", "currency": "USD" }
  }
}

Para ver qué campos se necesitan para alcanzar el siguiente nivel de cumplimiento (y desbloquear límites más altos), use GET /participants/{id}/complianceLevels — vea Límites por Nivel de Confianza.


Recibos (Requisito Regulatorio)

Como agente de un Money Service Business con licencia, usted está legalmente obligado a emitir un recibo al remitente inmediatamente después del envío de la transacción. La respuesta de la transacción incluye un objeto receipt con divulgaciones regulatorias obligatorias que deben mostrarse textualmente al usuario final.

El recibo debe incluir:

  1. Tipo de cambio — la tasa bloqueada de la cotización
  2. Comisiones — comisiones totales cobradas al cliente
  3. Monto total — monto completo pagado por el remitente
  4. Monto a recibir — monto exacto a recibir por el beneficiario
  5. Divulgaciones regulatorias — texto legal dinámico específico del corredor (p. ej., derecho a reembolso, política de cancelación)

No debe alterar los datos financieros ni el texto regulatorio devueltos por la API. Muéstrelos tal cual.


Sandbox: Forzar Transiciones de Estado

En sandbox/staging puede simular eventos externos (callbacks del gateway, notificaciones de payout) para llevar una transacción a través de su ciclo de vida sin movimiento de dinero real. Vea Pruebas en Sandbox.


Respuestas de Error

Estado HTTPCausa
400Campos requeridos faltantes, formato de datos inválido, fingerprint/IP faltante o cotización vencida
403Agente no aprobado, o el remitente no cumple los requisitos de cumplimiento
404La transacción/participante/cuenta referenciada no se encontró en su tenant
422Violación de regla de negocio (p. ej., límite excedido, corredor inválido, estado no reversible)

Todos los Endpoints

OperaciónMétodoEndpoint
Crear transacciónPOST/organizations/{tenant}/fx/transactions
Obtener transacciónGET/organizations/{tenant}/fx/transactions/{transactionId}
Listar transaccionesGET/organizations/{tenant}/fx/transactions
Obtener historial de estadosGET/organizations/{tenant}/fx/transactions/{transactionId}/status
Cancelar / revertir transacciónPUT/organizations/{tenant}/fx/transactions/{transactionId}/status/cancel
Actualizar metadatosPUT/organizations/{tenant}/fx/transactions/{transactionId}/metadata
Enviar lotePOST/organizations/{tenant}/fx/transactions/batch
Reintentar elemento del lotePOST/organizations/{tenant}/fx/transactions/batch/{transactionId}/retry
Consultar límitesGET/organizations/{tenant}/fx/participants/{participantId}/limits
Obtener campos requeridos/opcionalesGET/organizations/{tenant}/fx/transactions/schema?countryCode={iso2}
Forzar cambio de estado (sandbox)POST/organizations/{tenant}/fx/transactions/{transactionId}/events

Documentación Interactiva de la API