A valid request URL is required to generate request examples{
"referenceDate": "2026-07-28T09:00:00.000Z",
"baseTotal": 15,
"counts": {
"champions": 2,
"loyal": 3,
"at_risk": 1,
"new": 8,
"lost": 1
},
"items": [
{
"customerId": "cust-1",
"name": "Camille Renard",
"email": "camille.renard@example.com",
"phone": null,
"tier": "Or",
"postalCode": "75011",
"optIn": true,
"metrics": {
"recencyDays": 14,
"frequency": 17,
"monetaryCents": 84250
},
"scores": {
"recency": 5,
"frequency": 5,
"monetary": 5
},
"segment": "champions"
}
],
"total": 2,
"page": 1,
"pageSize": 20,
"pageCount": 1
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123,
"fieldErrors": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}Report the customer base by RFM segment (segment client)
Computes an RFM (Recency / Frequency / Monetary) segmentation over the whole customer base and returns the per-bucket population plus ONE PAGE of the individual customer rows. Reach for this to answer ‘who should I target’ or ‘how healthy is the base’; use listCustomers when you just need the directory. Buckets: champions (recent, frequent, high value), loyal, at_risk (was good, has gone quiet), new (never purchased) and lost. The optional segment / tier / postalCodePrefix / optIn / min-maxMonetaryCents / min-maxFrequency / min-maxRecencyDays facets are the saved-segment predicate — the same criteria a campaign’s custom list is built from — combined as AND. They narrow the returned rows ONLY: baseTotal and counts always describe the whole base, so a bucket keeps its true size. Mind the two totals: total counts the rows the PREDICATE matched across all pages (pair it with page/pageSize, default 20, max 100, and stop at pageCount), while baseTotal is the size of the base itself. monetaryCents is integer cents; recencyDays is null for a customer who never bought, and the recency facets never match those customers (target them with segment=new). Feed the same facets to createCampaign to target this audience — but note the campaign re-evaluates them at send, so this response is the audience NOW, not the audience the send will resolve. To size a predicate WITHOUT pulling contact details, request pageSize=1 and read total (the match count) together with referenceDate (the instant it was computed). Each row carries the customer’s raw email/phone, so these are contact details: narrow with the facets rather than walking every page.
A valid request URL is required to generate request examples{
"referenceDate": "2026-07-28T09:00:00.000Z",
"baseTotal": 15,
"counts": {
"champions": 2,
"loyal": 3,
"at_risk": 1,
"new": 8,
"lost": 1
},
"items": [
{
"customerId": "cust-1",
"name": "Camille Renard",
"email": "camille.renard@example.com",
"phone": null,
"tier": "Or",
"postalCode": "75011",
"optIn": true,
"metrics": {
"recencyDays": 14,
"frequency": 17,
"monetaryCents": 84250
},
"scores": {
"recency": 5,
"frequency": 5,
"monetary": 5
},
"segment": "champions"
}
],
"total": 2,
"page": 1,
"pageSize": 20,
"pageCount": 1
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123,
"fieldErrors": [
{
"field": "<string>",
"message": "<string>"
}
]
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}{
"error": {
"code": "VALIDATION_FAILED",
"message": "<string>",
"statusCode": 123
}
}Authorizations
Authorization: Bearer <token>. Accepts EITHER a Keycloak access token (scopes-in-token) OR an opaque POS session token; both resolve to the same pos.* scope vocabulary the route guards enforce.
Query Parameters
1-based page index to return. Defaults to 1.
1 <= x <= 9007199254740991Rows per page, 1..100. Defaults to 20.
1 <= x <= 100Restrict the returned rows to one RFM bucket (segment client), e.g. champions.
champions, loyal, at_risk, new, lost Restrict the returned rows to one loyalty-tier label, e.g. Or.
1Restrict the returned rows to customers whose postal code starts with this prefix (75 targets all of Paris). Customers with no postal code on file never match.
1Restrict the returned rows to customers with this marketing opt-in state.
true, false Restrict the returned rows to customers at or above this lifetime spend, in cents.
^\d+$Restrict the returned rows to customers at or below this lifetime spend, in cents.
^\d+$Restrict the returned rows to customers with at least this many finalized purchases.
^\d+$Restrict the returned rows to customers with at most this many finalized purchases.
^\d+$Restrict the returned rows to customers whose last purchase is at least this many days old (the lapsed / win-back facet). Customers who never purchased never match.
^\d+$Restrict the returned rows to customers who purchased within this many days (the recently-active facet). Customers who never purchased never match.
^\d+$Response
Whole-base per-segment counts plus one page of the (optionally filtered) rows.
Whole-base per-segment counts plus one page of the (optionally filtered) rows.
The rows on this page, in the query's sort order.
Show child attributes
Show child attributes
Total rows matching the filter across ALL pages, not just this one.
0 <= x <= 9007199254740991The 1-based page number served.
0 < x <= 9007199254740991Rows requested per page.
0 < x <= 9007199254740991Total number of pages; stop walking when page reaches it.
0 <= x <= 9007199254740991-9007199254740991 <= x <= 9007199254740991Show child attributes
Show child attributes

