ecomone developers
Open Ecomone
Docs / API reference / Customers

Customers

Customers are not a separate table: they are aggregated from the shop's orders by lower-cased e-mail.

List customers#

GET/api/public/v1/customerscustomers:read

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

limitinteger

Page size. Clamped to 1..200. Non-numeric values fall back to the default. Default: 50.

cursorstring (ISO 8601)

next_cursor of the previous page (a last_order_at value). Returns customers with last_order_at strictly before it.

searchstring

Case-insensitive substring match on e-mail or name (applied after aggregation).

shop_iduuid

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

dataarray

Customers.

next_cursorstring|null

last_order_at of the last customer when more exist.

data[].emailstring

Lower-cased e-mail; the customer identity (no separate customer table).

data[].namestring|null

Name from the most recent order.

data[].phonestring|null

Phone from the most recent order.

data[].currencystring|null

Currency of the first order encountered (the most recent one, since orders are processed newest first).

data[].orders_countinteger

Number of orders (all statuses).

data[].total_spent_centsinteger

Sum of total_cents of orders whose status is exactly 'paid' or 'fulfilled' (shipped/delivered orders are NOT counted - see notes).

data[].first_order_attimestamp

Earliest order.

data[].last_order_attimestamp

Latest order; pagination key for the list.

data[].created_attimestamp

Same as first_order_at.

Errors

401unauthorized

Any endpoint. Response carries header WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource".

403forbidden

Scope check per endpoint (and per body field on PATCH /orders/:id).

403forbidden

shop_id query parameter names a shop outside the credential's reach.

400shop_required

Multi-shop OAuth token without shop_id.

404not_found

Any endpoint when the resolved shop has active=false.

429rate_limited

Any endpoint. Header Retry-After (seconds until the next minute bucket).

500server_error

Any endpoint.

Try itNot authorized
Request
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"
200Response
{
  "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#

GET/api/public/v1/customers/{id}customers:read

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

idstring (e-mail, URL-encoded)required

Customer e-mail address.

Query parameters

shop_iduuid

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

data.emailstring

Lower-cased e-mail; the customer identity (no separate customer table).

data.namestring|null

Name from the most recent order.

data.phonestring|null

Phone from the most recent order.

data.currencystring|null

Currency of the first order encountered (the most recent one, since orders are processed newest first).

data.orders_countinteger

Number of orders (all statuses).

data.total_spent_centsinteger

Sum of total_cents of orders whose status is exactly 'paid' or 'fulfilled' (shipped/delivered orders are NOT counted - see notes).

data.first_order_attimestamp

Earliest order.

data.last_order_attimestamp

Latest order; pagination key for the list.

data.created_attimestamp

Same as first_order_at.

data.ordersarray

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

400bad_request

Detail endpoints and PATCH.

404not_found

Detail endpoints.

401unauthorized

Any endpoint. Response carries header WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource".

403forbidden

Scope check per endpoint (and per body field on PATCH /orders/:id).

403forbidden

shop_id query parameter names a shop outside the credential's reach.

400shop_required

Multi-shop OAuth token without shop_id.

404not_found

Any endpoint when the resolved shop has active=false.

429rate_limited

Any endpoint. Header Retry-After (seconds until the next minute bucket).

500server_error

Any endpoint.

Try itNot authorized
Request
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"
200Response
{
  "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"
        }
      }
    ]
  }
}

Authorize requests

Requests go straight from your browser to https://api.ecomone.shop. Your credentials stay in this browser tab and are never sent to this documentation site.