Customer Management

Create and manage customer records on Atlas, optionally with a dedicated virtual account for each customer.

A customer is a record on Atlas representing an individual or business that transacts with you, it lets you track who's paying you, update their details, and manage their standing on your account. Creating a customer is optional, you don't need one to accept payments.

Optionally, you can also provision a dedicated virtual account (DVA) for a customer, either when you create them or later. A DVA works like a bank account scoped to that customer: it gets its own unique account number and account name (matching the customer's name or business name), and any money paid into it is tracked against that customer. When a customer deposits money into their DVA, your Atlas account receives the funds and Atlas sends you a webhook to notify your backend of the transaction. Using the data from the webhook, you can update your customer records accordingly.

Related

Learn how webhooks work on Atlas on our webhook guide. Looking for a virtual account that isn't tied to a customer? See the Virtual Accounts guide instead.

Creating a customer

Customers are either individual or business, controlled by the type field:

  • Individual (type: "individual") - a single person. Requires first_name and last_name in addition to email and phone.
  • Business (type: "business") - a company or organization. Requires business_name in addition to email and phone. The first_name and last_name are auto-generated.

To create a customer, make a request to the create new customer endpoint. Only email, phone, type, and the type-specific name field are required. Set has_wallet to true to also provision a DVA for the customer, the resolved account name uses the customer's name or business name.

The request payload depends on the customer type:

{
  "first_name": "John",
  "last_name": "Doe",
  "email": "john.doe@example.com",
  "phone": "+2347012345678",
  "type": "individual",
  "has_wallet": true
}

The examples below show how to send this request for an individual customer:

curl -X POST "https://atlas.tryduplo.com/api/v1/customer" \
  -H "Authorization: Bearer your_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@example.com",
    "phone": "+2347012345678",
    "type": "individual",
    "has_wallet": true
  }'

Tip

For added security, consider encrypting this request before sending it to the Atlas API.

On a successful request, you'll get a response similar to the one below:

JSON
{
  "requestId": "a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
  "requestTimestamp": "2025-07-16 09:15:00",
  "message": "Customer created successfully",
  "statusCode": 201,
  "data": {
    "id": "019a1639-ce25-70b7-ab20-16fcb2bac023",
    "firstName": "John",
    "lastName": "Doe",
    "type": "individual",
    "businessName": null,
    "email": "john.doe@example.com",
    "phoneNumber": "+2347012345678",
    "reference": "dp_cust_iovciv7ovnw1qcx",
    "businessState": "TEST",
    "isBlacklisted": false,
    "hasWallet": true,
    "wallet": {
      "id": "469e02df-43ae-46e7-8ebc-0b0ab5e19303",
      "walletId": "469e02df-43ae-46e7-8ebc-0b0ab5e19304",
      "businessId": "469e02df-43ae-46e7-8ebc-0b0ab5e19305",
      "currency": "NGN",
      "category": "customer",
      "type": "multi_use",
      "status": "active",
      "accountNumber": "6754358291",
      "accountName": "dp_pay/john doe/john doe",
      "provider": "Zenith Bank"
    },
    "status": "ACTIVE",
    "source": "API",
    "createdAt": "2025-10-24 12:37:58"
  }
}

Info

The has_wallet field is a boolean that defaults to false. To create a virtual account along with the customer, you need to set this field to true in your payload.

The details for the customer's virtual account are contained under the wallet property, where accountNumber refers to the customer's virtual account number, accountName is the name associated with the virtual account, and provider is the bank associated with the virtual account.

Attaching a virtual account to an existing customer

If a customer does not already have a virtual account, for example because you created them without setting has_wallet to true, or Atlas created them automatically from a checkout, you can provision one later using the Create Customer Virtual Account endpoint. Pass the customer's reference ID in the URL.

Both fields in the request body are optional:

  • wallet_va_name - A display name for the virtual account. If omitted, Atlas resolves the name from the customer's details.
  • provider_name - The virtual account provider to use, either globus or wema. If omitted, Atlas uses the provider configured for your business state.
curl -X POST "https://atlas.tryduplo.com/api/v1/customer/create-virtual-account-by-reference/dp_cust_iovciv7ovnw1qcx" \
  -H "Authorization: Bearer your_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "wallet_va_name": "John Wallet",
    "provider_name": "wema"
  }'

On success, Atlas provisions the virtual account and returns the updated customer object with the wallet populated:

JSON
{
  "requestId": "a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
  "requestTimestamp": "2025-07-16 09:15:00",
  "message": "Customer wallet created successfully",
  "statusCode": 201,
  "data": {
    "id": "019a1639-ce25-70b7-ab20-16fcb2bac023",
    "firstName": "John",
    "lastName": "Doe",
    "type": "individual",
    "businessName": null,
    "email": "john.doe@example.com",
    "phoneNumber": "+2347012345678",
    "reference": "dp_cust_iovciv7ovnw1qcx",
    "businessState": "TEST",
    "isBlacklisted": false,
    "hasWallet": true,
    "wallet": {
      "id": "469e02df-43ae-46e7-8ebc-0b0ab5e19303",
      "walletId": "469e02df-43ae-46e7-8ebc-0b0ab5e19304",
      "businessId": "469e02df-43ae-46e7-8ebc-0b0ab5e19305",
      "currency": "NGN",
      "category": "customer",
      "type": "multi_use",
      "status": "active",
      "accountNumber": "6754358291",
      "accountName": "John Wallet",
      "provider": "Wema Bank"
    },
    "status": "ACTIVE",
    "source": "API",
    "createdAt": "2025-10-24 12:37:58"
  }
}

Info

A customer can only have one virtual account. If the customer already has one, the request returns a 422 error with the message "Customer already has a wallet." Use the Get Customer by Reference endpoint to check a customer's hasWallet status before calling this endpoint.

Retrieving customer information

You can retrieve information about a specific customer using the Get Customer by Reference endpoint:

curl -X GET "https://atlas.tryduplo.com/api/v1/customer/find-by-reference/dp_cust_iovciv7ovnw1qcx" \
  -H "Authorization: Bearer your_api_key" \
  -H "Accept: application/json"

To retrieve a list of all your customers, use the Get Customer List endpoint. It supports pagination (page, limit) and filtering by search, status, reference, sort, startDate, and endDate:

curl -X GET "https://atlas.tryduplo.com/api/v1/customer?limit=10&page=1" \
  -H "Authorization: Bearer your_api_key" \
  -H "Accept: application/json"

Updating customer information

You can update outdated or inaccurate customer information using the Update Customer by Reference endpoint. To call this endpoint, you need the customer's reference ID, available from the customer creation response or the Get Customer List endpoint.

For example, to update a customer's name and phone number:

curl -X PUT "https://atlas.tryduplo.com/api/v1/customer/update-by-reference/dp_cust_iovciv7ovnw1qcx" \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "phone": "+2347098765432"
  }'

You can only update a customer's first_name, last_name, and phone.

Blacklisting a customer

Blacklisting prevents a customer from performing transactions through their virtual account. This is useful for handling fraudulent activity or enforcing compliance requirements. When a customer is blacklisted, any deposits to their virtual account will be automatically reversed.

To blacklist a customer, use the Blacklist Customer endpoint with the customer's reference ID:

curl -X POST "https://atlas.tryduplo.com/api/v1/customer/blacklist" \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "reference": "dp_cust_iovciv7ovnw1qcx"
  }'

You'll receive a response confirming the blacklist status:

JSON
{
  "requestId": "a1b2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
  "requestTimestamp": "2025-07-16 09:15:00",
  "message": "Customer has been blacklisted.",
  "statusCode": 200,
  "data": {
    "id": "019a1639-ce25-70b7-ab20-16fcb2bac023",
    "firstName": "John",
    "lastName": "Doe",
    "type": "individual",
    "businessName": null,
    "email": "john.doe@example.com",
    "phoneNumber": "+2347012345678",
    "reference": "dp_cust_iovciv7ovnw1qcx",
    "businessState": "TEST",
    "isBlacklisted": true,
    "hasWallet": true,
    "wallet": {
      "id": "469e02df-43ae-46e7-8ebc-0b0ab5e19303",
      "walletId": "469e02df-43ae-46e7-8ebc-0b0ab5e19304",
      "businessId": "469e02df-43ae-46e7-8ebc-0b0ab5e19305",
      "currency": "NGN",
      "category": "customer",
      "type": "multi_use",
      "status": "active",
      "accountNumber": "6754358291",
      "accountName": "dp_pay/john doe/john doe",
      "provider": "Zenith Bank"
    },
    "status": "ACTIVE",
    "source": "API",
    "createdAt": "2025-10-24 12:37:58"
  }
}

To remove a customer from the blacklist, use the Activate Customer endpoint with the customer's reference ID:

curl -X POST "https://atlas.tryduplo.com/api/v1/customer/activate" \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "reference": "dp_cust_iovciv7ovnw1qcx"
  }'

On success, the response returns the updated customer object with isBlacklisted set to false.

Note

Blacklisting a customer only prevents them from making transactions using the blacklisted customer account. Atlas has no control over malicious customers who create new customer accounts using different details.

Handling virtual account deposits

When a customer deposits money into their virtual account, the amount is settled into your business' wallet and Atlas sends an IN_FLOW_SUCCESS_EVENT webhook to your configured endpoint.

If you need to map deposits to customers, the webhook payload includes transaction details that let you identify which customer made the deposit. The recipient object on the IN_FLOW_SUCCESS_EVENT payload's data identifies the account that received the inflow, which tells you whether the deposit landed in your business wallet or in a customer's dedicated virtual account:

recipient
{
  "accountName": "Jane Doe",
  "accountNumber": "3769210226"
}

Check recipient.accountNumber against the dedicated virtual accounts (DVAs) you assigned to your customers:

  • If it matches a customer's DVA, credit that customer's account on your system.
  • If it does not match any customer's DVA, the funds were paid into one of your business's own virtual accounts instead. Match recipient.accountNumber against the list or retrieve endpoints to identify which one, and record the deposit accordingly.

Always verify the webhook to ensure it came from Atlas.

How is this guide?

Last updated on

On this page