# Customers APIs overview

**How to work with the APIs for customers.**

This page describes rules that apply across the Customers APIs. For what Customers, Customer Groups, and Customer Search are and how they behave, see the [Customers overview](/api/customers-overview.md).

## APIs in this topic

| Resource | Purpose | Reference |
| --- | --- | --- |
| Customers | Represent a person purchasing Products. | [Customers](/api/projects/customers.md) |
| Customer Search | Search across a large number of Customers in a Project, for back-office use cases. | [Customer Search](/api/projects/customer-search.md) |
| Customer Groups | Assign special prices to specific products based on a Customer Group. | [Customer Groups](/api/projects/customerGroups.md) |
| Me endpoints | Access the resources of a single Customer. | [Me endpoints overview](/api/me-endpoints-overview.md) |

## Data model

### Global versus Store-specific Customers

For what global and Store-specific Customers are and how they differ, see [Customers overview](/api/customers-overview.md#global-versus-store-specific-customers).

A Customer is considered global when the [Customer](/search.md?urn=ctp:api:type:Customer) `stores` field is empty.

A Customer is considered Store-specific, when the [Customer](/search.md?urn=ctp:api:type:Customer) `stores` field contains one or more [Stores](/api/projects/stores.md).

Two different authorization flows are used depending on the type of Customer:

- [Password Flow for global Customers](/api/authorization.md#password-flow-for-global-customers)
- [Password Flow for Customers in a Store](/api/authorization.md#password-flow-for-customers-in-a-store)

### Customer addresses

A [Customer](/search.md?urn=ctp:api:type:Customer) stores all known addresses in a single `addresses` array. Each address entry has an auto-generated `id` and, optionally, a user-defined `key`. The platform uses the `id` to reference addresses from dedicated fields (`shippingAddressIds`, `billingAddressIds`, `defaultShippingAddressId`, `defaultBillingAddressId`) to express whether an address is used for shipping, billing, or as a default.

This ID-reference model means the same address is stored only once and can play multiple roles. For example, one address can be both a shipping and a billing address, and also the default for either. For field details, see the [Customer](/search.md?urn=ctp:api:type:Customer) representation.

When changing or removing an existing address, or assigning it a shipping, billing, or default role, you don't need to know the internal `id`. The relevant [update actions](/api/projects/customers.md#update-actions) accept either the address `id` or its `key` to identify the address. Removing an address also clears the Customer references to that address.

The same address-role model is used for the [BusinessUnit](/search.md?urn=ctp:api:type:BusinessUnit) representation.

### Customer Group assignments

The [Customer](/search.md?urn=ctp:api:type:Customer) `customerGroup` field allows assigning one Customer Group per Customer, while the `customerGroupAssignments` field supports assigning up to 500 Customer Groups and better supports complex pricing scenarios.

Although both fields can be used together in existing projects, we recommend using only the `customerGroupAssignments` field in new projects. In addition to supporting assigning multiple Customer Groups to Customers, it provides greater flexibility in complex pricing scenarios. To migrate existing Projects from using a single Customer Group per Customer to using multiple Customer Groups, see our [migration guide](/guides/migration-guides/multiple-customer-groups.md).

You can assign up to 500 Customer Groups to a [Business Unit](/api/projects/business-units.md) via the `customerGroupAssignments` field.

> When updating the Customer Group assignments for a Customer or Business Unit, the prices in the Customer's or Associate's existing [Carts](/api/projects/carts.md) are not recalculated automatically, and must be [recalculated](/api/projects/carts.md#recalculate) manually.

## Working with the APIs

### Email case-insensitivity

To perform a case-insensitive [query](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers:GET) for emails, convert the given email address to lowercase and use the additional query field [lowercaseEmail](/api/projects/customers.md#customer).

### Customer authentication (sign-in)

Customer authentication endpoints differentiate between [global and store-specific Customers](/api/customers-apis-overview.md#global-versus-store-specific-customers).

- To authenticate a global Customer (not associated with a Store), use the [general](/search.md?urn=ctp:api:endpoint:/{projectKey}/login:POST) or [Store-specific](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/login:POST) endpoint.
- To authenticate a Store-specific Customer, use the [Store-specific](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/login:POST) endpoint.

During the sign-in process, Customers may be assigned resources created prior to the sign-in. With `anonymousCart`, a single anonymous [Cart](/search.md?urn=ctp:api:type:Cart) can be assigned. With `anonymousId`, all [Carts](/api/projects/carts.md#cart), [Orders](/api/projects/orders.md#order), [ShoppingLists](/api/projects/shoppingLists.md#shoppinglist), and [Payments](/api/projects/payments.md#payment) with the same `anonymousId` can be assigned to the Customer. If both `anonymousCart` and `anonymousId` are defined, the anonymous Cart must have the same `anonymousId` assigned.

Cart assignment can happen in one of two ways:

- If the Customer does not have a Cart yet, or the value of [AnonymousCartSignInMode](/search.md?urn=ctp:api:type:AnonymousCartSignInMode) is set to `UseAsNewActiveCustomerCart`, then the anonymous Cart becomes the Customer's Cart.
- If the Customer already has one or more Carts and the value of [AnonymousCartSignInMode](/search.md?urn=ctp:api:type:AnonymousCartSignInMode) is set to `MergeWithExistingCustomerCart`, then the items of the anonymous Cart will be merged into the Customer's most recently modified active Cart. This process is referred to as [Cart merge](/api/carts-orders-overview.md#merge-a-cart) and results in a specific set of changes for both Carts.

Upon successfully signing-in a Customer, a [CustomerSignInResult](/search.md?urn=ctp:api:type:CustomerSignInResult) is returned. If the CustomerSignInResult contains a Cart, the Cart is [recalculated](/api/projects/carts.md#recalculate) to have up-to-date prices, taxes, discounts, and line items.

### Cart merge during sign-in and sign-up

Cart merge during sign-in and sign-up is only available for Customers authenticating through the [Internal OAuth](/api/authorization.md#request-an-access-token-using-the-internal-oauth-20-service). To merge Carts belonging to externally authenticated Customers, use the [Merge Cart](/search.md?urn=ctp:api:endpoint:/{projectKey}/carts/customer-id={customerId}/merge:POST) and [Merge Cart in Store](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/carts/customer-id={customerId}/merge:POST) endpoints on the Carts API.

Cart merge is applied by default on the following endpoints:

- [Create (sign up) Customer](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers:POST)
- [Create (sign up) Customer in Store](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers:POST)
- [Authenticate (sign-in) Customer](/search.md?urn=ctp:api:endpoint:/{projectKey}/login:POST)
- [Authenticate (sign in) Customer in Store](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/login:POST).

To deactivate this feature, set the `anonymousCartSignInMode` field on the [CustomerSignin](/search.md?urn=ctp:api:type:CustomerSignin) to `UseAsNewActiveCustomerCart`.

The response to a sign-in or sign-up contains the Customer's most recently modified active Cart. They can then modify this Cart and place an order.

### Customer email verification

Email verification follows the same set of steps for global as well as Store-specific Customers.
For global customers, use the [general Customer endpoints](/api/projects/customers.md#email-verification-of-customer). For Store-specific Customers, use the [Customer in Store endpoints](/api/projects/customers.md#email-verification-of-customer-in-store).

To verify a Customer's email, do the following:

1. Send an email token embedded in a link to the Customer.

   - For global Customers, use the [Create email token for Customer endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/email-token:POST).
   - For Store-specific Customers, use [Create email token for Customer in Store endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers/email-token:POST).

   If the token is valid for 60 minutes or less, its value can be retrieved through the [CustomerEmailTokenCreated](/api/projects/messages/customer-messages.md#customer-email-token-created) Message—enabling asynchronous flows.

   > By default, creating an email token does not invalidate older tokens; to invalidate older tokens, use the [CustomerCreateEmailToken](/search.md?urn=ctp:api:type:CustomerCreateEmailToken) update action.

2. When the Customer clicks the link, optionally retrieve the Customer by the email token.
   - For global Customers, use the [Get Customer by email token endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/email-token={emailToken}:GET).
   - For Store-specific Customers, use the [Get Customer in Store by email token endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers/email-token={emailToken}:GET).

3. Verify the Customer's email. This sets the Customer's `isEmailVerified` field to `true`.
   - For global Customers, use the [Verify email of Customer endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/email/confirm:POST).
   - For Store-specific Customers, use the [Verify email of Customer in Store endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers/email/confirm:POST).
   - These methods are also provided on the [My Customer Profile](/search.md?urn=ctp:api:endpoint:/{projectKey}/me/email/confirm:POST) with their respective [Scopes](/api/scopes.md).

When using the [Change Email](/api/projects/customers.md#change-email) update action, even if the email address remains the same, the Customer's `isEmailVerified` property is set to `false`.

After the email is verified, all email tokens issued previously through this flow are invalidated. This invalidation of tokens is [eventually consistent](/api/general-concepts.md#eventual-consistency).

### Customer password reset

Password reset follows the same set of steps for global as well as Store-specific Customers.
For global customers, use the [general Customer endpoints](/api/projects/customers.md#password-reset-of-customer). For Store-specific Customers, use the [Customer in Store endpoints](/api/projects/customers.md#password-reset-of-customer-in-store).

To reset a Customer's password, do the following:

1. Send a password reset token embedded in a link to the Customer.

   - For global Customers, use the [Create password reset token for Customer endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/password-token:POST).
   - For Store-specific Customers, use [Create password reset token for Customer in Store endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers/password-token:POST).

   If the token is valid for 60 minutes or less, its value can be retrieved through the [CustomerPasswordTokenCreated](/api/projects/messages/customer-messages.md#customer-password-token-created) Message—enabling asynchronous flows.

   > By default, creating a password token does not invalidate older tokens; to invalidate older tokens, use the [CustomerCreatePasswordResetToken](/search.md?urn=ctp:api:type:CustomerCreatePasswordResetToken) update action.

2. When the Customer clicks the link, optionally retrieve the Customer by the password token.
   - For global Customers, use the [Get Customer by password token endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/password-token={passwordToken}:GET).
   - For Store-specific Customers, use the [Get Customer in Store by password token endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers/password-token={passwordToken}:GET).

3. When the Customer enters the new password, reset the Customer's password.
   - For global Customers, use the [Reset password of Customer endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/password/reset:POST).
   - For Store-specific Customers, use the [Reset password of Customer in Store endpoint](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/customers/password/reset:POST).
   - These methods are also provided on the [My Customer Profile](/search.md?urn=ctp:api:endpoint:/{projectKey}/me/password/reset:POST) with their respective [Scopes](/api/scopes.md).

After the password is reset, all password tokens issued previously through this flow are invalidated. In addition, any access and refresh tokens issued previously through the [password flow](/api/authorization.md#password-flow) and [refresh token flow](/api/authorization.md#refresh-token-flow) are invalidated. This invalidation of tokens is [eventually consistent](/api/general-concepts.md#eventual-consistency).

### Customer permissions

An API Client with the `view_customers` scope provides access to all Customers in your Project.
Therefore, you must implement your own data protection in your storefront or use the [Me endpoints](/api/me-endpoints-overview.md).

### Store-specific permissions

If you have [Store-specific Customers](/api/customers-apis-overview.md#global-versus-store-specific-customers) in your Project, you can provide Store-specific access to those.
Customers can be managed per Store through the Customer in Store endpoints. Carts associated with these Customers can also be [retrieved per Store](/search.md?urn=ctp:api:endpoint:/{projectKey}/in-store/key={storeKey}/carts/customer-id={customerId}:GET).

The [Me endpoints](/api/me-endpoints-overview.md) are provided as Customer in Store variations with restricted access for one Store-specific Customer.

### Customer-specific prices &#x20;

When [placing an Order](/search.md?urn=ctp:api:endpoint:/{projectKey}/orders:POST), the [Cart's](/api/projects/carts.md#cart) `customerId` has to reference an [Associate](/search.md?urn=ctp:api:type:Associate) in the Business Unit that represents the customer. To ensure that you apply the correct pricing, reference the customer-specific [Channel](/api/projects/channels.md) in the `distributionChannel` of the Cart's [Line Item Drafts](/api/projects/carts.md#lineitemdraft). Without specifying the Channel, the base price is selected instead of the customer-specific price.

To use [Standalone Prices](/api/projects/standalone-prices.md), set the [ProductPriceMode](/api/projects/products.md#productpricemode) to `Standalone` and [create Prices](/search.md?urn=ctp:api:endpoint:/{projectKey}/standalone-prices:POST) for every Channel.

### Customer Search

The Customer Search API is designed to be ID-first—returning only Customer IDs—to provide the best performance. To fetch a Customer, use local caches or the [Get a Customer by ID](/search.md?urn=ctp:api:endpoint:/{projectKey}/customers/{id}:GET) endpoint.

> Customer Search is deactivated for a Project, by default.&#x20;
>
> To activate, use the [Change Customer Search status](/api/projects/project.md#change-customer-search-status) update action on the Project API or index the Customers in the [Merchant Center](/docs/login.md) (by navigating to **Customers > Customer list**).
>
> If no calls have been made to the [Search Customers](/api/projects/customer-search.md#search-customers) endpoint in the last 30 days, the feature is automatically deactivated for a Project and must be reactivated.

## Limits

A maximum of **10000000** Customers can be created per Project. A Customer can be assigned to a maximum of **500** Customer Groups. These are soft limits that can be increased per Project after a performance impact review. See [Limit increase guidance](/api/limit-increase-guidance.md#resource-count-limits).

A maximum number of **10000** Customer Groups can be created per Project. This is a soft limit that can be increased per Project after a performance impact review. See [Limit increase guidance](/api/limit-increase-guidance.md#b2b-hierarchy-and-permission-limits).

A maximum of **10000** addresses per Customer can be indexed for Customer Search.

A maximum of **50** Custom Fields per Customer can be indexed. If a Customer has more, only the first **50** Custom Fields, sorted alphabetically by field name, are indexed.

## Related pages

- [Area overview page with navigation](/api.md)
- [Previous page: Overview](/api/customers-overview.md)
- [Next page: Customers](/api/projects/customers.md)
- [Search documentation and API specs](/search.md)