Stitchflow
commercetools logo

commercetools User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 9, 2026

Summary and recommendation

The commercetools Platform API manages Customer (shopper) resources via REST under `https://api.{region}.commercetools.com/{projectKey}/customers`. Authentication uses OAuth 2.0 client credentials flow; tokens are project-scoped and must declare all required scopes at API Client creation - scopes cannot be amended post-creation without recreating the client.

The critical architectural distinction: Merchant Center team users (admin accounts) are not manageable via the Platform API. There is no REST endpoint for team user CRUD; that surface is UI-only or SSO/OIDC-only.

For identity graph use cases - syncing an external IdP or directory into commercetools customer records - the `externalId` field on the Customer object is the primary correlation key. It is not enforced as unique by the platform, so uniqueness must be guaranteed in the integration layer.

Subscriptions (webhooks) deliver CustomerCreated, CustomerDeleted, CustomerEmailVerified, and CustomerPasswordUpdated events to HTTP endpoints or message queues (AWS SQS/SNS, Azure Service Bus, Google Cloud Pub/Sub), enabling downstream identity graph updates without polling.

API quick reference

Has user APIYes
Auth methodOAuth 2.0 (Client Credentials flow for M2M; Password flow for customer login)
Base URLOfficial docs
SCIM availableNo
SCIM plan requiredEnterprise

Authentication

Auth method: OAuth 2.0 (Client Credentials flow for M2M; Password flow for customer login)

Setup steps

  1. Create an API Client in the Merchant Center under Settings > Developer Settings > API Clients.
  2. Select the required scopes (e.g., manage_customers, view_customers) for the client.
  3. Copy the client_id and client_secret shown once at creation time.
  4. POST to https://auth.{region}.commercetools.com/oauth/token with grant_type=client_credentials, client_id, client_secret, and scope to obtain a Bearer token.
  5. Include the Bearer token in the Authorization header for all API requests.

Required scopes

Scope Description Required for
manage_customers:{projectKey} Full read/write access to Customer resources. Create, update, delete customers
view_customers:{projectKey} Read-only access to Customer resources. List and retrieve customers
manage_customer_groups:{projectKey} Create and manage Customer Groups. Assigning customers to groups
manage_orders:{projectKey} Access to orders associated with customers. Retrieving customer order history
manage_project:{projectKey} Admin-level project management including team user administration via Merchant Center API. Managing Merchant Center team users programmatically

User object / data model

Field Type Description On create On update Notes
id string (UUID) Unique identifier of the Customer. auto-generated immutable System-assigned UUID.
version integer Current version for optimistic concurrency control. starts at 1 must be provided; increments on each update Required in all update requests.
email string Customer's email address; must be unique per project. required via ChangeEmail action Case-insensitive uniqueness enforced.
password string (hashed) Hashed password; never returned in plaintext. required (plaintext, then hashed) via ChangePassword action Not returned in GET responses.
firstName string Customer's first name. optional via SetFirstName action
lastName string Customer's last name. optional via SetLastName action
customerNumber string User-defined unique customer number. optional via SetCustomerNumber action Must be unique if set.
externalId string External system identifier. optional via SetExternalId action Useful for syncing with external identity systems.
isEmailVerified boolean Whether the customer's email has been verified. optional (default false) via SetEmailVerified action
customerGroup CustomerGroupReference Reference to the customer's group (for pricing/discounts). optional via SetCustomerGroup action
addresses array of Address List of addresses associated with the customer. optional via AddAddress / ChangeAddress / RemoveAddress actions
defaultShippingAddressId string ID of the default shipping address from the addresses array. optional via SetDefaultShippingAddress action
defaultBillingAddressId string ID of the default billing address from the addresses array. optional via SetDefaultBillingAddress action
dateOfBirth date (YYYY-MM-DD) Customer's date of birth. optional via SetDateOfBirth action
companyName string Company name associated with the customer. optional via SetCompanyName action
vatId string VAT ID for B2B customers. optional via SetVatId action
locale string (BCP 47) Preferred locale of the customer. optional via SetLocale action
custom CustomFields Project-defined custom fields. optional via SetCustomField / SetCustomType actions Requires a Custom Type to be defined first.
createdAt datetime (ISO 8601) Timestamp of customer creation. auto-generated immutable
lastModifiedAt datetime (ISO 8601) Timestamp of last modification. auto-generated auto-updated

Core endpoints

Create Customer

  • Method: POST
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers
  • Watch out for: Response wraps the customer in a CustomerSignInResult object (with cart if applicable). The password is never returned.

Request example

POST /{projectKey}/customers
Authorization: Bearer {token}
Content-Type: application/json
{
  "email": "jane@example.com",
  "password": "secret123",
  "firstName": "Jane",
  "lastName": "Doe"
}

Response example

{
  "customer": {
    "id": "abc-123",
    "version": 1,
    "email": "jane@example.com",
    "firstName": "Jane",
    "lastName": "Doe",
    "isEmailVerified": false,
    "createdAt": "2024-01-15T10:00:00.000Z"
  }
}

Get Customer by ID

  • Method: GET
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers/{id}
  • Watch out for: Requires manage_customers or view_customers scope. Password hash is never included in the response.

Request example

GET /{projectKey}/customers/abc-123
Authorization: Bearer {token}

Response example

{
  "id": "abc-123",
  "version": 1,
  "email": "jane@example.com",
  "firstName": "Jane",
  "lastName": "Doe",
  "isEmailVerified": false
}

Query Customers

  • Method: GET
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers
  • Watch out for: Uses commercetools Query Predicate syntax for the where parameter. Max limit is 500. For large datasets, use offset pagination carefully as deep offsets are slow.

Request example

GET /{projectKey}/customers?where=email%3D%22jane%40example.com%22&limit=20&offset=0
Authorization: Bearer {token}

Response example

{
  "limit": 20,
  "offset": 0,
  "count": 1,
  "total": 1,
  "results": [
    { "id": "abc-123", "email": "jane@example.com" }
  ]
}

Update Customer

  • Method: POST
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers/{id}
  • Watch out for: Updates use an action-based pattern (not PATCH with field diffs). The current version must be sent; a version mismatch returns HTTP 409 ConcurrentModification.

Request example

POST /{projectKey}/customers/abc-123
Authorization: Bearer {token}
Content-Type: application/json
{
  "version": 1,
  "actions": [
    { "action": "setFirstName", "firstName": "Janet" }
  ]
}

Response example

{
  "id": "abc-123",
  "version": 2,
  "firstName": "Janet",
  "email": "jane@example.com"
}

Delete Customer

  • Method: DELETE
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers/{id}?version={version}
  • Watch out for: The version query parameter is mandatory. Deletion is permanent and returns the deleted Customer object.

Request example

DELETE /{projectKey}/customers/abc-123?version=2
Authorization: Bearer {token}

Response example

{
  "id": "abc-123",
  "version": 2,
  "email": "jane@example.com"
}

Customer Login (Authenticate)

  • Method: POST
  • URL: https://api.{region}.commercetools.com/{projectKey}/login
  • Watch out for: This endpoint authenticates a shopper (Customer), not a Merchant Center team user. Returns CustomerSignInResult. Use the Password flow token endpoint for session tokens.

Request example

POST /{projectKey}/login
Content-Type: application/json
{
  "email": "jane@example.com",
  "password": "secret123"
}

Response example

{
  "customer": {
    "id": "abc-123",
    "email": "jane@example.com",
    "version": 2
  }
}

Create Customer Token (Email Verification / Password Reset)

  • Method: POST
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers/email-token
  • Watch out for: The token value must be sent to the customer via your own email infrastructure. commercetools does not send emails.

Request example

POST /{projectKey}/customers/email-token
Authorization: Bearer {token}
Content-Type: application/json
{
  "id": "abc-123",
  "version": 2,
  "ttlMinutes": 2880
}

Response example

{
  "id": "token-uuid",
  "customerId": "abc-123",
  "value": "abc123tokenvalue",
  "expiresAt": "2024-01-17T10:00:00.000Z"
}

Get Customer by Key

  • Method: GET
  • URL: https://api.{region}.commercetools.com/{projectKey}/customers/key={key}
  • Watch out for: The key field must be set on the Customer at creation or via SetKey action. Not all customers have keys.

Request example

GET /{projectKey}/customers/key=my-external-key
Authorization: Bearer {token}

Response example

{
  "id": "abc-123",
  "key": "my-external-key",
  "email": "jane@example.com",
  "version": 2
}

Rate limits, pagination, and events

  • Rate limits: commercetools enforces per-project rate limits. Default limits vary by plan and region. Limits are communicated via response headers when a threshold is approached or exceeded.
  • Rate-limit headers: Yes
  • Retry-After header: Yes
  • Rate-limit notes: HTTP 429 is returned when rate limit is exceeded. The X-RateLimit-Limit and X-RateLimit-Remaining headers are present. Retry-After header is included on 429 responses. Exact numeric limits are not publicly published and are project-specific.
  • Pagination method: offset
  • Default page size: 20
  • Max page size: 500
  • Pagination pointer: limit / offset
Plan Limit Concurrent
Standard/Growth Varies by project; typically ~100–200 requests/second per project 0
Enterprise/Premium Higher limits negotiated per contract; contact commercetools support 0
  • Webhooks available: Yes
  • Webhook notes: commercetools supports Subscriptions (webhooks) that deliver messages to external endpoints (HTTP/SQS/SNS/Azure Service Bus/Google Pub/Sub) when resource changes occur, including Customer events.
  • Alternative event strategy: Subscriptions can also target message queues (AWS SQS/SNS, Azure Service Bus, Google Cloud Pub/Sub) instead of HTTP endpoints.
  • Webhook events: CustomerCreated, CustomerUpdated (via resource update messages), CustomerDeleted, CustomerEmailVerified, CustomerPasswordUpdated, CustomerGroupSet

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: Enterprise
  • Endpoint: Not documented

Limitations:

  • SCIM is not documented or officially supported by commercetools as of the latest available documentation.
  • Merchant Center team user provisioning is managed via the Merchant Center UI or SSO/OIDC (Identity Enterprise).
  • SSO via OIDC is available for Enterprise plans; SCIM automated provisioning is not available.
  • Customer (shopper) accounts are managed via the Platform API, not SCIM.

Common scenarios

Three integration patterns cover the majority of identity-adjacent use cases:

  • Provision + verify: POST to /{projectKey}/customers to create the record, then POST to /{projectKey}/customers/email-token to generate a verification token. commercetools does not send email - the token value must be delivered via your own email infrastructure and confirmed via /{projectKey}/customers/email/confirm.

  • Action-based profile updates: All Customer mutations use a POST with an actions array, not a PATCH. The current version is mandatory; a stale version returns HTTP 409 ConcurrentModification. Multiple actions (e.g., setFirstName, setLocale, setExternalId) can be batched in a single request to minimize round-trips and version conflicts.

  • External identity sync via externalId: Set externalId at creation to the upstream directory's user ID. Query by predicate (where=externalId%3D%22{value}%22) to resolve the commercetools customer from an external event. Subscribe to CustomerCreated and CustomerDeleted messages to propagate changes back to the identity graph without polling the query endpoint.

Provision a new customer account and trigger email verification

  1. POST to /{projectKey}/customers with email, password, firstName, lastName to create the customer.
  2. Extract the customer id and version from the CustomerSignInResult response.
  3. POST to /{projectKey}/customers/email-token with the customer id, version, and desired ttlMinutes.
  4. Receive the token value in the response and send it to the customer via your own email service.
  5. When the customer clicks the link, POST to /{projectKey}/customers/email/confirm with the token value to mark isEmailVerified=true.

Watch out for: commercetools does not send emails. Steps 4–5 require your own email delivery infrastructure and a front-end confirmation page.

Update customer profile fields using action-based updates

  1. GET /{projectKey}/customers/{id} to retrieve the current customer and note the version.
  2. POST to /{projectKey}/customers/{id} with the current version and an actions array containing the desired update actions (e.g., setFirstName, setLastName, setLocale).
  3. Multiple actions can be batched in a single request.
  4. The response returns the updated Customer with an incremented version.

Watch out for: If another process updates the customer between your GET and POST, you will receive a 409 ConcurrentModification. Re-fetch the customer and retry with the new version.

Sync external identity system users to commercetools customers using externalId

  1. When creating a customer, include externalId set to the user's ID in your external identity system.
  2. To look up a customer by externalId, use GET /{projectKey}/customers?where=externalId%3D%22ext-user-456%22.
  3. To update the mapping, POST to /{projectKey}/customers/{id} with action setExternalId and the new value.
  4. Subscribe to CustomerCreated and CustomerDeleted messages via a Subscription to keep the external system in sync.

Watch out for: externalId is not enforced as unique by commercetools. Enforce uniqueness in your integration layer or use the where query to check before creation.

Why building this yourself is a trap

The most consequential caveat for any identity automation build: SCIM is not supported. Merchant Center team user provisioning has no API surface - it is managed exclusively through the Merchant Center UI or OIDC-based SSO for Enterprise plans.

Any workflow that assumes programmatic control over admin user lifecycle will hit a hard wall; there is no endpoint to create, update, or delete team members via the Platform API.

Pagination uses offset/limit with a maximum page size of 500. Deep offset queries (offset > 10,000) degrade significantly; large-dataset traversals should use the Customer Search API or sort-keyed iteration rather than naive offset increments.

Rate limits are project-specific and not publicly published - the X-RateLimit-Remaining header is the only real-time signal, and HTTP 429 responses include a Retry-After header. Exact thresholds for Standard/Growth plans are approximately 100–200 requests/second per project, but Enterprise limits are contract-negotiated and must be confirmed with commercetools directly.

Automate commercetools workflows without one-off scripts

Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 9, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste