The Customers API lets you create and manage customer records on your integration. Customers are automatically created on first charge, but you can also create them explicitly.
Depends on: paystack-setup for the
paystackRequesthelper and environment config.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /customer |
Create a customer |
| GET | /customer |
List customers |
| GET | /customer/:email_or_code |
Fetch a customer |
| PUT | /customer/:code |
Update a customer |
| POST | /customer/:code/identification |
Validate customer identity |
| POST | /customer/set_risk_action |
Whitelist/Blacklist a customer |
| POST | /customer/authorization/initialize |
Initialize authorization |
| GET | /customer/authorization/verify/:reference |
Verify authorization |
| POST | /customer/:id/initialize-direct-debit |
Initialize direct debit |
| PUT | /customer/:id/directdebit-activation-charge |
Activate direct debit |
| GET | /customer/:id/directdebit-mandate-authorizations |
Fetch mandate authorizations |
| POST | /customer/authorization/deactivate |
Deactivate an authorization |
Create Customer
POST /customer
| Param | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Customer's email address |
first_name |
string | No | Customer's first name |
last_name |
string | No | Customer's last name |
phone |
string | No | Customer's phone number |
metadata |
object | No | Key/value pairs for additional info |
Note:
first_name,last_name, andphonebecome required when assigning a Dedicated Virtual Account to customers in Betting, Financial Services, or General Service business categories.
const customer = await paystackRequest<{
email: string;
customer_code: string;
id: number;
}>("/customer", {
method: "POST",
body: JSON.stringify({
email: "customer@example.com",
first_name: "Zero",
last_name: "Sum",
phone: "+2348123456789",
}),
});
// customer.data.customer_code → "CUS_xnxdt6s1zg1f4nx"
List Customers
GET /customer
| Param | Type | Required | Description |
|---|---|---|---|
perPage |
integer | No | Records per page (default: 50) |
page |
integer | No | Page number (default: 1) |
from |
datetime | No | Start date e.g. 2016-09-24T00:00:05.000Z |
to |
datetime | No | End date |
const customers = await paystackRequest("/customer?perPage=20&page=1");
Fetch Customer
GET /customer/:email_or_code
Returns full customer details including transactions, subscriptions, and authorizations arrays.
const customer = await paystackRequest(
`/customer/${encodeURIComponent("CUS_xnxdt6s1zg1f4nx")}`
);
// Includes: customer.data.authorizations[].authorization_code
Update Customer
PUT /customer/:code
await paystackRequest(`/customer/${encodeURIComponent("CUS_xnxdt6s1zg1f4nx")}`, {
method: "PUT",
body: JSON.stringify({
first_name: "BoJack",
last_name: "Horseman",
}),
});
Validate Customer Identity
POST /customer/:code/identification
Validates a customer's identity via bank account verification. Returns 202 Accepted — validation happens asynchronously. Listen for customeridentification.success or customeridentification.failed webhooks.
| Param | Type | Required | Description |
|---|---|---|---|
country |
string | Yes | 2-letter country code (e.g. NG) |
type |
string | Yes | bank_account (only supported type) |
account_number |
string | Yes | Customer's bank account number |
bvn |
string | Yes | Bank Verification Number |
bank_code |
string | Yes | Bank code (from List Banks endpoint) |
first_name |
string | Yes | Customer's first name |
last_name |
string | Yes | Customer's last name |
middle_name |
string | No | Customer's middle name |
await paystackRequest(
`/customer/${encodeURIComponent("CUS_xnxdt6s1zg1f4nx")}/identification`,
{
method: "POST",
body: JSON.stringify({
country: "NG",
type: "bank_account",
account_number: "0123456789",
bvn: "20012345677",
bank_code: "007",
first_name: "Asta",
last_name: "Lavista",
}),
}
);
// Returns: { status: true, message: "Customer Identification in progress" }
Whitelist / Blacklist Customer
POST /customer/set_risk_action
| Param | Type | Required | Description |
|---|---|---|---|
customer |
string | Yes | Customer code or email |
risk_action |
string | No | default, allow (whitelist), or deny (blacklist) |
await paystackRequest("/customer/set_risk_action", {
method: "POST",
body: JSON.stringify({
customer: "CUS_xr58yrr2ujlft9k",
risk_action: "deny", // Blacklist this customer
}),
});
Initialize Authorization
POST /customer/authorization/initialize
Create a reusable authorization code for recurring direct debit transactions.
| Param | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Customer's email |
channel |
string | Yes | direct_debit (only supported option) |
callback_url |
string | No | URL to redirect customer after authorization |
account |
object | No | { number, bank_code } for bank account details |
address |
object | No | { street, city, state } for customer address |
const auth = await paystackRequest<{
redirect_url: string;
access_code: string;
reference: string;
}>("/customer/authorization/initialize", {
method: "POST",
body: JSON.stringify({
email: "customer@email.com",
channel: "direct_debit",
callback_url: "https://example.com/callback",
}),
});
// Redirect customer to auth.data.redirect_url
Verify Authorization
GET /customer/authorization/verify/:reference
const result = await paystackRequest(
`/customer/authorization/verify/${encodeURIComponent(reference)}`
);
// result.data.authorization_code, result.data.active
Initialize Direct Debit
POST /customer/:id/initialize-direct-debit
Link a bank account to a customer for direct debit transactions.
const result = await paystackRequest(
`/customer/${customerId}/initialize-direct-debit`,
{
method: "POST",
body: JSON.stringify({
account: { number: "0123456789", bank_code: "058" },
address: { street: "Some Where", city: "Ikeja", state: "Lagos" },
}),
}
);
// Redirect customer to result.data.redirect_url
Direct Debit Activation Charge
PUT /customer/:id/directdebit-activation-charge
Trigger an activation charge on an inactive mandate.
await paystackRequest(`/customer/${customerId}/directdebit-activation-charge`, {
method: "PUT",
body: JSON.stringify({ authorization_id: 1069309917 }),
});
Fetch Mandate Authorizations
GET /customer/:id/directdebit-mandate-authorizations
const mandates = await paystackRequest(
`/customer/${customerId}/directdebit-mandate-authorizations`
);
// mandates.data[].status, mandates.data[].authorization_code
Deactivate Authorization
POST /customer/authorization/deactivate
Permanently deactivate a saved card/authorization so it can no longer be used for charges.
await paystackRequest("/customer/authorization/deactivate", {
method: "POST",
body: JSON.stringify({
authorization_code: "AUTH_xxxIjkZVj5",
}),
});