Remittances

This guide serves as a walkthrough for Fuze's C2C Remittance solution.

Fuze allows partners to carry out remittance payments worldwide by taking advantage of stablecoins to settle with local payout partners. This means faster payouts, and highly competitive rates.

Buy local currency

Generate quote

To place an order for local currency, you will first need to generate a quote.

POST /api/v1/payment/remittance/quote

Body Parameters

fromCurrency: The currency you are converting from (required)

toCurrency: The local currency you want to buy (required)

quantity: The amount of currency you want to convert (fromCurrency) (required)

orgUserId: This is a static value which will be provided to you by us (required)


The request would be as follows:

{
  fromCurrency: 'AED',
  toCurrency: 'INR',
  quantity: 100,
  orgUserId: 'org-user'
}

In the response, you will get a quote id and an expiry time, as shown below.

{
	code: 200,
	data: {
	  quoteId: 1,
	  fromCurrency: 'AED',
	  toCurrency: 'INR',
	  quantity: 100,
	  price: 20,
	  expiryTime: 1717332855
	},
	error: null
}

Place order

The quote id can then be used to place the order, using the endpoint below.

POST /api/v1/payment/remittance/payment

Body Parameters

quoteId: The quote id that was created in last api (required)

quantity: The quantity of from currency that was used in last api (required)

`orgUserId: This is a static value which will be provided to you by us (required)

The request would be as follows

{
  quoteId: 1,
  quantity: 100,
  orgUserId: 'org-user'
}

A successful response will look as follows

{
	code: 200,
	data: {
	  uuid: '21a0194f-709e-4c62-8590-464ddb9abd8f',
	  fromCurrency: 'AED',
	  toCurrency: 'INR',
	  quantity: 100,
	  status: 'PENDING'
	},
	error: null
}

Fetch order

You can then fetch the status of the order using this API endpoint.

POST /api/v1/payment/remittance/payment/fetch

{
    "uuid": "21a0194f-709e-4c62-8590-464ddb9abd8f"
}

A successful response will look as follows:

{
    "code": 200,
    "data": {
        "uuid": "21a0194f-709e-4c62-8590-464ddb9abd8f",
        "fromCurrency": "AED",
        "toCurrency": "INR",
        "quantity": 100,
        "status": "COMPLETED"
    },
    "error": null
}

In case the order fails, the response will look as follows:

{
    "code": 200,
    "data": {
        "uuid": "21a0194f-709e-4c62-8590-464ddb9abd8f",
        "fromCurrency": "AED",
        "toCurrency": "INR",
        "quantity": 100,
        "status": "REJECTED"
    },
    "error": null
}

Fetch balance

At any given point, you can fetch your current balances using the API below.

GET /api/v1/payment/remittance/balance

A successful response will look as follows:

{
    "code": 200,
    "data": {
        "balance": [
            {
                "currency": "INR",
                "value": 1712.84
            },
            {
                "currency": "USD",
                "value": 999980
            }
        ]
    },
    "error": null
}

Verify Beneficiary

You can then verify the beneficiary using this API endpoint.

POST/api/v1/payment/remittance/beneficiary/create

{
    "receiverClientIdentifier": "RECEIVER_1",
    "currency": "INR",
    "accountType": "BANK",
    "country": "IN",
    "accountData": {
        "accountNumber": "1234567890",
        "ifscCode": "AMDN0000104",
        "name": "Beneficiary Test",
        "bankAccountType": "NRO/SAVINGS"
    }
}

receiverClientIdentifier: The unique identifier for the beneficiary (required)

currency: The local currency of the beneficiary (required)

accountType: Type of payout method. A list of payout methods for each corridor, and respective account data, will shared separately. (required)

country: Country of the beneficiary (required)

accountNumber: Bank account number of the beneficiary (required)

ifscCode: IFSC code of the bank account (required)

name: Full name of the beneficiary (required)

bankAccountType: Type of bank account. 'NRO/SAVINGS' or 'NRE' is supported for India. (optional)

In case a beneficiary verification is completed, the responses will look as follows:

{
    "code": 200,
    "data": {
        "status": "ACTIVE",
        "clientIdentifier": "RECEIVER_1"
    },
    "error": null
}
{
    "code": 200,
    "data": {
        "status": "INACTIVE",
        "clientIdentifier": "RECEIVER_1"
    },
    "error": null
}

Beneficiary verification can result in the following statuses:

ACTIVE - The beneficiary details have been successfully verified and are correct.

INACTIVE - The beneficiary details could not be verified or are incorrect.

If beneficiary verification is not immediately completed, we will return a pending state:

{
    "code": 200,
    "data": {
        "status": "PENDING",
        "clientIdentifier": "RECEIVER_1"
    },
    "error": null
}

** Webhooks will be there as well for any state change **

Creating a Payout

POST/api/v1/payment/remittance/payout/create-with-details

Fuze has a single API which takes the following data:

  • Originator KYC data
  • Beneficiary Payment Instrument Details
  • Payout Amount and associated data

In the example below, it assumes an INR Payout.

{
    "email": "[email protected]",
    "name": "test",
    "address": "1-A, Baker's street",
    "nationality": "INDIAN",
    "idType": "EID",
    "idNumber": "123456",
    "senderClientIdentifier": "DIRECT_REMIT_SENDER_1",
    "country": "AE",
    "dob": "1990-09-09",
    "clientOrderId": "DIRECT_REMIT_1",
    "amount": 10,
    "purpose": "SALARY",
    "account": {
        "receiverClientIdentifier": "DIRECT_REMIT_RECEIVER_1",
        "currency": "INR",
        "accountType": "BANK",
        "country": "IN",
        "accountData": {
            "accountNumber": "1234567890",
            "ifscCode": "AMDN0000104",
            "name": "Direct Remit Test",
            "bankAccountType": "NRO/SAVINGS"
        }
    }
}

Body Parameters

name: Full name of the originator (required)

email : Email address of the originator (optional - but either one of email or phone number is mandatory.)

phoneNumber: Phone number of the originator (optional - but either one of email or phone number is mandatory.)

address: Address of the originator (required)

nationality: Nationality of the originator (required)

country: Country where the originator is sending funds from / Country in which Id is issued. Country codes will be 2 alphabets (based on the ISO 3166 standard) (required)

idType: Name of ID, for example “EID” (required)

idNumber: ID number collected (required)

senderClientIdentifier: A unique identifier for the originator passed by you (required)

dob: Date of birth of the originator (required) (format: YYYY-MM-DD)

receiverClientIdentifier: The unique identifier for the beneficiary (required)

currency: The local currency of the beneficiary (required)

accountType: Type of payout method. A list of payout methods for each corridor, and respective account data, will shared separately. (required)

country: Country of the beneficiary (required)

relationship: Relationship between beneficiary and originator. This list can be different for different countries, and will be shared separately. (optional)

clientOrderId: An idempotency key to avoid duplicate requests (required)

amount: The amount of local currency that needs to be sent (required)

purpose: Purpose of transfer from originator to beneficiary (required)

accountData: Account data of the beneficiary. This data is validated by Fuze based on the type passed above. In the example below, the bank details for an Indian account are listed:

accountNumber: Bank account number of the beneficiary (required)

ifscCode: IFSC code of the bank account (required)

name: Full name of the beneficiary (required)

bankAccountType: Type of bank account. 'NRO/SAVINGS' or 'NRE' is supported for India. (optional)

The response would look as follows:

{
    "code": 200,
    "data": {
        "payoutId": 28863,
        "amount": 10,
        "currency": "INR",
        "payoutStatus": "PENDING",
        "createdAt": "2025-06-26T11:43:11.952Z",
        "paymentReferenceNumber": "",
        "paymentDate": "",
        "clientOrderId": "DIRECT_REMIT_1",
        "name": "test",
        "email": "[email protected]",
        "senderStatus": "ACTIVE",
        "senderClientIdentifier": "DIRECT_REMIT_SENDER_1",
        "receiverClientIdentifier": "DIRECT_REMIT_RECEIVER_1"
    },
    "error": null
}

Error and rejection scenarios

The following error codes will be received if the payout request cannot be placed. In such cases, the status will not move to pending. Instead the response to the request will contain the following error codes. Currency-specific payout failure reasons will be shared separately for each corridor:

code : 400, message : 'amount must not be less than 1'

code : 400, message : 'Invalid currency'

code : 400, message : 'clientOrderId must be shorter than or equal to 128 characters,clientOrderId should not be empty,clientOrderId must be a string'

code : 400, message : 'purpose must be shorter than or equal to 36 characters,purpose should not be empty,purpose must be a string'

code : 500, message : 'Insufficient balance for the payout'

code : 500, message : 'Payout already exists'

In case there's a failure thanks to a local payout partner outage, the payout will move to pending state first. So you will receive a webhook with failure reason. In some countries, there can be a variation of a pending state where more data is required for AML reasons, the documentation and process flow for which will be shared separately.

Payout Status

You can then fetch the status of the payout using this API endpoint.

POST/api/v1/payment/remittance/payout/fetch/

{
    "clientOrderId": "DIRECT_REMIT_1"
}

In case a payout is successful, the response will look as below

{
    "code": 200, 
    "data": {
            "status": "COMPLETED",
            "currency": "INR",
            "amountDeducted": -10,
            "amountSent": -10,
            "createdAt": "2025-03-03T11:03:33.879Z",
            "referenceId": "Bank-12345",
            "paymentReferenceNumber": "123456",
            "paymentDate": "2025-03-03T11:03:33.879Z",
            "clientOrderId": 'DIRECT_REMIT_1'
    },
    "error": null
}

Payouts have the following statuses:

COMPLETED - The payout has been successfully processed.

PENDING - The payout is still being processed

CANCELED - The payout has failed

REVERSED - The payout was initially marked as successfully processed, but has since been marked as failed.

EXPIRED - The payout was in Pending state for a long time, and has been expired by Fuze.


Webhooks

You can configure webhooks for all of the above status events. Webhook data will match what you'd get if you directly inquire the Payout Status API. Sample webhooks are below.

Pending

{
    "event": {
        "orgId": 12938,
        "entity": "BankTransfers",
        "eventType": "PAYOUT_PROCESSED",
        "numRetries": 0,
        "createdAt": "2025-07-01T06:46:50.330Z",
        "updatedAt": "2025-07-01T06:46:50.330Z"
    },
    "data": {
        "status": "PENDING",
        "currency": "INR",
        "amountDeducted": -10,
        "amountSent": -10,
        "createdAt": "2025-06-30T09:11:23.296Z",
        "referenceId": "BK-2025-06-30-1751274683121-6677915",
        "paymentReferenceNumber": "BK-2025-06-30-1751274683121-6677915",
        "paymentDate": "",
        "clientOrderId": "DIRECT_REMIT_1"
    }
}

Completed

{
    "event": {
        "orgId": 12938,
        "entity": "BankTransfers",
        "eventType": "PAYOUT_PROCESSED",
        "numRetries": 0,
        "createdAt": "2025-07-01T06:46:50.330Z",
        "updatedAt": "2025-07-01T06:46:50.330Z"
    },
    "data": {
        "status": "COMPLETED",
        "currency": "INR",
        "amountDeducted": -10,
        "amountSent": -10,
        "createdAt": "2025-06-30T09:11:23.296Z",
        "referenceId": "BK-2025-06-30-1751274683121-6677915",
        "paymentReferenceNumber": "BK-2025-06-30-1751274683121-6677915",
        "paymentDate": "",
        "clientOrderId": "DIRECT_REMIT_1"
    }
}

Failed

{
    "event": {
        "orgId": 12938,
        "entity": "BankTransfers",
        "eventType": "PAYOUT_PROCESSED",
        "numRetries": 0,
        "createdAt": "2025-07-01T06:46:50.330Z",
        "updatedAt": "2025-07-01T06:46:50.330Z"
    },
    "data": {
        "status": "CANCELED",
        "currency": "INR",
        "amountDeducted": -10,
        "amountSent": -10,
        "createdAt": "2025-06-30T09:11:23.296Z",
        "referenceId": "BK-2025-06-30-1751274683121-6677915",
        "paymentReferenceNumber": "BK-2025-06-30-1751274683121-6677915",
        "paymentDate": "",
        "clientOrderId": "DIRECT_REMIT_1",
        "reason": "Insufficient balance"
    }
}

Reversed

{
    "event": {
        "orgId": 12938,
        "entity": "BankTransfers",
        "eventType": "PAYOUT_PROCESSED",
        "numRetries": 0,
        "createdAt": "2025-07-01T06:46:50.330Z",
        "updatedAt": "2025-07-01T06:46:50.330Z"
    },
    "data": {
        "status": "REVERSED",
        "currency": "INR",
        "amountDeducted": -10,
        "amountSent": -10,
        "createdAt": "2025-06-30T09:11:23.296Z",
        "referenceId": "BK-2025-06-30-1751274683121-6677915",
        "paymentReferenceNumber": "BK-2025-06-30-1751274683121-6677915",
        "paymentDate": "",
        "clientOrderId": "DIRECT_REMIT_1",
        "reason": "Bank gateway error"
    }
}

The failure reasons mentioned above are generic. They will differ from corridor to corridor, and will be shared by us separately.