Backend API: Manage customer groups
Edit on GitHubThis document describes how to manage customer groups using the Backend API. You can use these endpoints to build Back Office extensions, CRM and marketing automation integrations, and segmentation pipelines.
A customer group is a named segment of customers. Discounts and other shop rules target a group, so moving a customer in or out of one changes what that customer sees. A customer can belong to any number of groups at the same time.
Customer groups are addressed by uuid. The internal database identifier is never exposed. The UUID is derived from the group id, so it is stable for the lifetime of the group — renaming the group does not change it.
The group itself and its members are managed through two resources: /customer-groups carries the name and description, and /customer-groups/{uuid}/customers carries the members.
Installation
These endpoints are provided by API Platform. To install and enable it, see Enable API Platform.
The uuid column is new on spy_customer_group, and it is stamped only when a row is saved. Reads never backfill it.
If your installation had customer groups before the upgrade, generate the missing UUIDs once:
docker/sdk console uuid:generate CustomerGroup spy_customer_group
A single row with a NULL UUID makes GET /customer-groups fail with 400 for the whole collection, not only for that row. The command is idempotent — it touches only the rows where the column is still NULL — so it is safe to repeat and safe to add to a deployment recipe after propel:migrate.
Retrieve customer groups
To retrieve a paginated collection of customer groups, send the request:
GET /customer-groups
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
| Accept | application/vnd.api+json | Media type of the response. If you omit this header, the endpoint answers with application/vnd.api+json. |
| QUERY PARAMETER | DESCRIPTION | POSSIBLE VALUES |
|---|---|---|
| page[limit] | Maximum number of items to return per page. | From 1 to any. Defaults to 10. |
| page[offset] | Number of items to skip before the page begins. | From 0 to any. Defaults to 0. |
| q | Free-text search, matched against the name and the description of the group. A group matches when either of them matches. | Any string. |
| filter[customer-groups.name] | Filters the collection by an exact name. The comparison ignores case. | Any group name. |
| sort | Sorts the collection by the given field. Prefix a field with - to sort in descending order. Separate several fields with a comma. |
name, createdAt |
The free-text search and the name filter are combined with AND, so each one you add narrows the result further. A name that no group uses returns an empty collection rather than an error.
Sorting by a field that is not on the list returns 400 with the error code 1203, and the error message names the supported fields. When you pass several fields, the second one decides the order only where the first one ties.
The members of a group are neither part of this response nor available as an include. To read them, see Retrieve the customers of a customer group.
| REQUEST | USAGE |
|---|---|
GET https://glue-backend.mysprykershop.com/customer-groups |
Retrieve the first page of customer groups. |
GET https://glue-backend.mysprykershop.com/customer-groups?page[limit]=50&page[offset]=100 |
Retrieve 50 customer groups, skipping the first 100. |
GET https://glue-backend.mysprykershop.com/customer-groups?q=wholesale |
Retrieve customer groups whose name or description matches wholesale. |
GET https://glue-backend.mysprykershop.com/customer-groups?filter[customer-groups.name]=Wholesale partners |
Retrieve the customer group named Wholesale partners. |
GET https://glue-backend.mysprykershop.com/customer-groups?sort=-createdAt |
Retrieve customer groups, newest first. |
Response
Response sample: retrieve customer groups
{
"data": [
{
"type": "customer-groups",
"id": "4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5",
"attributes": {
"uuid": "4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5",
"name": "Wholesale partners",
"description": "Customers eligible for wholesale pricing tiers.",
"createdAt": "2026-09-10T08:15:00+00:00"
},
"links": {
"self": "https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5"
}
},
{
"type": "customer-groups",
"id": "7d3c5f81-6a24-5e93-8c07-1b2f4a6d9e30",
"attributes": {
"uuid": "7d3c5f81-6a24-5e93-8c07-1b2f4a6d9e30",
"name": "Tier one",
"description": null,
"createdAt": "2026-09-12T11:42:31+00:00"
},
"links": {
"self": "https://glue-backend.mysprykershop.com/customer-groups/7d3c5f81-6a24-5e93-8c07-1b2f4a6d9e30"
}
}
],
"meta": {
"pagination": {
"numFound": 12,
"currentPage": 1,
"maxPage": 2,
"currentItemsPerPage": 10
}
},
"links": {
"self": "https://glue-backend.mysprykershop.com/customer-groups",
"first": "https://glue-backend.mysprykershop.com/customer-groups?page[limit]=10&page[offset]=0",
"last": "https://glue-backend.mysprykershop.com/customer-groups?page[limit]=10&page[offset]=10",
"next": "https://glue-backend.mysprykershop.com/customer-groups?page[limit]=10&page[offset]=10"
}
}
| ATTRIBUTE | TYPE | DESCRIPTION |
|---|---|---|
| uuid | String | Public unique customer group identifier. Addresses the group in every operation. |
| name | String | Name of the customer group. Unique across all customer groups. |
| description | String | Free-text note about what the group is for. |
| createdAt | String | Date and time the group was created, in ISO 8601. Read-only. |
A collection response carries its pagination summary in the top-level meta.pagination object:
| ATTRIBUTE | TYPE | DESCRIPTION |
|---|---|---|
| meta.pagination.numFound | Integer | Total number of items found. |
| meta.pagination.currentPage | Integer | Current page number. |
| meta.pagination.maxPage | Integer | Total number of pages. |
| meta.pagination.currentItemsPerPage | Integer | Number of items per page. |
The top-level links object carries the first and last links, plus prev and next when those pages exist. Each link repeats the query parameters of the request and rewrites the window as page[limit] and page[offset], so you can follow it as it is.
Retrieve a customer group
To retrieve a single customer group, send the request:
GET /customer-groups/{{customer_group_uuid}}
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group to retrieve. To get it, retrieve customer groups. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
Request sample: GET https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5
Response
The response contains the same attributes as Retrieve customer groups, without the meta.pagination object.
If no group matches the UUID, the endpoint returns 404 with the error code 1222.
Create a customer group
To create a customer group, send the request:
POST /customer-groups
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
| Content-Type | application/vnd.api+json | ✓ | Media type of the request body. |
You can create an empty group and fill it later, or assign its members in the same request.
Request sample: create an empty customer group
POST https://glue-backend.mysprykershop.com/customer-groups
{
"data": {
"type": "customer-groups",
"attributes": {
"name": "Wholesale partners",
"description": "Customers eligible for wholesale pricing tiers."
}
}
}
Request sample: create a customer group with members
POST https://glue-backend.mysprykershop.com/customer-groups
{
"data": {
"type": "customer-groups",
"attributes": {
"name": "Wholesale partners",
"description": "Customers eligible for wholesale pricing tiers.",
"customerReferences": [
"DE--1",
"DE--2"
]
}
}
}
| ATTRIBUTE | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| name | String | ✓ | Name of the customer group. Must not be blank, must not exceed 70 characters, and must not already be taken. |
| description | String | Free-text note about what the group is for. Must not exceed 255 characters. | |
| customerReferences | Array | References of the customers to assign to the new group. At most 1000 per request, with no duplicates, and each reference must not exceed 255 characters. Omit it, or send an empty array, to create the group empty. |
Names are compared without regard to case: with a group named Wholesale partners already present, WHOLESALE PARTNERS is rejected with 422 and the error code 1223.
Every customer reference must belong to an existing customer. If any of them is unknown, the endpoint rejects the whole request and creates no group. The response returns 422 with the error code 1224 and one errors[] entry per unknown reference, so a single request tells you every reference you need to correct.
The customer accounts themselves are neither read back nor modified, and no mail is sent.
customerReferences is capped at 1000 entries per request. To fill a larger group, create it with the first batch and add the rest with Add customers to a customer group, which you can call as often as you need.
The cap applies to writing only. Retrieve the customers of a customer group is paginated, so it is not limited to 1000.
Response
A successful request returns the 201 Created status code.
Response sample:
{
"data": {
"type": "customer-groups",
"id": "4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5",
"attributes": {
"uuid": "4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5",
"name": "Wholesale partners",
"description": "Customers eligible for wholesale pricing tiers.",
"createdAt": "2026-09-24T09:05:12+00:00"
},
"links": {
"self": "https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5"
}
}
}
customerReferences is write-only and is never returned. To confirm the assignment, see Retrieve the customers of a customer group.
Edit a customer group
To update a customer group, send the request:
PATCH /customer-groups/{{customer_group_uuid}}
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group to update. To get it, retrieve customer groups. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
| Content-Type | application/vnd.api+json | ✓ | Media type of the request body. |
Request sample: PATCH https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5
{
"data": {
"type": "customer-groups",
"id": "4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5",
"attributes": {
"name": "Wholesale partners EU",
"description": "Customers eligible for wholesale pricing tiers in the EU."
}
}
}
| ATTRIBUTE | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| name | String | New name of the customer group. Must not be blank, must not exceed 70 characters, and must not be taken by another group. | |
| description | String | New free-text note about what the group is for. Must not exceed 255 characters. |
The endpoint applies only the attributes present in the payload; every attribute you omit keeps its stored value.
Renaming a group does not change its UUID, so links and integrations that address the group keep working. Sending the group its own current name succeeds and changes nothing. Sending a name another group already uses, in any casing, returns 422 with the error code 1223.
This endpoint ignores customerReferences. Sending it changes nothing, and sending an empty array does not clear the group.
To change who belongs to the group, use the assignment endpoints:
- Add customers to a customer group adds members without removing any.
- Replace the customers of a customer group sets the complete list of members.
- Remove a customer from a customer group removes one member.
Response
The response contains the updated customer group, with the same attributes as Retrieve a customer group.
Delete a customer group
To delete a customer group, send the request:
DELETE /customer-groups/{{customer_group_uuid}}
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group to delete. To get it, retrieve customer groups. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
Request sample: DELETE https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5
Response
A successful request returns the 204 No Content status code with an empty body.
The assignments of the group go with it. The customers themselves are kept, along with every other group they belong to.
Discounts and other rules that target a deleted group simply stop matching it. They are neither deleted nor rewritten, so a discount can go on running with a condition that can never be met again. Review them after you delete a group.
Retrieve the customers of a customer group
To retrieve a paginated collection of the customers assigned to a group, send the request:
GET /customer-groups/{{customer_group_uuid}}/customers
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group whose members you want to retrieve. To get it, retrieve customer groups. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
| Accept | application/vnd.api+json | Media type of the response. If you omit this header, the endpoint answers with application/vnd.api+json. |
| QUERY PARAMETER | DESCRIPTION | POSSIBLE VALUES |
|---|---|---|
| page[limit] | Maximum number of items to return per page. | From 1 to any. Defaults to 10. |
| page[offset] | Number of items to skip before the page begins. | From 0 to any. Defaults to 0. |
| q | Free-text search, matched against the email address, the first name, and the last name of the member. A member matches when any of them matches. | Any string. |
| sort | Sorts the collection by the given field. Prefix a field with - to sort in descending order. Separate several fields with a comma. |
email, firstName, lastName |
The collection lists only the members of the group in the URL. A customer who belongs to several groups appears in each of them.
Sorting by a field that is not on the list returns 400 with the error code 1203, and the error message names the supported fields.
| REQUEST | USAGE |
|---|---|
GET https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers |
Retrieve the first page of members. |
GET https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers?q=sonia |
Retrieve the members whose email address, first name, or last name matches sonia. |
GET https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers?sort=lastName,firstName |
Retrieve the members, ordered by last name and then by first name. |
Response
Response sample: retrieve the customers of a customer group
{
"data": [
{
"type": "customer-group-customers",
"id": "DE--1",
"attributes": {
"customerReference": "DE--1",
"email": "[email protected]",
"firstName": "Spencor",
"lastName": "Hopkins"
}
},
{
"type": "customer-group-customers",
"id": "DE--2",
"attributes": {
"customerReference": "DE--2",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Smith"
}
}
],
"meta": {
"pagination": {
"numFound": 2,
"currentPage": 1,
"maxPage": 1,
"currentItemsPerPage": 10
}
},
"links": {
"self": "https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers",
"first": "https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers?page[limit]=10&page[offset]=0",
"last": "https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers?page[limit]=10&page[offset]=0"
}
}
| ATTRIBUTE | TYPE | DESCRIPTION |
|---|---|---|
| customerReference | String | Reference of the customer. Addresses the member when you remove it from the group. |
| String | Email address of the member. | |
| firstName | String | First name of the member. |
| lastName | String | Last name of the member. |
All four attributes are read-only. To change customer data, see Backend API: Manage customers.
A collection response carries its pagination summary in the top-level meta.pagination object:
| ATTRIBUTE | TYPE | DESCRIPTION |
|---|---|---|
| meta.pagination.numFound | Integer | Total number of items found. |
| meta.pagination.currentPage | Integer | Current page number. |
| meta.pagination.maxPage | Integer | Total number of pages. |
| meta.pagination.currentItemsPerPage | Integer | Number of items per page. |
The top-level links object carries the first and last links, plus prev and next when those pages exist. Each link repeats the query parameters of the request and rewrites the window as page[limit] and page[offset], so you can follow it as it is.
If no group matches the UUID, the endpoint returns 404 with the error code 1222.
Add customers to a customer group
To add customers to a group without removing the members it already has, send the request:
POST /customer-groups/{{customer_group_uuid}}/customers
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group to add the customers to. To get it, retrieve customer groups. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
| Content-Type | application/vnd.api+json | ✓ | Media type of the request body. |
Request sample: POST https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers
{
"data": {
"type": "customer-group-customers",
"attributes": {
"customerReferences": [
"DE--1",
"DE--2"
]
}
}
}
| ATTRIBUTE | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| customerReferences | Array | ✓ | References of the customers to add. Must contain at least one reference and at most 1000, with no duplicates, and each reference must not exceed 255 characters. |
The members the group already has stay as they are. References that are already members are skipped, so sending the same request twice is safe and changes nothing the second time.
The operation is all-or-nothing: if any reference is unknown, nothing is added, and the response returns 422 with the error code 1224 and one errors[] entry per unknown reference.
The customer accounts themselves are neither read back nor modified, and no mail is sent.
Response
A successful request returns the 204 No Content status code with an empty body. To read the resulting membership, see Retrieve the customers of a customer group.
Replace the customers of a customer group
To set the complete list of members of a group in one call, send the request:
PATCH /customer-groups/{{customer_group_uuid}}/customers
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group whose members you want to replace. To get it, retrieve customer groups. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
| Content-Type | application/vnd.api+json | ✓ | Media type of the request body. |
Request sample: PATCH https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers
{
"data": {
"type": "customer-group-customers",
"attributes": {
"customerReferences": [
"DE--1",
"DE--3"
]
}
}
}
| ATTRIBUTE | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| customerReferences | Array | ✓ | The complete new list of members. At most 1000 references, with no duplicates, and each reference must not exceed 255 characters. An empty array removes every member. |
The references you send become the complete new set of members, so include every customer the group is to keep. Customers missing from the list are removed from the group; their accounts, and their assignments to other groups, stay untouched.
An empty array removes every member and keeps the group itself, which is how you clear a group without deleting it.
The operation is all-or-nothing: if any reference is unknown or the list contains duplicates, the membership stays exactly as it was, and the response returns 422 with the error code 1224 and one errors[] entry per unknown reference. Sending the same list twice leaves the same members.
Unlike a PATCH on the group itself, omitting customerReferences is not a way to leave the membership alone. This operation exists only to set the membership, so a body without it is rejected with 422 rather than read as an empty list. The membership stays as it was.
To leave the membership alone, do not send this request at all.
Response
A successful request returns the 204 No Content status code with an empty body. To read the resulting membership, see Retrieve the customers of a customer group.
Remove a customer from a customer group
To remove one customer from a group, send the request:
DELETE /customer-groups/{{customer_group_uuid}}/customers/{{customer_reference}}
| PATH PARAMETER | DESCRIPTION |
|---|---|
| {{customer_group_uuid}} | UUID of the customer group to remove the customer from. To get it, retrieve customer groups. |
| {{customer_reference}} | Reference of the customer to remove. To get it, retrieve the customers of a customer group. |
Request
| HEADER KEY | HEADER VALUE | REQUIRED | DESCRIPTION |
|---|---|---|---|
| Authorization | string | ✓ | Alphanumeric string that authorizes the Back Office user to send requests to protected resources. Get it by authenticating as a Back Office user. |
Request sample: DELETE https://glue-backend.mysprykershop.com/customer-groups/4b1e6a02-9f37-5c48-b6d1-2e8a70c9f4a5/customers/DE--1
Response
A successful request returns the 204 No Content status code with an empty body.
The customer account is kept, and so is every other group the customer belongs to.
If no group matches the UUID, the endpoint returns 404 with the error code 1222. If the group exists but the customer is not one of its members, the endpoint returns 404 with the error code 1225.
Other management options
- Backend API: Manage customers
- Backend API: Manage customer addresses
- Backend API: Manage customer notes
- Backend API: Manage customer access
- Manage customer groups in the Back Office
- Customer groups overview
Possible errors
| CODE | REASON |
|---|---|
| 901 | The request body failed schema validation. Each error names the rejected attribute in source.pointer. |
| 1202 | The customer group request was rejected by a validation rule that has no more specific code. |
| 1203 | The sort parameter names a field that the collection does not support. |
| 1222 | No customer group matches the given UUID. |
| 1223 | The name is already taken by another customer group. Names are compared without regard to case. |
| 1224 | No customer matches one of the given customerReferences. Each unknown reference gets its own errors[] entry. |
| 1225 | The customer is not a member of the customer group. |
To view generic errors, see API errors and troubleshooting.
Thank you!
For submitting the form