Get Customer
Retrieve a specific customer from your store.
By default the response contains only the customer's base fields. Use the include query
parameter to expand related sections — orders, subscriptions, one-time product access, and a
lifetime-value breakdown — in the same call, so you don't have to stitch together several
requests.
Request
GET /customers/{id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Customer UUID |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
currency | string | Yes | Lowercase ISO currency code (e.g. pln). Scopes the money sections. See Get Store for valid values. |
include | string | No | Comma-separated list of sections to expand. Allowed values: orders, subscriptions, products, ltv. Unknown values are ignored. |
A section that is not requested is returned as null — the key is always present, so the
response shape stays stable. Requesting include=orders therefore leaves subscriptions,
products, and ltv as null.
currency scopes the money sections only: orders, ltv, and the base
lifetime_value / orders_count / first_seen / last_order fields. The subscriptions
and products sections are tracked per store and are returned regardless of currency.
Example Request
curl -X GET "https://cart.easy.tools/api/v1/customers/550e8400-e29b-41d4-a716-446655440010?currency=pln&include=orders,subscriptions,products,ltv" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Success Response (200)
Returns a single customer. The example below requests all sections.
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"name": "Jane Doe",
"email": "buyer@example.com",
"avatar": "https://example.com/avatars/jane.png",
"first_seen": "2026-01-15T10:15:30+00:00",
"last_order": "2026-05-20T14:02:00+00:00",
"orders_count": 4,
"subscriptions_count": 1,
"lifetime_value": 19600,
"currency": "pln",
"orders": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"amount": 4900,
"currency": "pln",
"product_name": "Premium Course",
"created_at": "2026-05-20T14:02:00+00:00"
}
],
"subscriptions": [
{
"id": "550e8400-e29b-41d4-a716-446655440020",
"remote_id": "sub_1QabcDEFghiJKLmn",
"provider": "stripe",
"status": "active",
"variant_name": "Monthly Plan",
"recurring_amount": 4900,
"currency": "pln",
"interval": "month",
"current_period_end": "2026-06-20T14:02:00+00:00",
"active_until": null,
"is_delegated": false,
"created_at": "2026-01-20T14:02:00+00:00"
}
],
"products": [
{
"id": "550e8400-e29b-41d4-a716-446655440030",
"product_name": "Premium Course",
"variant_name": "Lifetime",
"active_until": null,
"is_delegated": false,
"created_at": "2026-01-20T14:02:00+00:00"
}
],
"ltv": {
"gross": 24500,
"refunded": 4900,
"net": 19600,
"currency": "pln"
}
}
A lean read (no include) returns the base fields with every section set to null:
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"name": "Jane Doe",
"email": "buyer@example.com",
"avatar": "https://example.com/avatars/jane.png",
"first_seen": "2026-01-15T10:15:30+00:00",
"last_order": "2026-05-20T14:02:00+00:00",
"orders_count": 4,
"subscriptions_count": 1,
"lifetime_value": 19600,
"currency": "pln",
"orders": null,
"subscriptions": null,
"products": null,
"ltv": null
}
Response Fields
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | No | Unique identifier for the customer (UUID) |
name | string | Yes | Customer full name |
email | string | No | Customer email |
avatar | string | Yes | Avatar URL |
first_seen | string | Yes | When the customer first ordered, in the requested currency (ISO 8601 format) |
last_order | string | Yes | When the customer last ordered, in the requested currency (ISO 8601 format) |
orders_count | integer | No | Number of completed orders in the requested currency |
subscriptions_count | integer | No | Number of active (non-cancelled) subscriptions. Tracked per store, not per currency. |
lifetime_value | integer | Yes | Net lifetime value in minor units (payments minus refunds), in the requested currency |
currency | string | No | Lowercase ISO currency code the money fields are scoped to |
orders | array | Yes | The customer's orders in the requested currency. null unless orders is included. |
subscriptions | array | Yes | The customer's subscriptions. null unless subscriptions is included. |
products | array | Yes | The customer's one-time product access. null unless products is included. |
ltv | object | Yes | Lifetime-value breakdown. null unless ltv is included. |
orders[]
Scoped to the requested currency.
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | No | Order identifier (UUID) |
status | string | Yes | Order status: created, awaiting_payment, processing, completed, canceled, or refunded. |
amount | integer | No | Order total in minor units |
currency | string | No | Lowercase ISO currency code |
product_name | string | Yes | Primary product name, cached at purchase time |
created_at | string | No | When the order was created (ISO 8601 format) |
subscriptions[]
Tracked per store (currency-independent). variant_name and currency come from the related
price.
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | No | Subscription identifier (UUID) |
remote_id | string | Yes | The provider's own subscription id (e.g. the Stripe subscription id) |
provider | string | No | Payment provider the subscription lives in. Currently always stripe. |
status | string | Yes | Subscription status: active, trialing, past_due, canceled, incomplete, incomplete_expired, or unpaid. Null for statuses outside this set. |
variant_name | string | Yes | Related price (variant) name |
recurring_amount | integer | Yes | Recurring charge in minor units |
currency | string | Yes | Currency of the related price |
interval | string | Yes | Billing interval (e.g. "month", "year") |
current_period_end | string | Yes | End of the current billing period (ISO 8601 format) |
active_until | string | Yes | When access ends (ISO 8601 format) |
is_delegated | boolean | No | Whether access was granted by delegation rather than purchase |
created_at | string | No | When the subscription was created (ISO 8601 format) |
products[]
One-time product access, tracked per store (currency-independent).
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | No | Product access identifier (UUID) |
product_name | string | Yes | Related product name |
variant_name | string | Yes | Related price (variant) name |
active_until | string | Yes | When access expires (ISO 8601 format). Null means lifetime access. |
is_delegated | boolean | No | Whether access was granted by delegation rather than purchase |
created_at | string | No | When access was granted (ISO 8601 format) |
ltv
The breakdown behind the lifetime_value scalar, scoped to the requested currency.
refunded is the slice of gross that was returned, and net (= gross − refunded) equals
the top-level lifetime_value.
| Field | Type | Nullable | Description |
|---|---|---|---|
gross | integer | No | Total paid in minor units (sum of payments) |
refunded | integer | No | Total refunded in minor units |
net | integer | No | gross − refunded; equals the top-level lifetime_value |
currency | string | No | Lowercase ISO currency code |
Error Responses
Bad Request (400)
{
"message": "Invalid customer ID"
}
{
"message": "A valid currency query parameter is required"
}
Customer Not Found (404)
{
"message": "Customer with ID <UUID> not found"
}
Unauthorized (401)
{
"message": "Unauthenticated."
}