Inyo

Push Transaction

Push (payout) transactions transfer funds to a recipient β€” to a bank account, wallet, PIX key, UPI address, or card.

Endpoint

POST https://{FQDN}/v2/payment

Headers:

HeaderValue
AuthorizationBearer {accessToken}
Content-Typeapplication/json

The country schema is the contract

Every payout country has its own draft-07 JSON Schema. It decides which paymentMethod fields exist, which are required, the pattern each must match, the allowed walletOperator values, whether recipient.documents is mandatory, and which currency recipientAmount may carry. These rules differ per corridor and change as corridors are added β€” a recipient hardcoded for one country will be rejected by the next.

Fetch the schema for the destination country and build the request from it:

GET https://{FQDN}/schema/{countryCode}

countryCode is ISO 3166-1 alpha-3 (BRA, IND, PHL). The response covers recipient, recipientAmount, and additionalData β€” and, on the corridors that constrain it, sender. See Schemas for the full endpoint reference.

sender is present in some country schemas and not others. Where it appears it tightens the sender-side rules beyond the generic push schema; where it is absent, only the generic rules apply. This is being filled in β€” treat a missing sender block as "not yet constrained here", not as "never constrained". Reading the block at request time rather than caching a copy is what keeps you ahead of it.

This is the schema the gateway validates POST /v2/payment against, so it is the only one that answers "will this payload be accepted?" for a push.

flowchart TD
  A[Choose destination country] --> B["GET /schema/{countryCode}"]
  B --> C{"paymentMethod.type<br/>offered by the corridor"}
  C -->|BANK_DEPOSIT| D["accountNumber + the<br/>fields the schema requires"]
  C -->|WALLET| E["walletId + walletType<br/>+ walletOperator"]
  C -->|PIX| F["key + keyType"]
  C -->|CARD| G["cardTokenId"]
  D --> H["Add recipient.documents and<br/>additionalData.paymentPurpose<br/>if the schema requires them"]
  E --> H
  F --> H
  G --> H
  H --> I["POST /v2/foreign-exchange<br/>for a quoted fxId"]
  I --> J["POST /v2/payment"]

Request Structure

Root Object

FieldTypeRequiredDescription
externalPaymentIdstringYesYour unique payment identifier (idempotency key)
ipAddressstringYesOriginator's IPv4 or IPv6 address
paymentTypestringYes"PUSH"
amountobjectYesSource amount (what you're sending)
recipientAmountobjectYesDestination amount (what the recipient receives)
senderobjectYesSender details and address
recipientobjectYesRecipient details, address, and payout method
fxIdstringYesFX quote identifier from the Foreign Exchange endpoint
dynamicDescriptorstringNoText to surface on the recipient's statement
additionalDataobjectNoCorridor extras β€” see additionalData

Quote an FX rate and pass its fxId on every push. It is what binds the payment to the rate you were quoted; without it the gateway prices the conversion itself and the recipient may receive a different amount than the one you showed your user. The same applies to PULLPUSH.

There is no capture field on a push. Capture and pre-authorization are pull-side concepts; a push has no authorization to hold.

amount / recipientAmount

FieldTypeRequiredDescription
totalnumberYesAmount, minimum 0
currencystringYesISO 4217 code

amount is the source side, recipientAmount the destination. The destination currency is fixed per country β€” each country schema pins recipientAmount.currency to an enum, so BRA accepts only BRL and DEU only EUR. The one exception is Guinea (GIN), which accepts GNF or XOF.

sender Object

FieldTypeRequiredDescription
firstNamestringYesSender's first name
lastNamestringYesSender's last name
addressobjectYesSender's address
birthDatestringVariesYYYY-MM-DD. Required by KOR
birthCountryCodestringVariesISO alpha-3. Required by KOR

sender.address Object

FieldTypeRequiredDescription
countryCodestringVariesISO alpha-3 country code (e.g., "USA")
citystringVariesCity name
line1stringVariesStreet address line 1
stateCodestringNoState abbreviation (e.g., "MA")
line2stringNoStreet address line 2
zipCodestringNoPostal/ZIP code

The generic push schema requires the address object but marks none of its fields required. A number of destination countries override that and require countryCode, city, and line1:

BGD, CHL, CHN, CIV, GIN, IDN, KEN, LKA, MDG, MLI, MYS, NGA, PAK, PHL, SGP, TUR

South Korea (KOR) is the exception in shape: it adds sender.birthDate and sender.birthCountryCode β€” both pattern-validated β€” instead of tightening the address. China (CHN) accepts an optional sender.birthDate on top of the address rule.

Populating countryCode, city, and line1 on every push is the safer default. They cost nothing on the corridors that don't demand them, and they are what the list above will keep growing into.

recipient Object

FieldTypeRequiredDescription
firstNamestringYesRecipient's first name
lastNamestringYesRecipient's last name
paymentMethodobjectYesPayout method and details
addressobjectVariesRequired by many corridors β€” see Country coverage
documentsarrayVariesIdentity documents β€” required by BRA, CHL, COL, TUR, and by KEN on BANK_DEPOSIT
emailstringVariesRequired by COL
phoneNumberstringVariesRequired by KOR, MNG
birthDatestringVariesRequired by KOR
birthCountryCodestringVariesRequired by KOR

The country schema is authoritative on every "Varies" row above.

recipient.documents Array

Each entry:

FieldTypeRequiredDescription
documentstringYesThe document number
typestringYesDocument type β€” the schema's enum is country-specific
countryCodestringNoCountry that issued the document

The field is named document, not value. Accepted types by country:

Countrytype valuesRequired?
Brazil (BRA)CPF β€” 11 digits, or formatted 123.456.789-09Yes
Colombia (COL)CCYes
Turkey (TUR)ID, PASSPORT, DRIVER_LICENSEYes
Chile (CHL)RUTYes
Kenya (KEN)ID, PASSPORTOn BANK_DEPOSIT

additionalData

FieldTypeDescription
paymentPurposestringRegulatory purpose-of-payment code. Required by a number of corridors, and the accepted codes are a country-specific enum β€” some run to a handful, others to well over a hundred
statementNarrativestringFree text describing the transaction

paymentPurpose is always required for CAN, CHN, COL, EGY, GMB, IDN, IND, KOR, MYS, NPL, PAK, SGP, THA, VNM, and required on BANK_DEPOSIT for BGD and PHL. Read the accepted codes out of the country schema β€” they are not a shared list, and a code valid in Thailand is not valid in Malaysia.

Several corridors require the additionalData object to be present even when it carries nothing. BRA, MAR, and MEX are the clearest case: the schema demands the key but requires no property inside it, so a payload without "additionalData": {} is rejected with VE_001 β€” additionalData can't be empty while an empty object passes. Country coverage marks these.

Foreign Exchange

For cross-currency push payments, fetch a rate before submitting and pass the returned fxId β€” the gateway then applies the rate bound to that quote.

Rates differ by payment method, so quote for the method you are about to pay out on. See Foreign Exchange for the full request/response schemas.

Quick example:

curl -X POST https://{FQDN}/v2/foreign-exchange \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...' \
  -H 'Content-Type: application/json' \
  -d '{
    "sourceCurrencyCode": "USD",
    "destinationCurrencyCode": "BRL",
    "paymentMethod": "BANK_ACCOUNT"
  }'
{
  "fxId": "b2c3d4e5-...",
  "conversionRate": 4.975,
  "sourceCurrencyCode": "USD",
  "destinationCurrencyCode": "BRL",
  "paymentMethod": "BANK_ACCOUNT",
  "quoteIdExpiryDateTime": "2025-03-31T15:30:00Z"
}

Note: FX quotes have a limited validity period. Check quoteIdExpiryDateTime and refresh if expired.

Response

A push is accepted asynchronously. A 200 with status: "PENDING" means the gateway took the payment, not that the recipient was paid:

{
  "paymentId": "bda24392-cac5-4fcf-af80-4a29df3ba0ff",
  "parentPaymentId": "bda24392-cac5-4fcf-af80-4a29df3ba0ff",
  "externalPaymentId": "push-bgd-001",
  "amount": 20.0,
  "created": "2026-07-15 21:29:50",
  "status": "PENDING",
  "approved": false,
  "captured": false,
  "voided": false,
  "responseCode": "01",
  "automaticReversed": false
}

Poll GET /v2/payment/{externalId} or wait for the webhook for the settled outcome. Do not treat approved: false on a PENDING push as a decline β€” it reflects that no authorization has been approved yet, which is the normal state of a push in flight.

What's Next

  • Payout methods β€” Field reference for BANK_DEPOSIT, WALLET, PIX, and CARD
  • Country coverage β€” Every corridor and what each requires
  • Examples β€” Complete request bodies, grouped by region
  • Errors β€” PAY_001 and PAY_271