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
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
senderId | string (UUID) | Sim | O ID de participante do remetente (de POST /people) |
recipientId | string (UUID) | Sim | O ID de participante do destinatário (de POST /people) |
fundingAccountId | string (UUID) | Sim | A fonte de recursos do remetente (de POST /fundingAccounts) |
recipientAccountId | string (UUID) | Sim | A conta de payout do destinatário (de POST /recipientAccounts/gateway) |
quoteId | string (UUID) | Sim | A cotação de FX travada (de POST /payout/quotes) |
externalId | string | Não | Seu ID de referência interno para reconciliação. Retornado nos webhooks como externalTransactionId. |
deviceData | object | Condicional | Inteligência de dispositivo para prevenção de fraude (veja abaixo) |
deviceData.userIpAddress | string | Condicional | O endereço IP do usuário final. Obrigatório quando o fingerprinting está habilitado para o seu tenant (o padrão). |
deviceData.fingerprint | string | Condicional | O requestId da biblioteca de fingerprint de dispositivo. Obrigatório quando o fingerprinting está habilitado (o padrão). |
deviceData.visitor | string | Recomendado | O visitorId da biblioteca de fingerprint de dispositivo |
additionalData | object | Não | Localização legada para fingerprint e visitor (ambos aceitos), além de campos específicos por país conforme o schema de transação |
sendingReason | string | Não | Finalidade da transferência (ex.: "Family support", "Payment for services") |
senderReceiverRelationship | string | Não | Relação entre remetente e destinatário (ex.: "Family member", "Business partner") |
sourceOfFunds | string | Não | Origem 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— orequestIdda biblioteca de fingerprintdeviceData.visitor— ovisitorIdda biblioteca de fingerprintdeviceData.userIpAddress— o endereço IP do usuário final
Envie AMBOS
fingerprintevisitor. 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.
fingerprintevisitortambém são aceitos dentro deadditionalData(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
| Campo | Descrição |
|---|---|
id | ID único da transação |
complianceStatus | Resultado atual da triagem de conformidade (veja o ciclo de vida abaixo) |
payoutStatus | Status atual da entrega do payout (veja o ciclo de vida abaixo) |
paymentStatus | ActionRequired quando o cartão exige um desafio 3DS; caso contrário, null |
redirectAcsUrl | URL do desafio 3DS — presente apenas quando paymentStatus é ActionRequired |
status.messages | Trilha de auditoria das transições de status com timestamps |
exchangeRate | A taxa de FX aplicada |
totalAmount | Valor total cobrado do remetente (na moeda de origem) |
receivingAmount | Valor a ser recebido pelo beneficiário (na moeda de destino) |
fee | Tarifa da transação na moeda de origem |
conversionAmount | Valor que foi convertido (moeda de origem) |
receipt | Divulgações regulatórias que devem ser exibidas ao remetente (veja abaixo) |
type | Tipo 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:
- Abra o
redirectAcsUrlem uma WebView ou popup. - O usuário completa a verificação 3DS na página do emissor.
- Escute o evento
postMessageda interface de pagamento para determinar se o desafio teve sucesso. - 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.).paymentStatusvolta anullassim que o desafio é resolvido. - Se falhou: feche a WebView e mostre um erro — a transação passa para
PaymentDeclined→Cancelled.
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
WaitingChallenge3dsnã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
| Status | Descrição |
|---|---|
Pending | Triagem ainda não concluída |
Approved | Passou nas verificações de conformidade — a transação pode prosseguir |
Rejected | Reprovada na revisão de conformidade — a transação está bloqueada |
Cancelled | A transação foi cancelada antes da conclusão |
Refunded | A transação foi reembolsada após a captura do pagamento |
Failed | Pagamento recusado ou ocorreu um erro irrecuperável |
Status de Payout
| Status | Descrição |
|---|---|
Pending | Transação aceita, etapa de pagamento ainda em andamento |
Processing | Entregue à rede de payout (MSB), aguardando entrega |
Completed | Fundos entregues ao destinatário |
Cancelled | A transação foi cancelada |
Failed | Payout rejeitado pela rede, pagamento recusado ou erro |
Voided | Payout cancelado (void) pela rede de payout |
Refunded | A 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 (PayoutHold→PayoutReleased→ o fluxo é retomado)PayoutRejected— a rede de payout rejeitou a transação; ela é cancelada e o pagamento é revertidoManualReview→ReviewRejected— 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 prosseguirPendingReversalApproval— 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,
ManualReviewpode ser aprovado automaticamente (todas as transações, apenas cartão ou apenas ACH), caso em que você veráManualReview→ReviewApprovedem 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âmetro | Tipo | Descrição |
|---|---|---|
page | integer | Número da página (indexado a partir de 0), padrão 0 |
size | integer | Resultados por página, padrão 20 |
senderId | string (UUID) | Filtrar por participante remetente |
status | string | Filtrar 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:
| Status | Descrição |
|---|---|
204 | Reversão aceita e enfileirada |
404 | Transação não encontrada |
422 | A 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ção | Método | Endpoint |
|---|---|---|
| Enviar lote | POST | /organizations/{tenant}/fx/transactions/batch |
| Repetir um item de lote com falha | POST | /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:
- Taxa de câmbio — a taxa travada da cotação
- Tarifas — total de tarifas cobradas do cliente
- Valor total — valor integral pago pelo remetente
- Valor a receber — valor exato a ser recebido pelo beneficiário
- 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 HTTP | Causa |
|---|---|
400 | Campos obrigatórios ausentes, formato de dados inválido, fingerprint/IP ausente ou cotação expirada |
403 | Agente não aprovado, ou remetente não atende aos requisitos de conformidade |
404 | Transação/participante/conta referenciada não encontrada no seu tenant |
422 | Violação de regra de negócio (ex.: limite excedido, corredor inválido, estado não reversível) |
Todos os Endpoints
| Operação | Método | Endpoint |
|---|---|---|
| Criar transação | POST | /organizations/{tenant}/fx/transactions |
| Obter transação | GET | /organizations/{tenant}/fx/transactions/{transactionId} |
| Listar transações | GET | /organizations/{tenant}/fx/transactions |
| Obter histórico de status | GET | /organizations/{tenant}/fx/transactions/{transactionId}/status |
| Cancelar / reverter transação | PUT | /organizations/{tenant}/fx/transactions/{transactionId}/status/cancel |
| Atualizar metadados | PUT | /organizations/{tenant}/fx/transactions/{transactionId}/metadata |
| Enviar lote | POST | /organizations/{tenant}/fx/transactions/batch |
| Repetir item do lote | POST | /organizations/{tenant}/fx/transactions/batch/{transactionId}/retry |
| Verificar limites | GET | /organizations/{tenant}/fx/participants/{participantId}/limits |
| Obter campos obrigatórios/opcionais | GET | /organizations/{tenant}/fx/transactions/schema?countryCode={iso2} |
| Forçar mudança de status (sandbox) | POST | /organizations/{tenant}/fx/transactions/{transactionId}/events |
