Customers
Customers are not a separate table: they are aggregated from the shop's orders by lower-cased e-mail.
List customers#
List customers aggregated from orders, most recent buyer first. Loads the shop's 5,000 most recent orders that have an e-mail, groups them by lower-cased e-mail and sorts by last_order_at descending. Customers whose orders are all older than the 5,000 most recent orders do not appear.
Query parameters
Page size. Clamped to 1..200. Non-numeric values fall back to the default. Default: 50.
next_cursor of the previous page (a last_order_at value). Returns customers with last_order_at strictly before it.
Case-insensitive substring match on e-mail or name (applied after aggregation).
Only for OAuth tokens that cover several shops: the shop to query. Must be one of the token's shops (else 403 forbidden). Required when the token covers more than one shop (else 400 shop_required). Optional for API keys (a key belongs to exactly one shop; any other value returns 403).
Response fields
Customers.
last_order_at of the last customer when more exist.
Lower-cased e-mail; the customer identity (no separate customer table).
Name from the most recent order.
Phone from the most recent order.
Currency of the first order encountered (the most recent one, since orders are processed newest first).
Number of orders (all statuses).
Sum of total_cents of orders whose status is exactly 'paid' or 'fulfilled' (shipped/delivered orders are NOT counted - see notes).
Earliest order.
Latest order; pagination key for the list.
Same as first_order_at.
Errors
Any endpoint. Response carries header WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource".
Scope check per endpoint (and per body field on PATCH /orders/:id).
shop_id query parameter names a shop outside the credential's reach.
Multi-shop OAuth token without shop_id.
Any endpoint when the resolved shop has active=false.
Any endpoint. Header Retry-After (seconds until the next minute bucket).
Any endpoint.
curl "https://api.ecomone.shop/api/public/v1/customers?limit=10" \
-H "X-Api-Key: $ECOMONE_API_KEY" \
-H "X-Api-Secret: $ECOMONE_API_SECRET"const res = await fetch("https://api.ecomone.shop/api/public/v1/customers?limit=10", {
method: "GET",
headers: {
"X-Api-Key": process.env.ECOMONE_API_KEY,
"X-Api-Secret": process.env.ECOMONE_API_SECRET,
},
});
if (!res.ok) throw new Error((await res.json()).message);
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.ecomone.shop/api/public/v1/customers?limit=10",
headers={
"X-Api-Key": os.environ["ECOMONE_API_KEY"],
"X-Api-Secret": os.environ["ECOMONE_API_SECRET"],
},
timeout=30,
)
res.raise_for_status()
data = res.json()["data"]{
"data": [
{
"email": "jane.doe@example.com",
"name": "Jane Doe",
"phone": "+41 79 000 00 00",
"currency": "CHF",
"orders_count": 4,
"total_spent_cents": 24560,
"first_order_at": "2026-02-11T08:41:00.000Z",
"last_order_at": "2026-08-28T09:13:58.000Z",
"created_at": "2026-02-11T08:41:00.000Z"
}
],
"next_cursor": "2026-08-28T09:13:58.000Z"
}Retrieve a customer#
Retrieve one customer by e-mail, with order history. :id is the URL-encoded e-mail address. It is lower-cased and matched exactly against orders.customer_email (up to 500 most recent orders).
Path parameters
Customer e-mail address.
Query parameters
Only for OAuth tokens that cover several shops: the shop to query. Must be one of the token's shops (else 403 forbidden). Required when the token covers more than one shop (else 400 shop_required). Optional for API keys (a key belongs to exactly one shop; any other value returns 403).
Response fields
Lower-cased e-mail; the customer identity (no separate customer table).
Name from the most recent order.
Phone from the most recent order.
Currency of the first order encountered (the most recent one, since orders are processed newest first).
Number of orders (all statuses).
Sum of total_cents of orders whose status is exactly 'paid' or 'fulfilled' (shipped/delivered orders are NOT counted - see notes).
Earliest order.
Latest order; pagination key for the list.
Same as first_order_at.
The customer's orders, newest first, max 500: [{id, order_number, status, fulfillment_status, total_cents, currency, created_at, updated_at, items, shipping_address, customer_name, customer_phone, line_items, shipping_address_normalized}]. line_items and shipping_address_normalized have the same shape as on GET /orders/{id}.
Errors
Detail endpoints and PATCH.
Detail endpoints.
Any endpoint. Response carries header WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource".
Scope check per endpoint (and per body field on PATCH /orders/:id).
shop_id query parameter names a shop outside the credential's reach.
Multi-shop OAuth token without shop_id.
Any endpoint when the resolved shop has active=false.
Any endpoint. Header Retry-After (seconds until the next minute bucket).
Any endpoint.
curl "https://api.ecomone.shop/api/public/v1/customers/anna.muster@example.com" \
-H "X-Api-Key: $ECOMONE_API_KEY" \
-H "X-Api-Secret: $ECOMONE_API_SECRET"const res = await fetch("https://api.ecomone.shop/api/public/v1/customers/anna.muster@example.com", {
method: "GET",
headers: {
"X-Api-Key": process.env.ECOMONE_API_KEY,
"X-Api-Secret": process.env.ECOMONE_API_SECRET,
},
});
if (!res.ok) throw new Error((await res.json()).message);
const { data } = await res.json();import os, requests
res = requests.get(
"https://api.ecomone.shop/api/public/v1/customers/anna.muster@example.com",
headers={
"X-Api-Key": os.environ["ECOMONE_API_KEY"],
"X-Api-Secret": os.environ["ECOMONE_API_SECRET"],
},
timeout=30,
)
res.raise_for_status()
data = res.json()["data"]{
"data": {
"email": "jane.doe@example.com",
"name": "Jane Doe",
"phone": "+41 79 000 00 00",
"currency": "CHF",
"orders_count": 4,
"total_spent_cents": 24560,
"first_order_at": "2026-02-11T08:41:00.000Z",
"last_order_at": "2026-08-28T09:13:58.000Z",
"created_at": "2026-02-11T08:41:00.000Z",
"orders": [
{
"id": "9f1c2b7e-4a55-4d1f-9b62-1c0a3f6d8e21",
"order_number": 1042,
"status": "paid",
"fulfillment_status": "unfulfilled",
"total_cents": 8590,
"currency": "CHF",
"created_at": "2026-08-28T09:13:58.000Z",
"updated_at": "2026-08-28T09:14:25.000Z",
"items": [
{
"id": "3b8b1f0a-1d2c-4f34-8a7c-6e2f9b4d5c11",
"title": "Linen Shirt White",
"price_cents": 3950,
"qty": 2,
"variant_label": "M / White",
"sku": "LS-W-M",
"variants": {
"Size": "M",
"Color": "White"
}
}
],
"shipping_address": {
"name": "Jane Doe",
"address1": "Example Street 1",
"zip": "8000",
"city": "Zurich",
"country": "CH"
},
"customer_name": "Jane Doe",
"customer_phone": "+41 79 000 00 00",
"line_items": [
{
"id": "9f1c2b7e-4a55-4d1f-9b62-1c0a3f6d8e21:0",
"product_id": "3b8b1f0a-1d2c-4f34-8a7c-6e2f9b4d5c11",
"variant_id": "v1",
"title": "Linen Shirt White",
"variant_title": "M / White",
"sku": "LS-W-M",
"quantity": 2,
"unit_price_cents": 3950,
"total_cents": 7900,
"requires_shipping": true
}
],
"shipping_address_normalized": {
"name": "Jane Doe",
"company": null,
"line1": "Example Street 1",
"line2": null,
"postal_code": "8000",
"city": "Zurich",
"state": null,
"country": "CH",
"phone": "+41 79 000 00 00"
}
}
]
}
}