Custom APIs
B2C Commerce provides powerful tools to customize shopper experiences. Today SCAPI can be customized via Hooks, where developers use the B2C Commerce Script API to add filters or modify responses before they get sent back to the calling application.
To further leverage existing development tools, we provide a framework enabling developers to write custom script code, such as controllers, and expose this functionality as a custom REST API under the SCAPI framework.
The SCAPI Custom APIs video walks you through how to build a cartridge with a Custom API. If you do not have access to the code samples provided in the video, see Salesforce Commerce Cloud GitHub Repositories and Access.

A Custom API URL has the following structural format:
https://{shortCode}.api.commercecloud.salesforce.com/custom/{apiName}/{apiVersion}/organizations/{organizationId}/{endpointPath}
The term custom
must be used as API family. The parameters apiName
, apiVersion
, and endpointPath
can be defined as described below.
In order to create a Custom API, three components are required:
- The API contract as an OAS 3.0 schema file.
- The API implementation as a script using the B2C Commerce Script API.
- The API mapping defined in an
api.json
file.
In this guide, we will look at an example called Loyalty Info API that can be used to retrieve the loyalty status for a given customer. This graphic shows the required components and their relationship:
Only existing customers can access some of the links on this page. Visit Salesforce Commerce Cloud GitHub Repositories and Access for information about how to get access to the Commerce Cloud repositories.
The components will be further explained in the next sections. For now, please note the following details from the diagram:
- A dashed line shows where this URL segment is defined.
- The blue parameter is the endpoint identifier. It is used to bind the endpoint to the implementation and appears in all three components.
Custom APIs are defined within custom code cartridges. In the cartridge
directory, a new folder rest-apis
must be created which is the root folder for all APIs in that cartridge.
In the rest-apis
folder, subdirectories represent the actual APIs. The names of these directories represent the API names as they are addressed by the URL. Each directory contains the files for the three components representing this API.
Example: The structure for the example API called loyalty-info
is expected to look like this:
API directory names can only contain alphanumeric lowercase characters and hyphens.
Due to the registration process, it is recommended to start implementing Custom API endpoints in a new code version.
The API contract must be provided by an OAS 3.0 schema file in YAML format. For more information about OAS 3.0, refer to the OAS 3.0 specification.
In this schema file, the API version and the endpoints are defined. The API version is located in the info.version
field and is transformed into a URL version by using the major version segment and prepending it with v
(for example, 1.0.1
→ v1
).
The endpoints are defined as part of the paths
object and can implement multiple operations (i.e. HTTP methods). Each operation is required to have a property called operationId
, which must be unique within the schema file. It is used for mapping the endpoint to the implementation. The path
of the endpoint becomes the endpointPath
in the URL structure.
In order to secure the endpoint, a valid security scheme must be defined as a shared component and applied at the endpoint or global level. See Authentication for more details.
Example: The schema for a /customers?c_customer_id={id}
endpoint in version v1
is expected to look like this:
The API implementation is provided by a script file using the B2C Commerce Script API. The function name must match the value of the endpoint’s operationId
in the contract.
Example: A valid implementation for /customers?c_customer_id={id}
based on the definition in the contract could look like this:
It is strongly recommended to always return responses in JSON format. Errors should additionally adhere to the SCAPI error format as described in RFC 9457, with at least the type
field being present. Response bodies are subject to validation in the future and may be declined if they don’t meet these requirements.
Please make sure that the implementation contains high quality, well-tested code with sufficient error handling. In order to protect the platform, Custom APIs use a Circuit Breaker mechanism that will block API requests when the implementation throws too many errors. See Circuit Breaker for more information.
To learn how to create JSON responses in your scripts with ease, have a look at the documentation of the Script API class RESTResponseMgr
.
The API mapping is provided by an api.json
file. It contains a list of endpoints, and for each entry the endpoint name, its schema file, and the name of the implementing script is defined.
Example: A valid mapping for /customers?c_customer_id={id}
based on the definitions in the contract and implementation is expected to look like this:
Relative paths are not supported. The schema and implementation must be located at the same level as the corresponding api.json
.
The implementation name must be provided without the file extension.
When the Custom API endpoints have been correctly defined as previously described, they must be registered in order to be accessible.
The registration is triggered by activating the code version containing the new API definitions. Whenever changes to an API are required, it is recommended to work in a new code version and to switch the version when ready.
Custom API versions are represented in two different formats, the API version and the URL version.
The API version is defined in the contract as part of the info.version
field and applies to all endpoints defined in this file. The value must be numeric but can have multiple segments separated by a dot.
In the URL, the version is transformed by using the major version segment and prepending it with v
. For example, this list shows valid API versions and their corresponding URL versions:
- 1 → v1
- 1.0 → v1
- 2.0 → v2
- 2.1.1 → v2
It is recommended to introduce breaking changes in a new major version. Please see the SCAPI Change Policy for details.
The following system query parameters exist and can be used when defined in the contract:
siteId
- The site of the current requestlocale
- The locale of the current request
Make sure you understand the meaning of these parameters and when to use them. For example, the system uses the siteId
to identify the site context, so using this parameter only makes sense for a Shopper API request. For an Admin API request that requires a site, for example: an API that returns objects filtered by site, use a custom query parameter like c_siteId
. Note that the site is a query parameter instead of a path parameter, which is different from other ways of customization, such as using controllers and hooks.
The parameter locale
is used to set the locale of the request, and behaves the same way as the Script API method dw.system.Request#setLocale
.
If a siteId
is not provided, the request is treated as a SCAPI Admin API request and the Business Manager site is used. If a locale
is not provided in a request, the site’s default locale is used.
The parameter siteId
is also used to register a Custom API. This means that if the cartridge containing a Custom API is not added to a site cartridge path, any request to it with that siteId
results in a 404
response. For Admin APIs, the cartridge must be added to the cartridge path of the Business Manager site.
Using a shopper token for an Admin API request is not allowed. In these scenarios, use an AmOAuth2
token.
Example 1: Define the system query parameter using the name for siteId
and type string
. If the parameter isn't a valid string, the request is declined.
Example 2: Define the system query parameter with the name locale
and the type string
. If the parameter isn't a valid string, the request is declined.
Example 3: Make a Custom API request with system query parameters:
System query parameters must be defined with the correct schema
field as previously shown. Setting required
to false
means that the value is not required. When required
is true
, the request is refused if the parameter is missing or empty.
Like the non-custom B2C Commerce APIs (SCAPI), each endpoint is either a Shopper or an Admin API endpoint. For general information on how to differentiate those API groups, see SCAPI Groups.
For Custom APIs, there are three main differences between Shopper and Admin endpoints:
- Shopper endpoints have stricter limits for request runtime, request body size, and API quotas. See Limitations for specific values.
- Shopper endpoints require the
siteId
query parameter, while Admin endpoints must omit this parameter. Requests without asiteId
are treated as Admin API requests. - Shopper endpoints require the
ShopperToken
security scheme, while Admin endpoints require theAmOAuth2
security scheme, and each endpoint can have only one security scheme. See Authentication for details on how to use these.
Supported methods for Custom APIs include:
- GET
- POST
- PUT
- PATCH
- DELETE
- HEAD
- OPTIONS
The following example extends the Loyalty Information API with a POST method with which an admin can update the loyalty information:
Here is a sample implementation for this endpoint:
To learn more about new convenience methods for SCAPI path parsing, refer to the Request
class in Script API.
The attribute additionalProperties
is NOT allowed when defining the request body schema. To take advantage of request body validation and build robust APIs, define the request body schema in detail. If the request body schema of an endpoint contains additionalProperties
, the endpoint is not registered.
All request parameters must be defined in the contract as requests with unknown parameters are declined. Custom query parameters must be prefixed with c_
. System query parameters must be added to the contract if used.
Example: Defining a mandatory query parameter with the name c_status
and the type integer
. If the parameter is not present or is not a valid integer, the request is declined.
To get access to this repository, please complete the trail Tools & Resources for Salesforce B2C Commerce Developers.
Our community is maintaining a Custom API collection within the Sample Hooks Collection, providing the functionality earlier offered with hooks as new Custom APIs. Here are a few APIs available with this collection:
- URL Resolution
- URL List API
- Guest Order Look Up
- Customer Groups API
- Mini Product
- Send Mail API
- Geo IP API
For more information, check out the Custom APIs Collection on the Salesforce Commerce Cloud GitHub repository.
The following limitations are in place:
- General:
- Transactions can’t be committed in the case of GET requests.
- The schema attribute
additionalProperties
is not allowed. - Shopper and Admin APIs must adhere to the applicable API quotas. For quota details, see API Quotas documentation.
- Shopper APIs:
- Maximum request runtime of 10 seconds.
- Maximum request body size of 5 MiB (5,242,880 bytes).
STOREFRONT
activity type. Storefront quota limits are applied.
- SCAPI Admin APIs:
- Maximum request runtime of 60 seconds.
- Maximum request body size of 20 MB (20,000,000 bytes).
BUSINESS_MANAGER
activity type. Default quota limits are applied.