commercetools exposes B2B resources through two endpoint patterns suited to B2B. Choosing the wrong one either bypasses permission enforcement entirely or blocks legitimate buyer access, so the choice is an architectural decision, not just a routing detail. These patterns build on the OAuth scopes and API Client foundations covered in the Composable Commerce developer essentials path.
This page frames the two patterns as a decision for the architect. For the authoritative permission-evaluation matrix across every endpoint type, see Permission evaluation in the API reference.
Two ways to access B2B resources
| Pattern | Path shape | Permission evaluation | Typical use case |
|---|---|---|---|
| General | /{projectKey}/carts | None | Seller back-office operations, customer support |
as-associate | /{projectKey}/as-associate/{associateId}/in-business-unit/key={key}/carts | My and Others permissions | A B2B buyer portal acting on behalf of an Associate |
General endpoints
The general endpoints carry no knowledge of which Associate is behind the call, so no Associate Role permissions are validated. They are intended for the Seller to manage data without permission enforcement, for example in back-office tools or support consoles.
Because they skip permission checks, general endpoints must never be exposed directly to buyers.
as-associate endpoints
The
as-associate endpoints take both an associateId and a Business Unit key in the URL, and check the acting Associate's permissions against that Business Unit. They validate both the Associate's My permissions and the Others permissions that grant access to other Associates' resources, for example letting a supervisor view a colleague's cart.This is the pattern purpose-built for the company-on-behalf-of model, which is why it is the recommended foundation for a B2B buyer portal.
GET /{projectKey}/as-associate/{associateId}/in-business-unit/key=pacific-residential/carts HTTP/1.1
Authorization: Bearer {accessToken}
The response is scoped to the named Business Unit: it returns only the carts that belong to
pacific-residential, and each cart carries the businessUnit reference that the gate scoped the call to.{
"limit": 20,
"offset": 0,
"count": 1,
"total": 1,
"results": [
{
"id": "a1b2c3d4-1111-2222-3333-444455556666",
"version": 3,
"businessUnit": {
"typeId": "business-unit",
"key": "pacific-residential"
},
"cartState": "Active",
"lineItems": []
}
]
}
The Permission Gate
Every
as-associate call passes through a server-side gate that performs three checks before the operation runs:- Membership: the caller must be an Associate of the Business Unit named in the URL.
- Permission: the Associate's roles (direct and inherited) must include the specific permission the operation requires, for example
CreateOthersCarts. - Scope: the response is scoped to that Business Unit's commercial context, such as its Stores and the Associates within it.
If the permission check fails, the platform returns
403 Forbidden with an AssociateMissingPermissionError. The frontend does not implement any of these checks; they are enforced by the platform, which is the core security benefit of the pattern.{
"statusCode": 403,
"message": "Associate '7c1e9f20-aaaa-bbbb-cccc-1234567890ab' has no rights to create a cart for customer 'f8a4e2c1-1111-2222-3333-444455556666' in business-unit 'pacific-residential'. Needs 'CreateOthersCarts'.",
"errors": [
{
"code": "AssociateMissingPermission",
"message": "Associate '7c1e9f20-aaaa-bbbb-cccc-1234567890ab' has no rights to create a cart for customer 'f8a4e2c1-1111-2222-3333-444455556666' in business-unit 'pacific-residential'. Needs 'CreateOthersCarts'.",
"associate": {
"typeId": "customer",
"id": "7c1e9f20-aaaa-bbbb-cccc-1234567890ab"
},
"businessUnit": {
"typeId": "business-unit",
"key": "pacific-residential"
},
"permissions": ["CreateOthersCarts"]
}
]
}
The
as-associate endpoints verify permissions against the URL parameters, but they do not validate those URL parameters against the token's scopes. Anyone who can call the endpoint can name any associateId and Business Unit. For this reason, as-associate endpoints must only be called from a trusted middleware that authenticates the buyer and sets the URL parameters correctly, never directly from an untrusted browser client. See Through the associate endpoint in the API reference for the canonical statement of this constraint.Choosing a pattern
Use this decision guide when an operation needs an endpoint:
- The Seller is managing data with no buyer permission enforcement → general.
- A buyer portal must enforce buyer permissions, including access to other Associates' resources →
as-associate, behind trusted middleware.
Worked example: routing Pacific Property Group operations
Trace the right endpoint for three Pacific Property Group operations.
- The Seller's support team corrects a stuck order for the Commercial Division. No buyer permissions are involved, so this goes through the general endpoint from an internal tool.
- A Residential buyer views their own cart in the buyer portal. The portal routes this through
as-associatebehind its trusted middleware, so buyer permissions are enforced centrally and consistently. - A Residential supervisor opens a colleague's cart to help complete it. This touches another Associate's resource, so it requires
as-associatewith theViewOthersCartspermission. If the supervisor's roles lack that permission, the Permission Gate returns403 Forbidden.
Key takeaways
- General endpoints perform no permission checks and are for Seller back-office use only.
as-associateendpoints act on behalf of an Associate within a Business Unit and validate bothMyandOtherspermissions.as-associateis the recommended pattern for B2B buyer portals because the platform enforces permissions server-side.- The Permission Gate checks membership, permission, and scope on every
as-associatecall and returns403 Forbiddenwhen a permission is missing. as-associateendpoints do not validate URL parameters against token scopes, so they must be called only from trusted middleware.