Global payouts integration guide

This guide walks through the primary flows for integrating with Latitude’s global payouts product. You’ll learn how to create recipients (individuals with the global_payouts product type), optionally lock exchange rates with quotes, and execute transfers.

Before you start, make sure you’re familiar with the API basics — authentication, idempotency, webhooks, and prefunding.

Summary

The high-level steps are as follows:

  1. Prerequisites
    • Prefund your Latitude account with USD or USDC
    • (Optional) Create a webhook subscription for transfer events
  2. Create a recipient with financial account details via POST /v1/individuals with the global_payouts product type
  3. (Optional) Create a quote to lock an exchange rate for 2 minutes
  4. Create a transfer — either referencing a quote or with transfer parameters directly
  5. Determine the outcome via webhooks or polling

Detailed Steps

Step 0: Prerequisites

a) Prefund your Latitude account

See API basics — Prefunded flows for funding options.

b) (Optional) Create a webhook subscription

Create a webhook subscription to be notified of transfer events. See API basics — Webhooks for details. The relevant event types for this flow are:

  • transfer.completed — sent when a transfer completes successfully
  • transfer.failed — sent when a transfer terminally fails

Step 1: Create a Recipient (Individual) with Financial Accounts

Create a recipient profile with financial account information. The required fields vary by country — see Country-specific details for the full reference.

Request:

POST /v1/individuals HTTP/1.1
Content-Type: application/json
{
"product_types": ["global_payouts"],
"given_name": "Rahul",
"family_name": "Patel",
"country": "IN",
"email": "[email protected]",
"phone": "+919876543210",
"address": {
"line_1": "Flat 304, Building B, Sunshine Apartments",
"city": "Bengaluru",
"state": "Karnataka",
"postal_code": "560001"
},
"financial_accounts": [
{
"type": "upi",
"details": {
"upi_id": "9876543210@paytm"
}
}
]
}

Response:

HTTP/1.1 201 Created
Content-Type: application/json
{
"id": "ind_01h3x5n6z7y8w9v0u1t2s3r4",
"given_name": "Rahul",
"family_name": "Patel",
"email": "[email protected]",
"phone": "+919876543210",
"country": "IN",
"product_types": ["global_payouts"],
"address": {
"line_1": "Flat 304, Building B, Sunshine Apartments",
"city": "Bengaluru",
"state": "Karnataka",
"postal_code": "560001",
"country": "IN"
},
"status": "pending",
"financial_accounts": [
{
"id": "fa_01h3x5n6z7y8w9v0u1t2s3r4",
"type": "upi",
"details": {
"upi_id": "9876543210@paytm"
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
],
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}

Fields with no value are omitted from the response rather than returned as null — in this example there is no line_2, no document, and no status_details, so none of those keys appear. Quotes and transfers still refer to this recipient using recipient_id in their responses, carrying the same ind_ identifier.

Step 2: (Optional) Create a Quote

Create a quote to lock the conversion rate and fees for 2 minutes. You must specify exactly one of the following amount fields:

FieldMeaning
source_amountGross amount of the source currency to send (fees deducted from this amount)
destination_amountDesired amount of the destination currency to receive
net_source_amountNet source amount after fees (fees added on top)

Request:

POST /v1/quotes HTTP/1.1
Content-Type: application/json
{
"financial_account": { "id": "fa_01h3x5n6z7y8w9v0u1t2s3r4" },
"payout_method": "upi",
"source_amount": "100.00",
"source_currency": "usd",
"destination_currency": "inr"
}

Response:

HTTP/1.1 201 Created
Content-Type: application/json
{
"id": "qu_01h3x5n6z7y8w9v0u1t2s3r4",
"source_amount": "100.00",
"source_currency": "usd",
"destination_amount": "8356.42",
"destination_currency": "inr",
"derived_source_amount": false,
"exchange_rate": "83.5642",
"payout_method": "upi",
"financial_account": {
"id": "fa_01h3x5n6z7y8w9v0u1t2s3r4",
"type": "upi",
"details": {
"upi_id": "9876543210@paytm"
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
"recipient_id": "ind_01h3x5n6z7y8w9v0u1t2s3r4",
"total_fee": "1.05",
"fee_currency": "usd",
"total_tax": "0.00",
"tax_currency": "usd",
"net_source_amount": "98.95",
"expires_at": "2025-01-15T10:32:00Z",
"created_at": "2025-01-15T10:30:00Z"
}

Step 3: Create a Transfer

You can create a transfer in two ways:

Reference the quote ID to use the locked exchange rate and fees.

Request:

POST /v1/transfers HTTP/1.1
Content-Type: application/json
{
"quote_id": "qu_01h3x5n6z7y8w9v0u1t2s3r4"
}

Option B: Without a quote

Provide the transfer parameters directly. The exchange rate will be determined at the time the transfer is processed. Specify exactly one of source_amount, destination_amount, or net_source_amount.

Request:

POST /v1/transfers HTTP/1.1
Content-Type: application/json
{
"source_amount": "100.00",
"source_currency": "usd",
"destination_currency": "inr",
"financial_account": { "id": "fa_01h3x5n6z7y8w9v0u1t2s3r4" },
"payout_method": "upi"
}

Response (both options):

HTTP/1.1 201 Created
Content-Type: application/json
{
"id": "tr_01h3x5n6z7y8w9v0u1t2s3r4",
"client_reference_id": null,
"source_amount": "100.00",
"source_currency": "usd",
"destination_amount": "8356.42",
"destination_currency": "inr",
"exchange_rate": "83.5642",
"recipient_id": "ind_01h3x5n6z7y8w9v0u1t2s3r4",
"financial_account_id": "fa_01h3x5n6z7y8w9v0u1t2s3r4",
"payout_method": "upi",
"status": "pending",
"total_fee": "1.05",
"fee_currency": "usd",
"total_tax": "0.00",
"tax_currency": "usd",
"net_source_amount": "98.95",
"completed_in": null,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z",
"failure_reason": null,
"settlement_reference_id": null
}

Step 4: Determine the Outcome

Once you’ve created a transfer, there are two options to determine the outcome:

  1. Webhooks (recommended): Listen for transfer.completed or transfer.failed events. See API basics — Webhooks.
  2. Polling: Call GET /v1/transfers/{id} to check the current status.