curl --request PUT \
--url https://staging.api.payluk.ng/v1/customer/update/{customerId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"firstname": "Ada",
"lastname": "Eze",
"email": "[email protected]",
"phone": "09022331122",
"countryId": "NG"
}
'import requests
url = "https://staging.api.payluk.ng/v1/customer/update/{customerId}"
payload = {
"firstname": "Ada",
"lastname": "Eze",
"email": "[email protected]",
"phone": "09022331122",
"countryId": "NG"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
firstname: 'Ada',
lastname: 'Eze',
email: '[email protected]',
phone: '09022331122',
countryId: 'NG'
})
};
fetch('https://staging.api.payluk.ng/v1/customer/update/{customerId}', 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/customer/update/{customerId}",
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([
'firstname' => 'Ada',
'lastname' => 'Eze',
'email' => '[email protected]',
'phone' => '09022331122',
'countryId' => 'NG'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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/customer/update/{customerId}"
payload := strings.NewReader("{\n \"firstname\": \"Ada\",\n \"lastname\": \"Eze\",\n \"email\": \"[email protected]\",\n \"phone\": \"09022331122\",\n \"countryId\": \"NG\"\n}")
req, _ := http.NewRequest("PUT", 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(string(body))
}HttpResponse<String> response = Unirest.put("https://staging.api.payluk.ng/v1/customer/update/{customerId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"firstname\": \"Ada\",\n \"lastname\": \"Eze\",\n \"email\": \"[email protected]\",\n \"phone\": \"09022331122\",\n \"countryId\": \"NG\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.api.payluk.ng/v1/customer/update/{customerId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"firstname\": \"Ada\",\n \"lastname\": \"Eze\",\n \"email\": \"[email protected]\",\n \"phone\": \"09022331122\",\n \"countryId\": \"NG\"\n}"
response = http.request(request)
puts response.read_body{
"status": 200,
"message": "Customer updated successfully",
"data": {
"customerId": "6a19b57ffa797d3af379ca2a",
"firstname": "Ada",
"lastname": "Eze",
"email": "[email protected]",
"phone": "09022331122",
"bvn": null,
"status": "active",
"blockedReason": null,
"blockedAt": null,
"createdAt": "2026-05-29T15:49:19.848Z",
"dob": null,
"permissions": {
"canWithdraw": true,
"canBuy": true,
"canSell": true
},
"countryId": "69b8d4c7f80e1f661b48c9ca"
}
}Update customer
Corrects a customer’s profile details. Only firstname, lastname, email, phone and countryId are editable; bvn carries verification state and changes through its own flow.
Send at least one of the five fields; any field you omit is left untouched. The customer is resolved scoped to your merchant account, so an ID belonging to another merchant is rejected. Email and phone are each unique per merchant, so reusing one that another of your customers already holds fails with a validation error. A new phone is validated against the countryId you send, or your merchant account’s country if you omit it. Requires the API key to belong to a merchant super-admin account.
curl --request PUT \
--url https://staging.api.payluk.ng/v1/customer/update/{customerId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"firstname": "Ada",
"lastname": "Eze",
"email": "[email protected]",
"phone": "09022331122",
"countryId": "NG"
}
'import requests
url = "https://staging.api.payluk.ng/v1/customer/update/{customerId}"
payload = {
"firstname": "Ada",
"lastname": "Eze",
"email": "[email protected]",
"phone": "09022331122",
"countryId": "NG"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
firstname: 'Ada',
lastname: 'Eze',
email: '[email protected]',
phone: '09022331122',
countryId: 'NG'
})
};
fetch('https://staging.api.payluk.ng/v1/customer/update/{customerId}', 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/customer/update/{customerId}",
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([
'firstname' => 'Ada',
'lastname' => 'Eze',
'email' => '[email protected]',
'phone' => '09022331122',
'countryId' => 'NG'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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/customer/update/{customerId}"
payload := strings.NewReader("{\n \"firstname\": \"Ada\",\n \"lastname\": \"Eze\",\n \"email\": \"[email protected]\",\n \"phone\": \"09022331122\",\n \"countryId\": \"NG\"\n}")
req, _ := http.NewRequest("PUT", 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(string(body))
}HttpResponse<String> response = Unirest.put("https://staging.api.payluk.ng/v1/customer/update/{customerId}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"firstname\": \"Ada\",\n \"lastname\": \"Eze\",\n \"email\": \"[email protected]\",\n \"phone\": \"09022331122\",\n \"countryId\": \"NG\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.api.payluk.ng/v1/customer/update/{customerId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"firstname\": \"Ada\",\n \"lastname\": \"Eze\",\n \"email\": \"[email protected]\",\n \"phone\": \"09022331122\",\n \"countryId\": \"NG\"\n}"
response = http.request(request)
puts response.read_body{
"status": 200,
"message": "Customer updated successfully",
"data": {
"customerId": "6a19b57ffa797d3af379ca2a",
"firstname": "Ada",
"lastname": "Eze",
"email": "[email protected]",
"phone": "09022331122",
"bvn": null,
"status": "active",
"blockedReason": null,
"blockedAt": null,
"createdAt": "2026-05-29T15:49:19.848Z",
"dob": null,
"permissions": {
"canWithdraw": true,
"canBuy": true,
"canSell": true
},
"countryId": "69b8d4c7f80e1f661b48c9ca"
}
}Authorizations
Your secret key as a Bearer token. The key prefix selects the environment: sk_test_... (staging) or sk_live_... (production); a key on the wrong host is refused with 403 Unauthorized Access. Each key is limited to 10 requests per minute (429 beyond that) and, on production, to the IP addresses on your dashboard allowlist when one is configured.
Path Parameters
The merchant customer's unique identifier.
Body
At least one of firstname, lastname, email, phone or countryId must be present.
New first name. Cannot be an empty string.
1"Ada"
New last name. Cannot be an empty string.
1"Eze"
New email address. Stored lowercased and must not already belong to another customer on your account.
New phone number, digits only with no leading +. Validated for the country and stored in its local form; must not already belong to another customer on your account.
^[0-9]+$"09022331122"
New country, as an ISO 3166-1 alpha-2 code (NG) or an id from Get countries.
1"NG"