curl --request PUT \
--url https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'customer-id: <customer-id>' \
--data '
{
"amount": 200000,
"milestones": [
{
"title": "Design",
"description": "Figma mockups",
"amount": 60000,
"dueDate": "2026-07-15",
"customerId": "665f1b2c9a1e4d0012ab3c40"
},
{
"title": "Development",
"description": "Frontend + backend",
"amount": 140000
}
]
}
'import requests
url = "https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}"
payload = {
"amount": 200000,
"milestones": [
{
"title": "Design",
"description": "Figma mockups",
"amount": 60000,
"dueDate": "2026-07-15",
"customerId": "665f1b2c9a1e4d0012ab3c40"
},
{
"title": "Development",
"description": "Frontend + backend",
"amount": 140000
}
]
}
headers = {
"customer-id": "<customer-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {
'customer-id': '<customer-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 200000,
milestones: [
{
title: 'Design',
description: 'Figma mockups',
amount: 60000,
dueDate: '2026-07-15',
customerId: '665f1b2c9a1e4d0012ab3c40'
},
{title: 'Development', description: 'Frontend + backend', amount: 140000}
]
})
};
fetch('https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'amount' => 200000,
'milestones' => [
[
'title' => 'Design',
'description' => 'Figma mockups',
'amount' => 60000,
'dueDate' => '2026-07-15',
'customerId' => '665f1b2c9a1e4d0012ab3c40'
],
[
'title' => 'Development',
'description' => 'Frontend + backend',
'amount' => 140000
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"customer-id: <customer-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}"
payload := strings.NewReader("{\n \"amount\": 200000,\n \"milestones\": [\n {\n \"title\": \"Design\",\n \"description\": \"Figma mockups\",\n \"amount\": 60000,\n \"dueDate\": \"2026-07-15\",\n \"customerId\": \"665f1b2c9a1e4d0012ab3c40\"\n },\n {\n \"title\": \"Development\",\n \"description\": \"Frontend + backend\",\n \"amount\": 140000\n }\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("customer-id", "<customer-id>")
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(string(body))
}HttpResponse<String> response = Unirest.put("https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}")
.header("customer-id", "<customer-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 200000,\n \"milestones\": [\n {\n \"title\": \"Design\",\n \"description\": \"Figma mockups\",\n \"amount\": 60000,\n \"dueDate\": \"2026-07-15\",\n \"customerId\": \"665f1b2c9a1e4d0012ab3c40\"\n },\n {\n \"title\": \"Development\",\n \"description\": \"Frontend + backend\",\n \"amount\": 140000\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["customer-id"] = '<customer-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 200000,\n \"milestones\": [\n {\n \"title\": \"Design\",\n \"description\": \"Figma mockups\",\n \"amount\": 60000,\n \"dueDate\": \"2026-07-15\",\n \"customerId\": \"665f1b2c9a1e4d0012ab3c40\"\n },\n {\n \"title\": \"Development\",\n \"description\": \"Frontend + backend\",\n \"amount\": 140000\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": 200,
"message": "Escrow converted to milestone successfully",
"data": {
"id": "665f1b2c9a1e4d0012ab3c10",
"amount": 200000,
"purpose": "MacBook Pro 14\"",
"whoPays": "buyer",
"fee": 5000,
"paymentToken": "PY_8AB12C9D3045",
"status": "PENDING",
"state": "AWAITING_PAYMENT",
"settlementType": "MILESTONE",
"milestones": [
{
"id": "665f1b2c9a1e4d0012ab3c27",
"title": "Design",
"description": "Figma mockups",
"amount": 60000,
"dueDate": "2026-07-15",
"status": "PENDING",
"releasedAt": null
},
{
"id": "665f1b2c9a1e4d0012ab3c28",
"title": "Development",
"description": "Frontend + backend",
"amount": 140000,
"dueDate": null,
"status": "PENDING",
"releasedAt": null
}
],
"updatedAt": "2026-06-24T11:00:00.000Z"
}
}Convert standard escrow to milestone
Converts an existing standard escrow into a milestone escrow by splitting its amount into milestones (JSON body, no file upload). Supply amount to set a new escrow amount, or omit it to keep the current one; either way the sum of milestone amounts must equal the target amount, and there must be at least 2 milestones. Conversion forces the escrow to be buyer-paid (whoPays becomes buyer) and recalculates the fee. Allowed only while the escrow is still AWAITING_PAYMENT, and only by the seller that created it. Requires the customer-id header (the seller).
curl --request PUT \
--url https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'customer-id: <customer-id>' \
--data '
{
"amount": 200000,
"milestones": [
{
"title": "Design",
"description": "Figma mockups",
"amount": 60000,
"dueDate": "2026-07-15",
"customerId": "665f1b2c9a1e4d0012ab3c40"
},
{
"title": "Development",
"description": "Frontend + backend",
"amount": 140000
}
]
}
'import requests
url = "https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}"
payload = {
"amount": 200000,
"milestones": [
{
"title": "Design",
"description": "Figma mockups",
"amount": 60000,
"dueDate": "2026-07-15",
"customerId": "665f1b2c9a1e4d0012ab3c40"
},
{
"title": "Development",
"description": "Frontend + backend",
"amount": 140000
}
]
}
headers = {
"customer-id": "<customer-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {
'customer-id': '<customer-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 200000,
milestones: [
{
title: 'Design',
description: 'Figma mockups',
amount: 60000,
dueDate: '2026-07-15',
customerId: '665f1b2c9a1e4d0012ab3c40'
},
{title: 'Development', description: 'Frontend + backend', amount: 140000}
]
})
};
fetch('https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'amount' => 200000,
'milestones' => [
[
'title' => 'Design',
'description' => 'Figma mockups',
'amount' => 60000,
'dueDate' => '2026-07-15',
'customerId' => '665f1b2c9a1e4d0012ab3c40'
],
[
'title' => 'Development',
'description' => 'Frontend + backend',
'amount' => 140000
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"customer-id: <customer-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}"
payload := strings.NewReader("{\n \"amount\": 200000,\n \"milestones\": [\n {\n \"title\": \"Design\",\n \"description\": \"Figma mockups\",\n \"amount\": 60000,\n \"dueDate\": \"2026-07-15\",\n \"customerId\": \"665f1b2c9a1e4d0012ab3c40\"\n },\n {\n \"title\": \"Development\",\n \"description\": \"Frontend + backend\",\n \"amount\": 140000\n }\n ]\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("customer-id", "<customer-id>")
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(string(body))
}HttpResponse<String> response = Unirest.put("https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}")
.header("customer-id", "<customer-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 200000,\n \"milestones\": [\n {\n \"title\": \"Design\",\n \"description\": \"Figma mockups\",\n \"amount\": 60000,\n \"dueDate\": \"2026-07-15\",\n \"customerId\": \"665f1b2c9a1e4d0012ab3c40\"\n },\n {\n \"title\": \"Development\",\n \"description\": \"Frontend + backend\",\n \"amount\": 140000\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.api.payluk.ng/v1/escrow/milestone/convert/{paymentToken}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["customer-id"] = '<customer-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 200000,\n \"milestones\": [\n {\n \"title\": \"Design\",\n \"description\": \"Figma mockups\",\n \"amount\": 60000,\n \"dueDate\": \"2026-07-15\",\n \"customerId\": \"665f1b2c9a1e4d0012ab3c40\"\n },\n {\n \"title\": \"Development\",\n \"description\": \"Frontend + backend\",\n \"amount\": 140000\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": 200,
"message": "Escrow converted to milestone successfully",
"data": {
"id": "665f1b2c9a1e4d0012ab3c10",
"amount": 200000,
"purpose": "MacBook Pro 14\"",
"whoPays": "buyer",
"fee": 5000,
"paymentToken": "PY_8AB12C9D3045",
"status": "PENDING",
"state": "AWAITING_PAYMENT",
"settlementType": "MILESTONE",
"milestones": [
{
"id": "665f1b2c9a1e4d0012ab3c27",
"title": "Design",
"description": "Figma mockups",
"amount": 60000,
"dueDate": "2026-07-15",
"status": "PENDING",
"releasedAt": null
},
{
"id": "665f1b2c9a1e4d0012ab3c28",
"title": "Development",
"description": "Frontend + backend",
"amount": 140000,
"dueDate": null,
"status": "PENDING",
"releasedAt": null
}
],
"updatedAt": "2026-06-24T11:00:00.000Z"
}
}Authorizations
Your secret key as a Bearer token. The key prefix selects the environment: sk_test_... (test) or sk_live_... (live).
Headers
The merchant customer this request acts on behalf of.
Path Parameters
The escrow's payment token (e.g. PY_8AB12C9D3045).
Body
Splits a standard escrow's amount into milestones. amount is optional: supply it to set a new escrow amount, or omit it to keep the escrow's current amount. Either way the milestone amounts must sum to the target amount.
At least 2 milestones whose amounts sum to the target amount (the new amount if supplied, otherwise the escrow's existing amount).
2Show child attributes
Show child attributes
Optional new escrow amount. When omitted, the escrow keeps its current amount.
200000