Guides
Customers
Learn how to create, manage, and query customers in NovaBilling.
Customer Management
Customers are the core entity in NovaBilling. Every subscription, invoice, and payment is associated with a customer. This guide covers all customer operations in detail.
Customer Object
A customer record contains the following fields:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (e.g., cust_x1y2z3) |
externalId | string | Your application's user ID for cross-referencing |
email | string | Customer's email address (unique per tenant) |
name | string | Customer's full name |
country | string | ISO 3166-1 alpha-2 country code |
currency | string | Preferred currency (ISO 4217) |
status | string | Customer status: active or inactive |
metadata | object | Custom key-value pairs for your application data |
totalSpent | number | Lifetime total amount paid |
activeSubscriptions | number | Count of active subscriptions |
createdAt | string | ISO 8601 creation timestamp |
updatedAt | string | ISO 8601 last update timestamp |
Creating Customers
Create a customer with at minimum an email address and name.
curl -X POST http://localhost:3000/api/customers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_live_a1b2c3d4..." \
-d '{
"externalId": "usr_98765",
"email": "sarah@kampaltech.ug",
"name": "Nakato Sarah",
"country": "UG",
"currency": "UGX",
"metadata": {
"userId": "usr_98765",
"accountType": "business"
}
}'
import { NovaBillingClient } from 'novabilling';
const client = new NovaBillingClient({ token: 'sk_live_a1b2c3d4...' });
const customer = await client.customers.create({
externalId: 'usr_98765',
email: 'sarah@kampaltech.ug',
name: 'Nakato Sarah',
country: 'UG',
currency: 'UGX',
metadata: {
userId: 'usr_98765',
accountType: 'business'
}
});
console.log('Customer created:', customer.id);
from novabilling import NovaBilling
client = NovaBilling(token="sk_live_a1b2c3d4...")
customer = client.customers.create(
external_id="usr_98765",
email="sarah@kampaltech.ug",
name="Nakato Sarah",
country="UG",
currency="UGX",
metadata={
"user_id": "usr_98765",
"account_type": "business"
}
)
print(f"Customer created: {customer.id}")
Customer email addresses must be unique within your tenant. Attempting to create a customer with an existing email will return a
409 Conflict error.Updating Customers
Update any customer field. Only the fields you provide will be updated; omitted fields remain unchanged.
curl -X PATCH http://localhost:3000/api/customers/cust_x1y2z3 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk_live_a1b2c3d4..." \
-d '{
"name": "Nakato Sarah Williams",
"metadata": {
"userId": "usr_98765",
"accountType": "enterprise",
"upgradeDate": "2025-03-01"
}
}'
const updated = await client.customers.update('cust_x1y2z3', {
name: 'Nakato Sarah Williams',
metadata: {
userId: 'usr_98765',
accountType: 'enterprise',
upgradeDate: '2025-03-01'
}
});
console.log('Updated:', updated.name);
updated = client.customers.update(
"cust_x1y2z3",
name="Nakato Sarah Williams",
metadata={
"user_id": "usr_98765",
"account_type": "enterprise",
"upgrade_date": "2025-03-01"
}
)
print(f"Updated: {updated.name}")
The
metadata field is replaced entirely on update. If you want to add a new key while preserving existing ones, include all existing metadata keys in the update request.Listing and Filtering Customers
Retrieve customers with pagination, search, and sorting.
Basic Listing
curl -X GET "http://localhost:3000/api/customers?page=1&limit=20" \
-H "Authorization: Bearer sk_live_a1b2c3d4..."
const customers = await client.customers.list({
page: 1,
limit: 20
});
console.log(`Showing ${customers.data.length} of ${customers.total} customers`);
customers = client.customers.list(page=1, limit=20)
print(f"Showing {len(customers.data)} of {customers.total} customers")
Search by Name or Email
curl -X GET "http://localhost:3000/api/customers?search=sarah&page=1&limit=20" \
-H "Authorization: Bearer sk_live_a1b2c3d4..."
const results = await client.customers.list({
search: 'sarah',
page: 1,
limit: 20
});
for (const customer of results.data) {
console.log(`${customer.name} - ${customer.email}`);
}
results = client.customers.list(search="sarah", page=1, limit=20)
for customer in results.data:
print(f"{customer.name} - {customer.email}")
Getting Customer Details
curl -X GET http://localhost:3000/api/customers/cust_x1y2z3 \
-H "Authorization: Bearer sk_live_a1b2c3d4..."
const customer = await client.customers.get('cust_x1y2z3');
console.log(JSON.stringify(customer, null, 2));
customer = client.customers.get("cust_x1y2z3")
print(customer)
Deleting Customers
Delete a customer and all their associated data. This action is irreversible.
curl -X DELETE http://localhost:3000/api/customers/cust_x1y2z3 \
-H "Authorization: Bearer sk_live_a1b2c3d4..."
await client.customers.delete('cust_x1y2z3');
console.log('Customer deleted');
client.customers.delete("cust_x1y2z3")
print("Customer deleted")
Deleting a customer will cancel all active subscriptions and void all unpaid invoices. This action cannot be undone. Make sure to cancel subscriptions gracefully before deleting a customer if you need to process final invoices.
Best Practices
- Use metadata for application data -- Store your application's user IDs, account types, and other relevant data in the metadata field. This makes it easy to correlate NovaBilling customers with your application records.
- Store customer IDs -- Save the NovaBilling customer ID (
cust_...) in your application's user record for easy lookups. - Validate email uniqueness -- The API enforces email uniqueness per tenant. Handle
409 Conflicterrors gracefully in your integration. - Set country and currency -- Always provide the customer's country and preferred currency for accurate billing and payment routing.