Four calls: read the route, save who you are paying, save how to reach them, resolve a destination. The last one is what a transfer spends.
1. Find the route
Never guess the fields. Ask which routes serve the destination and what each one needs.
Keep two things from the response: route.id, and the fieldDescriptors that tell you what to collect.
2. Save the recipient
Who you are paying. More is required here than you might expect — relationship, email, and a full address are all mandatory, because payout providers ask for them.
type decides the name fields: individual needs firstName and lastName, business needs legalName.
3. Add routing
The keys inside fields come from the route’s descriptors — not from a list you maintain.
The response masks what you sent:
maskedIdentifier is the only form the account number comes back in, ever. No endpoint returns the value you sent. If your UI needs to show it, store it yourself.
4. Resolve a destination
An empty body uses the recipient’s default detail. The response is what a transfer spends:
Two things to do with it:
- Show
displayName to whoever is approving the payment. On a route that supports verification, this is the name the bank holds — not the name you typed. A mismatch is the cheapest fraud check you will ever run.
- Spend it soon. It expires in 24 hours and can be used once.
Doing it in one call instead
For a one-off, skip the recipient entirely:
Note the four recipient* fields. They are optional to the parser and required by the payout rail on international routes — leave them out and you get 422 recipient_profile_incomplete. Routing fields go at the top level here, not inside fields.
If it failed
Next