Customers
Customers represent the people or organizations who purchase licenses. Each license is associated with a customer within your application.
Customer Properties
| Field | Type | Description |
|---|---|---|
email | string | Customer's email address (unique per app) |
name | string? | Optional customer name |
external_id | string? | External system ID (e.g., Stripe customer ID) |
metadata | object? | JSON object for custom data |
Creating Customers
POST /api/v1/apps/:slug/customers
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/customers \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "jane@example.com",
"name": "Jane Smith",
"external_id": "cus_stripe_123",
"metadata": {
"company": "Acme Corp",
"plan": "annual"
}
}'
# Response
{
"data": {
"id": "cus_abc123",
"email": "jane@example.com",
"name": "Jane Smith",
"external_id": "cus_stripe_123",
"metadata": {"company": "Acme Corp", "plan": "annual"},
"created_at": "2026-01-23T10:00:00Z"
}
} Get or Create
For integration workflows, use the get-or-create pattern to idempotently ensure a customer exists:
POST /api/v1/apps/:slug/customers/get-or-create
$ curl -X POST http://localhost:4000/api/v1/apps/my-app/customers/get-or-create \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "jane@example.com",
"name": "Jane Smith"
}'
# Returns existing customer if email matches,
# otherwise creates a new one Filtering & Pagination
List customers with optional filters:
GET /api/v1/apps/:slug/customers
# Filter by email (partial match)
$ curl "http://localhost:4000/api/v1/apps/my-app/customers?email=jane" \
-H "Authorization: Bearer sk_live_..."
# Filter by external_id (exact match)
$ curl "http://localhost:4000/api/v1/apps/my-app/customers?external_id=cus_stripe_123" \
-H "Authorization: Bearer sk_live_..."
# Paginate results
$ curl "http://localhost:4000/api/v1/apps/my-app/customers?page=1&per_page=20" \
-H "Authorization: Bearer sk_live_..."
# Response includes pagination meta
{
"data": [...],
"meta": {
"total": 150,
"page": 1,
"per_page": 20
}
} Customer Lookup
Retrieve customers by ID, email, or external_id:
GET endpoints
# By ID
$ curl http://localhost:4000/api/v1/apps/my-app/customers/cus_abc123 \
-H "Authorization: Bearer sk_live_..."
# By email
$ curl "http://localhost:4000/api/v1/apps/my-app/customers/by-email?email=jane@example.com" \
-H "Authorization: Bearer sk_live_..."
# By external_id
$ curl "http://localhost:4000/api/v1/apps/my-app/customers/by-external-id?external_id=cus_stripe_123" \
-H "Authorization: Bearer sk_live_..." Cascade Deletion
When a customer is deleted, all their licenses are also deleted. When an app is deleted, all customers and licenses are deleted.
Warning: Customer deletion is permanent and cascades to all licenses. Consider revoking licenses instead if you want to preserve history.