Inyo

Transação

O endpoint de Transação é o ápice do fluxo de remessa. Ele conecta o remetente, o destinatário, a fonte de recursos, a conta do destinatário e a cotação para executar um pagamento internacional.


Criando uma Transação

Endpoint: POST /organizations/{tenant}/fx/transactions
Autenticação: Nível de agente (x-api-key + x-agent-id + x-agent-api-key)

Corpo da Requisição

CampoTipoObrigatórioDescrição
senderIdstring (UUID)SimO ID de participante do remetente (de POST /people)
recipientIdstring (UUID)SimO ID de participante do destinatário (de POST /people)
fundingAccountIdstring (UUID)SimA fonte de recursos do remetente (de POST /fundingAccounts)
recipientAccountIdstring (UUID)SimA conta de payout do destinatário (de POST /recipientAccounts/gateway)
quoteIdstring (UUID)SimA cotação de FX travada (de POST /payout/quotes)
externalIdstringNãoSeu ID de referência interno para reconciliação. Retornado nos webhooks como externalTransactionId.
deviceDataobjectCondicionalInteligência de dispositivo para prevenção de fraude (veja abaixo)
deviceData.userIpAddressstringCondicionalO endereço IP do usuário final. Obrigatório quando o fingerprinting está habilitado para o seu tenant (o padrão).
deviceData.fingerprintstringCondicionalO requestId da biblioteca de fingerprint de dispositivo. Obrigatório quando o fingerprinting está habilitado (o padrão).
deviceData.visitorstringRecomendadoO visitorId da biblioteca de fingerprint de dispositivo
additionalDataobjectNãoLocalização legada para fingerprint e visitor (ambos aceitos), além de campos específicos por país conforme o schema de transação
sendingReasonstringNãoFinalidade da transferência (ex.: "Family support", "Payment for services")
senderReceiverRelationshipstringNãoRelação entre remetente e destinatário (ex.: "Family member", "Business partner")
sourceOfFundsstringNãoOrigem dos recursos (ex.: "Salary", "Savings", "Business income")

Fingerprint do Dispositivo

A maioria dos tenants tem o fingerprinting de dispositivo habilitado (é o padrão da plataforma). Quando habilitado, toda transação deve incluir um fingerprint e o endereço IP do usuário, ou a requisição é rejeitada. Integre uma biblioteca de fingerprint de dispositivo à sua aplicação cliente — a Inyo fornece as chaves de API do serviço de fingerprint durante o onboarding.

Antes de enviar uma transação, chame a biblioteca de fingerprint no lado do cliente e passe os resultados:

  • deviceData.fingerprint — o requestId da biblioteca de fingerprint
  • deviceData.visitor — o visitorId da biblioteca de fingerprint
  • deviceData.userIpAddress — o endereço IP do usuário final

Envie AMBOS fingerprint e visitor. A integração de inteligência de dispositivo server-side do gateway de pagamentos só é executada quando ambos os valores estão presentes. Enviar apenas um descarta silenciosamente o bloco de inteligência de dispositivo da chamada ao gateway, o que reduz a precisão da pontuação de fraude e pode contribuir para recusas.

fingerprint e visitor também são aceitos dentro de additionalData (formato legado). deviceData é a localização preferida.

Exemplo de Requisição

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"
}'

Exemplo de Resposta (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 da Resposta

CampoDescrição
idID único da transação
complianceStatusResultado atual da triagem de conformidade (veja o ciclo de vida abaixo)
payoutStatusStatus atual da entrega do payout (veja o ciclo de vida abaixo)
paymentStatusActionRequired quando o cartão exige um desafio 3DS; caso contrário, null
redirectAcsUrlURL do desafio 3DS — presente apenas quando paymentStatus é ActionRequired
status.messagesTrilha de auditoria das transições de status com timestamps
exchangeRateA taxa de FX aplicada
totalAmountValor total cobrado do remetente (na moeda de origem)
receivingAmountValor a ser recebido pelo beneficiário (na moeda de destino)
feeTarifa da transação na moeda de origem
conversionAmountValor que foi convertido (moeda de origem)
receiptDivulgações regulatórias que devem ser exibidas ao remetente (veja abaixo)
typeTipo da transação — FX

Erros de Validação

Falhas de validação retornam HTTP 400 com um detalhamento 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." }
  ]
}

Tratando o 3D Secure (3DS)

Quando o cartão do remetente exige autenticação 3DS, a resposta de criação inclui:

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

Fluxo:

  1. Abra o redirectAcsUrl em uma WebView ou popup.
  2. O usuário completa a verificação 3DS na página do emissor.
  3. Escute o evento postMessage da interface de pagamento para determinar se o desafio teve sucesso.
  4. Se teve sucesso: feche a WebView e faça polling em GET /fx/transactions/{id} — a transação retoma automaticamente (integração de payout, revisão de conformidade, etc.). paymentStatus volta a null assim que o desafio é resolvido.
  5. Se falhou: feche a WebView e mostre um erro — a transação passa para PaymentDeclinedCancelled.

Se o cartão não for desafiado, a transação prossegue imediatamente e redirectAcsUrl fica ausente. Enquanto o desafio está pendente, a transação permanece no estado WaitingChallenge3ds.

Nunca pule o desafio 3DS. Uma transação presa em WaitingChallenge3ds não progredirá até que o desafio seja concluído ou a transação seja cancelada.


Ciclo de Vida do Status da Transação

Toda transação expõe duas dimensões de status resumidas em GET /fx/transactions/{id}, além de um status interno de granularidade fina entregue via webhooks.

Status de Conformidade

StatusDescrição
PendingTriagem ainda não concluída
ApprovedPassou nas verificações de conformidade — a transação pode prosseguir
RejectedReprovada na revisão de conformidade — a transação está bloqueada
CancelledA transação foi cancelada antes da conclusão
RefundedA transação foi reembolsada após a captura do pagamento
FailedPagamento recusado ou ocorreu um erro irrecuperável

Status de Payout

StatusDescrição
PendingTransação aceita, etapa de pagamento ainda em andamento
ProcessingEntregue à rede de payout (MSB), aguardando entrega
CompletedFundos entregues ao destinatário
CancelledA transação foi cancelada
FailedPayout rejeitado pela rede, pagamento recusado ou erro
VoidedPayout cancelado (void) pela rede de payout
RefundedA transação foi reembolsada

Fluxos de Status Detalhados

Os status de granularidade fina abaixo são entregues em webhooks TransactionStatusChanged e no endpoint de histórico de status.

Cartão (com 3DS):

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

Cartão (sem 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

Ramificações de exceção:

  • PayoutHold — a rede de payout aplicou uma retenção (hold) de conformidade; liberada automaticamente ou pela equipe de conformidade (PayoutHoldPayoutReleased → o fluxo é retomado)
  • PayoutRejected — a rede de payout rejeitou a transação; ela é cancelada e o pagamento é revertido
  • ManualReviewReviewRejected — a equipe de conformidade rejeitou o pagamento; ele é cancelado (void)
  • BlockedPendingReview — uma regra de risco ou correspondência em blocklist pausou a transação para revisão do operador antes de prosseguir
  • PendingReversalApproval — o payout foi cancelado (void) a jusante e a reversão aguarda aprovação do operador (configurável por tenant)
  • CancelRequested — você solicitou o cancelamento; a reversão está sendo processada

Dependendo da configuração do seu tenant, ManualReview pode ser aprovado automaticamente (todas as transações, apenas cartão ou apenas ACH), caso em que você verá ManualReviewReviewApproved em sequência imediata.


Consultando Transações

Obter Transação 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 Transações

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 Query:

ParâmetroTipoDescrição
pageintegerNúmero da página (indexado a partir de 0), padrão 0
sizeintegerResultados por página, padrão 20
senderIdstring (UUID)Filtrar por participante remetente
statusstringFiltrar por status de conformidade (ex.: APPROVED)

Resposta: { "total": <count>, "transactions": [ ... ] }, mais recentes primeiro.

Obter Histórico de Status da Transação

Retorna a trilha de auditoria completa das mudanças de status de uma transação, mais recentes primeiro.

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"

Exemplo de Resposta:

[
  {
    "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"
      }
    ]
  }
]

Cancelando / Revertendo uma Transação

Há um único endpoint de reversão. A Inyo determina a operação de reversão correta com base em quão longe a transação avançou:

  • Pagamento apenas pré-autorizado → a autorização é cancelada (void)
  • Pagamento já capturado (mas fundos ainda não entregues) → o pagamento é reembolsado

Endpoint: PUT /organizations/{tenant}/fx/transactions/{transactionId}/status/cancel
Autenticação: Nível 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"

A reversão é processada de forma assíncrona: a transação passa para CancelRequested, e então para Cancelled (void) ou Refunded assim que o gateway confirma.

Respostas:

StatusDescrição
204Reversão aceita e enfileirada
404Transação não encontrada
422A transação não está em um estado reversível

Uma vez que a rede de payout tenha entregue os fundos ao destinatário (Paid / Completed), a transação não pode mais ser revertida pela API — entre em contato com o suporte da Inyo.


Atualizando os Metadados da Transação

Anexe dados arbitrários de chave-valor a uma transação para seu rastreamento interno. Retorna 204.

Endpoint: PUT /organizations/{tenant}/fx/transactions/{transactionId}/metadata
Autenticação: Nível 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"
}'

Transações em Lote

Para casos de uso de alto volume, você pode enviar múltiplas transações em uma única chamada. Cada item usa o mesmo formato da requisição de criação individual.

OperaçãoMétodoEndpoint
Enviar lotePOST/organizations/{tenant}/fx/transactions/batch
Repetir um item de lote com falhaPOST/organizations/{tenant}/fx/transactions/batch/{transactionId}/retry
{ "transactions": [ { "senderId": "...", "recipientId": "...", "...": "..." } ] }

Ambos os endpoints retornam 202 Accepted; as transações individuais progridem de forma independente — acompanhe-as via webhooks ou polling.


Limites de Transação

Antes de executar uma transação, verifique se o remetente não excedeu seus limites. Os números reportados aqui são calculados com as mesmas regras que o validador de transações aplica, então o que aparece como available é o que uma transação pode de fato usar.

Endpoint: GET /organizations/{tenant}/fx/participants/{participantId}/limits
Autenticação: Nível 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"

Exemplo de Resposta:

{
  "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 quais campos são necessários para alcançar o próximo nível de conformidade (e desbloquear limites maiores), use GET /participants/{id}/complianceLevels — veja Limites por Nível de Confiança.


Recibos (Exigência Regulatória)

Como agente de uma Money Service Business licenciada, você é legalmente obrigado a emitir um recibo ao remetente imediatamente após o envio da transação. A resposta da transação inclui um objeto receipt com divulgações regulatórias obrigatórias que devem ser exibidas literalmente ao usuário final.

O recibo deve incluir:

  1. Taxa de câmbio — a taxa travada da cotação
  2. Tarifas — total de tarifas cobradas do cliente
  3. Valor total — valor integral pago pelo remetente
  4. Valor a receber — valor exato a ser recebido pelo beneficiário
  5. Divulgações regulatórias — texto legal dinâmico específico do corredor (ex.: direito a reembolso, política de cancelamento)

Você não deve alterar os dados financeiros nem o texto regulatório retornados pela API. Exiba-os como estão.


Sandbox: Forçando Transições de Status

No sandbox/staging você pode simular eventos externos (callbacks do gateway, notificações de payout) para conduzir uma transação por seu ciclo de vida sem movimentação real de dinheiro. Veja Testes no Sandbox.


Respostas de Erro

Status HTTPCausa
400Campos obrigatórios ausentes, formato de dados inválido, fingerprint/IP ausente ou cotação expirada
403Agente não aprovado, ou remetente não atende aos requisitos de conformidade
404Transação/participante/conta referenciada não encontrada no seu tenant
422Violação de regra de negócio (ex.: limite excedido, corredor inválido, estado não reversível)

Todos os Endpoints

OperaçãoMétodoEndpoint
Criar transaçãoPOST/organizations/{tenant}/fx/transactions
Obter transaçãoGET/organizations/{tenant}/fx/transactions/{transactionId}
Listar transaçõesGET/organizations/{tenant}/fx/transactions
Obter histórico de statusGET/organizations/{tenant}/fx/transactions/{transactionId}/status
Cancelar / reverter transaçãoPUT/organizations/{tenant}/fx/transactions/{transactionId}/status/cancel
Atualizar metadadosPUT/organizations/{tenant}/fx/transactions/{transactionId}/metadata
Enviar lotePOST/organizations/{tenant}/fx/transactions/batch
Repetir item do lotePOST/organizations/{tenant}/fx/transactions/batch/{transactionId}/retry
Verificar limitesGET/organizations/{tenant}/fx/participants/{participantId}/limits
Obter campos obrigatórios/opcionaisGET/organizations/{tenant}/fx/transactions/schema?countryCode={iso2}
Forçar mudança de status (sandbox)POST/organizations/{tenant}/fx/transactions/{transactionId}/events

Documentação Interativa da API