> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.redpincompany.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.redpincompany.com/_mcp/server.

# Making your first payment

> Step-by-step tutorial to complete your first test payment in sandbox

This tutorial walks you through the complete process of making your first test payment using Redpin's sandbox environment.

## Prerequisites

> **Info**
>
> Before starting, ensure you have sandbox credentials from our Partner Integrations Team and basic understanding of the [payment flow](/api-guide/getting-started#core-payment-flow).

**Required items:**

* Sandbox credentials from our Partner Integrations Team
* Your Customer ID on Redpin's platform

> **Warning**
>
> All API requests require OAuth 2.0 Bearer token authentication. See the [Authentication guide](/api-guide/getting-started/authentication) for complete setup instructions and token management.

## Step-by-step payment process

#### Step 1: Submit third-party customer data (if required)

> **Warning**
>
> **This step is only required if the person sending the funds is NOT the account holder.** If you (the account holder) are sending funds from your own account, skip this step and proceed to Step 2.

Submit compliance data for the third-party customer who will be making the payment:

**When to use this step:**

* Property developers collecting payments from buyers
* Platforms facilitating payments on behalf of their users
* Any scenario where the funding source is not the account holder

**When to skip this step:**

* You are sending funds from your own account
* Direct account holder transactions

#### Step 2: Get currency quote

Request a quote for the currency conversion:

> **Tip**
>
> Quotes expire after 30 minutes. Save the `quote_id` for creating the payment in Step 4.

#### Step 3: Add recipient

Register the beneficiary who will receive the payment:

### Request

POST [https://sandbox.currenciesdirect.com/v2/customers/\{customer_id}/recipients](https://sandbox.currenciesdirect.com/v2/customers/\{customer_id}/recipients)

**`Add an Individual Recipient in UAE using IBAN`**

```curl Add an Individual Recipient in UAE using IBAN
curl -X POST https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "name": "Ahmed Al Mansoori",
  "type": "Individual",
  "country_code": "ARE",
  "customer_own_account": "no",
  "address": {
    "address_line": "Office 2101, Jumeirah Bay X2 Tower",
    "city": "Dubai",
    "state": "Dubai",
    "post_code": "000000"
  },
  "recipient_bank_details": {
    "currency": "AED",
    "iban": "AE070331234567890123456"
  },
  "nick_name": "Ahmed UAE",
  "email": "ahmed.mansoori@example.com",
  "phone_number": "+971-501234567",
  "mobile_number": "+971-501234567",
  "client_reference_id": "recipient-123",
  "payment_reference": "Invoice#4567",
  "additional_details": {
    "tax_id": "AH12345678"
  }
}'
```

**`Add an Individual Recipient in UAE using IBAN`**

```python Add an Individual Recipient in UAE using IBAN
import requests

url = "https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients"

payload = {
    "name": "Ahmed Al Mansoori",
    "type": "Individual",
    "country_code": "ARE",
    "customer_own_account": "no",
    "address": {
        "address_line": "Office 2101, Jumeirah Bay X2 Tower",
        "city": "Dubai",
        "state": "Dubai",
        "post_code": "000000"
    },
    "recipient_bank_details": {
        "currency": "AED",
        "iban": "AE070331234567890123456"
    },
    "nick_name": "Ahmed UAE",
    "email": "ahmed.mansoori@example.com",
    "phone_number": "+971-501234567",
    "mobile_number": "+971-501234567",
    "client_reference_id": "recipient-123",
    "payment_reference": "Invoice#4567",
    "additional_details": { "tax_id": "AH12345678" }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Add an Individual Recipient in UAE using IBAN`**

```javascript Add an Individual Recipient in UAE using IBAN
const url = 'https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"name":"Ahmed Al Mansoori","type":"Individual","country_code":"ARE","customer_own_account":"no","address":{"address_line":"Office 2101, Jumeirah Bay X2 Tower","city":"Dubai","state":"Dubai","post_code":"000000"},"recipient_bank_details":{"currency":"AED","iban":"AE070331234567890123456"},"nick_name":"Ahmed UAE","email":"ahmed.mansoori@example.com","phone_number":"+971-501234567","mobile_number":"+971-501234567","client_reference_id":"recipient-123","payment_reference":"Invoice#4567","additional_details":{"tax_id":"AH12345678"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Add an Individual Recipient in UAE using IBAN`**

```go Add an Individual Recipient in UAE using IBAN
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients"

	payload := strings.NewReader("{\n  \"name\": \"Ahmed Al Mansoori\",\n  \"type\": \"Individual\",\n  \"country_code\": \"ARE\",\n  \"customer_own_account\": \"no\",\n  \"address\": {\n    \"address_line\": \"Office 2101, Jumeirah Bay X2 Tower\",\n    \"city\": \"Dubai\",\n    \"state\": \"Dubai\",\n    \"post_code\": \"000000\"\n  },\n  \"recipient_bank_details\": {\n    \"currency\": \"AED\",\n    \"iban\": \"AE070331234567890123456\"\n  },\n  \"nick_name\": \"Ahmed UAE\",\n  \"email\": \"ahmed.mansoori@example.com\",\n  \"phone_number\": \"+971-501234567\",\n  \"mobile_number\": \"+971-501234567\",\n  \"client_reference_id\": \"recipient-123\",\n  \"payment_reference\": \"Invoice#4567\",\n  \"additional_details\": {\n    \"tax_id\": \"AH12345678\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Add an Individual Recipient in UAE using IBAN`**

```ruby Add an Individual Recipient in UAE using IBAN
require 'uri'
require 'net/http'

url = URI("https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"name\": \"Ahmed Al Mansoori\",\n  \"type\": \"Individual\",\n  \"country_code\": \"ARE\",\n  \"customer_own_account\": \"no\",\n  \"address\": {\n    \"address_line\": \"Office 2101, Jumeirah Bay X2 Tower\",\n    \"city\": \"Dubai\",\n    \"state\": \"Dubai\",\n    \"post_code\": \"000000\"\n  },\n  \"recipient_bank_details\": {\n    \"currency\": \"AED\",\n    \"iban\": \"AE070331234567890123456\"\n  },\n  \"nick_name\": \"Ahmed UAE\",\n  \"email\": \"ahmed.mansoori@example.com\",\n  \"phone_number\": \"+971-501234567\",\n  \"mobile_number\": \"+971-501234567\",\n  \"client_reference_id\": \"recipient-123\",\n  \"payment_reference\": \"Invoice#4567\",\n  \"additional_details\": {\n    \"tax_id\": \"AH12345678\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

**`Add an Individual Recipient in UAE using IBAN`**

```java Add an Individual Recipient in UAE using IBAN
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"name\": \"Ahmed Al Mansoori\",\n  \"type\": \"Individual\",\n  \"country_code\": \"ARE\",\n  \"customer_own_account\": \"no\",\n  \"address\": {\n    \"address_line\": \"Office 2101, Jumeirah Bay X2 Tower\",\n    \"city\": \"Dubai\",\n    \"state\": \"Dubai\",\n    \"post_code\": \"000000\"\n  },\n  \"recipient_bank_details\": {\n    \"currency\": \"AED\",\n    \"iban\": \"AE070331234567890123456\"\n  },\n  \"nick_name\": \"Ahmed UAE\",\n  \"email\": \"ahmed.mansoori@example.com\",\n  \"phone_number\": \"+971-501234567\",\n  \"mobile_number\": \"+971-501234567\",\n  \"client_reference_id\": \"recipient-123\",\n  \"payment_reference\": \"Invoice#4567\",\n  \"additional_details\": {\n    \"tax_id\": \"AH12345678\"\n  }\n}")
  .asString();
```

**`Add an Individual Recipient in UAE using IBAN`**

```php Add an Individual Recipient in UAE using IBAN
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients', [
  'body' => '{
  "name": "Ahmed Al Mansoori",
  "type": "Individual",
  "country_code": "ARE",
  "customer_own_account": "no",
  "address": {
    "address_line": "Office 2101, Jumeirah Bay X2 Tower",
    "city": "Dubai",
    "state": "Dubai",
    "post_code": "000000"
  },
  "recipient_bank_details": {
    "currency": "AED",
    "iban": "AE070331234567890123456"
  },
  "nick_name": "Ahmed UAE",
  "email": "ahmed.mansoori@example.com",
  "phone_number": "+971-501234567",
  "mobile_number": "+971-501234567",
  "client_reference_id": "recipient-123",
  "payment_reference": "Invoice#4567",
  "additional_details": {
    "tax_id": "AH12345678"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Add an Individual Recipient in UAE using IBAN`**

```csharp Add an Individual Recipient in UAE using IBAN
using RestSharp;

var client = new RestClient("https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"name\": \"Ahmed Al Mansoori\",\n  \"type\": \"Individual\",\n  \"country_code\": \"ARE\",\n  \"customer_own_account\": \"no\",\n  \"address\": {\n    \"address_line\": \"Office 2101, Jumeirah Bay X2 Tower\",\n    \"city\": \"Dubai\",\n    \"state\": \"Dubai\",\n    \"post_code\": \"000000\"\n  },\n  \"recipient_bank_details\": {\n    \"currency\": \"AED\",\n    \"iban\": \"AE070331234567890123456\"\n  },\n  \"nick_name\": \"Ahmed UAE\",\n  \"email\": \"ahmed.mansoori@example.com\",\n  \"phone_number\": \"+971-501234567\",\n  \"mobile_number\": \"+971-501234567\",\n  \"client_reference_id\": \"recipient-123\",\n  \"payment_reference\": \"Invoice#4567\",\n  \"additional_details\": {\n    \"tax_id\": \"AH12345678\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Add an Individual Recipient in UAE using IBAN`**

```swift Add an Individual Recipient in UAE using IBAN
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "name": "Ahmed Al Mansoori",
  "type": "Individual",
  "country_code": "ARE",
  "customer_own_account": "no",
  "address": [
    "address_line": "Office 2101, Jumeirah Bay X2 Tower",
    "city": "Dubai",
    "state": "Dubai",
    "post_code": "000000"
  ],
  "recipient_bank_details": [
    "currency": "AED",
    "iban": "AE070331234567890123456"
  ],
  "nick_name": "Ahmed UAE",
  "email": "ahmed.mansoori@example.com",
  "phone_number": "+971-501234567",
  "mobile_number": "+971-501234567",
  "client_reference_id": "recipient-123",
  "payment_reference": "Invoice#4567",
  "additional_details": ["tax_id": "AH12345678"]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox.currenciesdirect.com/v2/customers/cust_123456789/recipients")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "client_reference_id": "recipient-123",
  "recipient_id": "1668758"
}
```

#### Step 4: Create payment with FX conversion

Create the payment order with automatic FX conversion:

> **Info**
>
> **Important:** Set the `is_third_party_payment` flag based on the same decision from Step 1:
>
> * `is_third_party_payment: true` - If you submitted third-party customer data in Step 1
> * `is_third_party_payment: false` - If you skipped Step 1 (account holder sending own funds)

### Request

POST [https://sandbox.currenciesdirect.com/v3/customers/\{customer_id}/payments](https://sandbox.currenciesdirect.com/v3/customers/\{customer_id}/payments)

**`Single Recipient Third-Party Payment`**

```curl Single Recipient Third-Party Payment
curl -X POST https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "purpose_of_transaction": "PROPERTY_PURCHASE",
  "amount": {
    "currency": "GBP",
    "value": 50000
  },
  "recipient_details": [
    {
      "amount": {
        "currency": "GBP",
        "value": 50000
      },
      "recipient_id": "REC-001",
      "payment_reference": "PROPERTY_PURCHASE_PAYMENT",
      "purpose_of_transaction": "PROPERTY_PURCHASE"
    }
  ],
  "client_reference_id": "REF120532",
  "quote_id": "548eb44b-5e1b-45fb-86eb-88eb5bcaa781",
  "is_third_party_payment": true,
  "client_customer_ref": "CUST-001",
  "payment_reference": "PAY-2024-001"
}'
```

**`Single Recipient Third-Party Payment`**

```python Single Recipient Third-Party Payment
import requests

url = "https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments"

payload = {
    "purpose_of_transaction": "PROPERTY_PURCHASE",
    "amount": {
        "currency": "GBP",
        "value": 50000
    },
    "recipient_details": [
        {
            "amount": {
                "currency": "GBP",
                "value": 50000
            },
            "recipient_id": "REC-001",
            "payment_reference": "PROPERTY_PURCHASE_PAYMENT",
            "purpose_of_transaction": "PROPERTY_PURCHASE"
        }
    ],
    "client_reference_id": "REF120532",
    "quote_id": "548eb44b-5e1b-45fb-86eb-88eb5bcaa781",
    "is_third_party_payment": True,
    "client_customer_ref": "CUST-001",
    "payment_reference": "PAY-2024-001"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Single Recipient Third-Party Payment`**

```javascript Single Recipient Third-Party Payment
const url = 'https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"purpose_of_transaction":"PROPERTY_PURCHASE","amount":{"currency":"GBP","value":50000},"recipient_details":[{"amount":{"currency":"GBP","value":50000},"recipient_id":"REC-001","payment_reference":"PROPERTY_PURCHASE_PAYMENT","purpose_of_transaction":"PROPERTY_PURCHASE"}],"client_reference_id":"REF120532","quote_id":"548eb44b-5e1b-45fb-86eb-88eb5bcaa781","is_third_party_payment":true,"client_customer_ref":"CUST-001","payment_reference":"PAY-2024-001"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Single Recipient Third-Party Payment`**

```go Single Recipient Third-Party Payment
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments"

	payload := strings.NewReader("{\n  \"purpose_of_transaction\": \"PROPERTY_PURCHASE\",\n  \"amount\": {\n    \"currency\": \"GBP\",\n    \"value\": 50000\n  },\n  \"recipient_details\": [\n    {\n      \"amount\": {\n        \"currency\": \"GBP\",\n        \"value\": 50000\n      },\n      \"recipient_id\": \"REC-001\",\n      \"payment_reference\": \"PROPERTY_PURCHASE_PAYMENT\",\n      \"purpose_of_transaction\": \"PROPERTY_PURCHASE\"\n    }\n  ],\n  \"client_reference_id\": \"REF120532\",\n  \"quote_id\": \"548eb44b-5e1b-45fb-86eb-88eb5bcaa781\",\n  \"is_third_party_payment\": true,\n  \"client_customer_ref\": \"CUST-001\",\n  \"payment_reference\": \"PAY-2024-001\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Single Recipient Third-Party Payment`**

```ruby Single Recipient Third-Party Payment
require 'uri'
require 'net/http'

url = URI("https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"purpose_of_transaction\": \"PROPERTY_PURCHASE\",\n  \"amount\": {\n    \"currency\": \"GBP\",\n    \"value\": 50000\n  },\n  \"recipient_details\": [\n    {\n      \"amount\": {\n        \"currency\": \"GBP\",\n        \"value\": 50000\n      },\n      \"recipient_id\": \"REC-001\",\n      \"payment_reference\": \"PROPERTY_PURCHASE_PAYMENT\",\n      \"purpose_of_transaction\": \"PROPERTY_PURCHASE\"\n    }\n  ],\n  \"client_reference_id\": \"REF120532\",\n  \"quote_id\": \"548eb44b-5e1b-45fb-86eb-88eb5bcaa781\",\n  \"is_third_party_payment\": true,\n  \"client_customer_ref\": \"CUST-001\",\n  \"payment_reference\": \"PAY-2024-001\"\n}"

response = http.request(request)
puts response.read_body
```

**`Single Recipient Third-Party Payment`**

```java Single Recipient Third-Party Payment
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"purpose_of_transaction\": \"PROPERTY_PURCHASE\",\n  \"amount\": {\n    \"currency\": \"GBP\",\n    \"value\": 50000\n  },\n  \"recipient_details\": [\n    {\n      \"amount\": {\n        \"currency\": \"GBP\",\n        \"value\": 50000\n      },\n      \"recipient_id\": \"REC-001\",\n      \"payment_reference\": \"PROPERTY_PURCHASE_PAYMENT\",\n      \"purpose_of_transaction\": \"PROPERTY_PURCHASE\"\n    }\n  ],\n  \"client_reference_id\": \"REF120532\",\n  \"quote_id\": \"548eb44b-5e1b-45fb-86eb-88eb5bcaa781\",\n  \"is_third_party_payment\": true,\n  \"client_customer_ref\": \"CUST-001\",\n  \"payment_reference\": \"PAY-2024-001\"\n}")
  .asString();
```

**`Single Recipient Third-Party Payment`**

```php Single Recipient Third-Party Payment
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments', [
  'body' => '{
  "purpose_of_transaction": "PROPERTY_PURCHASE",
  "amount": {
    "currency": "GBP",
    "value": 50000
  },
  "recipient_details": [
    {
      "amount": {
        "currency": "GBP",
        "value": 50000
      },
      "recipient_id": "REC-001",
      "payment_reference": "PROPERTY_PURCHASE_PAYMENT",
      "purpose_of_transaction": "PROPERTY_PURCHASE"
    }
  ],
  "client_reference_id": "REF120532",
  "quote_id": "548eb44b-5e1b-45fb-86eb-88eb5bcaa781",
  "is_third_party_payment": true,
  "client_customer_ref": "CUST-001",
  "payment_reference": "PAY-2024-001"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Single Recipient Third-Party Payment`**

```csharp Single Recipient Third-Party Payment
using RestSharp;

var client = new RestClient("https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"purpose_of_transaction\": \"PROPERTY_PURCHASE\",\n  \"amount\": {\n    \"currency\": \"GBP\",\n    \"value\": 50000\n  },\n  \"recipient_details\": [\n    {\n      \"amount\": {\n        \"currency\": \"GBP\",\n        \"value\": 50000\n      },\n      \"recipient_id\": \"REC-001\",\n      \"payment_reference\": \"PROPERTY_PURCHASE_PAYMENT\",\n      \"purpose_of_transaction\": \"PROPERTY_PURCHASE\"\n    }\n  ],\n  \"client_reference_id\": \"REF120532\",\n  \"quote_id\": \"548eb44b-5e1b-45fb-86eb-88eb5bcaa781\",\n  \"is_third_party_payment\": true,\n  \"client_customer_ref\": \"CUST-001\",\n  \"payment_reference\": \"PAY-2024-001\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Single Recipient Third-Party Payment`**

```swift Single Recipient Third-Party Payment
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "purpose_of_transaction": "PROPERTY_PURCHASE",
  "amount": [
    "currency": "GBP",
    "value": 50000
  ],
  "recipient_details": [
    [
      "amount": [
        "currency": "GBP",
        "value": 50000
      ],
      "recipient_id": "REC-001",
      "payment_reference": "PROPERTY_PURCHASE_PAYMENT",
      "purpose_of_transaction": "PROPERTY_PURCHASE"
    ]
  ],
  "client_reference_id": "REF120532",
  "quote_id": "548eb44b-5e1b-45fb-86eb-88eb5bcaa781",
  "is_third_party_payment": true,
  "client_customer_ref": "CUST-001",
  "payment_reference": "PAY-2024-001"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox.currenciesdirect.com/v3/customers/cust_123456789/payments")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (201)

```json
{
  "payment_id": "PAY-2024-001",
  "instruction_number": "CUST-001-0001",
  "amount": {
    "currency": "AUD",
    "value": 50000
  },
  "recipient_details": [
    {
      "recipient_id": "REC-001",
      "recipient_name": "John Smith",
      "amount": {
        "currency": "AUD",
        "value": 50000
      },
      "payment_reference": "PROPERTY_PURCHASE_PAYMENT",
      "country": "GBR"
    }
  ],
  "status": "AWAITING_FUNDS",
  "created_datetime": "2024-01-15T10:30:00Z"
}
```

**Key parameters:**

* `is_third_party_payment`: Must match whether you completed Step 1
* `client_customer_ref`: Required when `is_third_party_payment: true`
* `quote_id`: From Step 2
* `recipient_details`: From Step 3

#### Step 5: Get payment instructions

Retrieve the bank details for the customer to send their payment:

### Request

GET [https://sandbox.currenciesdirect.com/v3/customers/\{customer_id}/payments/\{payment_id}/bank-transfer-instructions](https://sandbox.currenciesdirect.com/v3/customers/\{customer_id}/payments/\{payment_id}/bank-transfer-instructions)

**`Domestic Transfer (VBAN)`**

```curl Domestic Transfer (VBAN)
curl -G https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions \
     -H "Authorization: Bearer <token>" \
     -d from_country=GBR
```

**`Domestic Transfer (VBAN)`**

```python Domestic Transfer (VBAN)
import requests

url = "https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions"

querystring = {"from_country":"GBR"}

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

**`Domestic Transfer (VBAN)`**

```javascript Domestic Transfer (VBAN)
const url = 'https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR';
const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Domestic Transfer (VBAN)`**

```go Domestic Transfer (VBAN)
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Domestic Transfer (VBAN)`**

```ruby Domestic Transfer (VBAN)
require 'uri'
require 'net/http'

url = URI("https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

**`Domestic Transfer (VBAN)`**

```java Domestic Transfer (VBAN)
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR")
  .header("Authorization", "Bearer <token>")
  .asString();
```

**`Domestic Transfer (VBAN)`**

```php Domestic Transfer (VBAN)
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

**`Domestic Transfer (VBAN)`**

```csharp Domestic Transfer (VBAN)
using RestSharp;

var client = new RestClient("https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

**`Domestic Transfer (VBAN)`**

```swift Domestic Transfer (VBAN)
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox.currenciesdirect.com/v3/customers/020123456789/payments/987654321/bank-transfer-instructions?from_country=GBR")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "payment_method": "domestic_transfer",
  "amount": {
    "currency": "GBP",
    "value": 1000.45
  },
  "account_details": {
    "name": "Wattson",
    "address": "Texas, Texas, Texas, 32323, USA"
  },
  "bank_details": {
    "name": "JP Morgan Chase",
    "address": "J.P. Morgan Florida 12345",
    "routing_codes": [
      {
        "type": "ROUTING_EFT",
        "value": "028000024",
        "label": "EFT routing number"
      },
      {
        "type": "ROUTING_WIRE",
        "value": "021000021",
        "label": "Wire routing number"
      },
      {
        "type": "ACCOUNT_NUMBER",
        "value": "20000023381857",
        "label": "Account number"
      },
      {
        "type": "ACCOUNT_TYPE",
        "value": "checking",
        "label": "Account type"
      }
    ]
  },
  "payment_reference": {
    "value": "ABCD123456",
    "label": "Payment reference",
    "disclaimer": "Always include this payment reference – it tells us the money has come from you."
  },
  "payment_scheme_note": "Please note: This account only accepts FPS, BACS and CHAPS payments. FPS payments are available for amounts up to £1 million."
}
```

## Webhook configuration

#### Set up webhooks for status updates

Configure webhooks to receive real-time payment status updates:

### Request

POST [https://sandbox.currenciesdirect.com/v1/webhooks](https://sandbox.currenciesdirect.com/v1/webhooks)

```curl
curl -X POST https://sandbox.currenciesdirect.com/v1/webhooks \
     -H "Authorization: Bearer <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "endpoint": "https://webhooks.merchantapp.com/notify/payment-status",
  "event_type": "PAYMENT STATUS"
}'
```

```python
import requests

url = "https://sandbox.currenciesdirect.com/v1/webhooks"

payload = {
    "endpoint": "https://webhooks.merchantapp.com/notify/payment-status",
    "event_type": "PAYMENT STATUS"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://sandbox.currenciesdirect.com/v1/webhooks';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"endpoint":"https://webhooks.merchantapp.com/notify/payment-status","event_type":"PAYMENT STATUS"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://sandbox.currenciesdirect.com/v1/webhooks"

	payload := strings.NewReader("{\n  \"endpoint\": \"https://webhooks.merchantapp.com/notify/payment-status\",\n  \"event_type\": \"PAYMENT STATUS\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://sandbox.currenciesdirect.com/v1/webhooks")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"endpoint\": \"https://webhooks.merchantapp.com/notify/payment-status\",\n  \"event_type\": \"PAYMENT STATUS\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://sandbox.currenciesdirect.com/v1/webhooks")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"endpoint\": \"https://webhooks.merchantapp.com/notify/payment-status\",\n  \"event_type\": \"PAYMENT STATUS\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://sandbox.currenciesdirect.com/v1/webhooks', [
  'body' => '{
  "endpoint": "https://webhooks.merchantapp.com/notify/payment-status",
  "event_type": "PAYMENT STATUS"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://sandbox.currenciesdirect.com/v1/webhooks");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"endpoint\": \"https://webhooks.merchantapp.com/notify/payment-status\",\n  \"event_type\": \"PAYMENT STATUS\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "endpoint": "https://webhooks.merchantapp.com/notify/payment-status",
  "event_type": "PAYMENT STATUS"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox.currenciesdirect.com/v1/webhooks")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "id": 10234
}
```

> **Note**
>
> Webhook signatures are included in the `svix-signature` header for security verification. See [Webhooks documentation](/api-guide/webhooks) for signature validation examples.

## Testing the payment flow

> **Check**
>
> In sandbox, payments are automatically simulated with instant status updates for testing purposes.

#### Status progression

Monitor these status changes during testing:

1. **`AWAITING_FUNDS`** - Payment created, awaiting customer funds
2. **`RECEIVED_FUNDS`** - Funds received, ready for FX conversion
3. **`FX_COMPLETED`** - Currency conversion completed
4. **`PAYOUT_INITIATED`** - Transfer to recipient initiated
5. **`PAYMENT_COMPLETED`** - Payment successfully delivered to recipient

#### Successful payment test

**Expected flow**:

* All steps complete without errors
* Webhooks deliver status updates
* Final status is `PAYMENT_COMPLETED`

#### Common test scenarios

**Quote expiration**:

* Quote expires before conversion creation
* Regenerate quote and retry

**Validation errors**:

* Invalid recipient bank details
* Incorrect currency codes
* Missing required fields

## Next steps

#### [Error handling](/api-guide/getting-started/error-handling)

Review error handling patterns and implement robust failure recovery

#### [Production migration](/api-guide/getting-started/sandbox-to-production)

Plan your migration from sandbox to production environment

#### [Integration options](/api-guide/partners/integration-guidelines)

Explore API vs Hosted approaches for your platform

#### [Webhooks setup](/api-guide/webhooks)

Configure production webhooks for real-time notifications