Salesforce Omnichannel Inventory is an inventory solution that delivers near real-time inventory availability at the location level across all your fulfillment channels.
I’d like to explain how to use Omnichannel Inventory APIs with Salesforce Commerce APIs (aka B2C Commerce API) for Salesforce Order Management solutions. Once we set up our inventory integration, it will be used in the Order Fulfillment stage for allocation of the order items to the available location based on the items’ inventory availability.
There is one prerequisite before we start which is having a program that creates certificates (crypto library). If you don’t have any program installed, you can install OpenSSL. It’s an open source crypto library which I’ll show how to do it.
Using Commerce APIs will require a series of steps and the first one is configuring the environment.
If you already have an environment ready to use, then you can skip Setup Environment step and move to Create Certificate step.
Setup Environment
I’ll create a scratch org with minimum features & settings to have an environment ready for the next steps.
Create an Empty SFDX project and replace project-scratch-def.json
file content with the content at below. The new scratch definition file content has the necessary settings & features for the environment we will use.
{
"edition": "Enterprise",
"language": "en_US",
"features": [
"OrderManagement",
"OmnichannelInventory"
],
"settings": {
"orderSettings": {
"enableOrders": true,
"enableOrderEvents": true,
"enableNegativeQuantity": true,
"enableZeroQuantity": true,
"enableEnhancedCommerceOrders": true
},
"orderManagementSettings": {
"enableOrderManagement": true
},
"inventorySettings": {
"enableOmniChannelInventory": true
}
}
}
After replacing the content of the file, execute the following SF CLI command to create the scratch org.
sf org create scratch --alias commerceapi --definition-file config/project-scratch-def.json
Validate Omnichannel Inventory Provisioning
After creating the scratch org, be sure you received an email with the title Sandbox: Omnichannel Inventory Tenant Provisioning Succeeded.
If you receive an email saying that Sandbox: Omnichannel Inventory Tenant Provisioning Failed, delete the scratch org and re-create it until you receive a successful email. (You will most likely get the success email)
You can delete the scratch org with the following SF CLI command.
sf org delete scratch --target-org commerceapi
Certificate
Using Salesforce Commerce APIs for Salesforce Omnichannel Inventory will require OAuth 2.0 JWT Bearer Flow. Therefore, we will need a Connected App that uses a digital signature and for that, we will create a certificate and upload to Salesforce.
Install OpenSSL
If you already have a cryptography library installed on your computer, you can skip this step and move to Create Certificate step.
Download OpenSSL
Download OpenSSL (openssl-1.0.2j-fips-x86_64)
No installation is required, unzipping the folder into any location is enough i.e. C:\Users\OpenSSL
Set OpenSSL Path to Environment Variables
Simultaneously press Windows + R
and type sysdm.cpl
Go to Advanced > Environment Variables
You’ll see two types of variables: User Variables & System Variables. We’ll go with User Variables.
- Double click on variable Path
- Select New
- Add the path of OpenSSL (extracted) folder including bin directory
Validate OpenSSL Setup
Open any CLI or terminal application you have installed on your machine and execute the following command and you should see a similar response.
openssl version
Create Certificate
Create a new certificate folder on the desktop to organize the certificate and its related files. After, open the folder in a terminal.
1. Generate a private key
openssl genpkey -des3 -algorithm RSA -pass pass:commerceapi -out server.pass.key -pkeyopt rsa_keygen_bits:2048
2. Store it in a file called server.key
openssl rsa -passin pass:commerceapi -in server.pass.key -out server.key
You can delete the server.pass.key
file because it is no longer needed.
3. Generate a certificate signing request using the server.key
file. Store the certificate signing request in a file called server.csr
. Enter information about your company when prompted
openssl req -new -key server.key -out server.csr
4. Generate a self-signed digital certificate from the server.key
and server.csr
files. Store the certificate in a file called server.crt
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
5. Generate the public.key
file which will be used for JWT debugging & validation
openssl rsa -in server.key -pubout > public.key
Create Custom Scopes
Authorization for Omnichannel Inventory APIs requires scopes. These inventory scopes will be created in Salesforce and later, will be used in the Connected App.
Go to Setup > Identity > OAuth Custom Scopes > New Custom Scope
For each of the scope, enter Name & Description and then, save it (Leave Include on well known endpoint option as unchecked).
Name | Description |
---|---|
sfcc_inventory_impex_graphs | Export location graphs |
sfcc_inventory_impex_inventory_rw | Import inventory records |
sfcc_inventory_impex_inventory | Export inventory records |
sfcc_inventory_availability | Get inventory availability data |
sfcc_inventory_availability_rw | Update inventory availability data |
sfcc_inventory_reservations | Get inventory reservation information |
sfcc_inventory_reservations_rw | Update inventory reservations |
Total: 7 |
After adding the OAuth custom scopes, the page will look like this:
Create Connected App
The Connected App will be used to the get access token from Salesforce which will be used for Commerce API authorization.
Go to Setup > Apps > App Manager > New Connected App
- Enter Connected App Name
- Enter Contact Email
- Check Enable OAuth Settings
- Check Enable for Device Flow
- Enter Callback URL
- For production:
https://login.salesforce.com/services/oauth2/success
- For the others:
https://test.salesforce.com/services/oauth2/success
- For production:
- Check Use digital signatures & click Choose File. Upload
server.crt
file (from the certificates folder that we created before) - Add Selected OAuth Scopes
- Manage user data via APIs (api)
- Perform requests at any time (refresh_token, offline_access)
- Check Require Secret for Web Server Flow
- Check Require Secret for Refresh Token Flow & click Save & Continue.
After creating the connected app, we’ll copy the consumer secret and consumer key of the connected app which will be used later for authorization.
Click Manage Consumer Details (Salesforce will ask you to verify your identity).
- Copy Consumer Key (store somewhere temporarily)
- Copy Consumer Secret (store somewhere temporarily)
- Click Cancel or close the page
Navigate to the Connected App and click Manage > Edit Policies where we’ll configure OAuth policies.
- Select Admin approved users are pre-authorized for Permitted Users setting
- Select Relax IP retrictions for IP Relaxation setting
- Click Save
Now, let’s set the profile associated with this app. Click Manage Profiles and set the profile you desire. Since my user is admin, I’ll associate System Administrator with the connected app.
- Selected the profile for association
- Click Save
Now, we’ll add the custom Oauth scope we’ve created for the Connected App. Click Manage OAuth Custom Scopes button below to the Manage Profiles button. Select all the custom scopes (1) we created and click Save (2).
Connected App & Authorization via Salesforce CLI
So far we’ve created the certificate, the connected app and then we used the certificate in that connected app. Let’s use Salesforce CLI to validate our steps. Open any terminal or CLI app or Visual Studio Code to run the sf command.
This is the sf command we’ll execute to authorize:
sf org login jwt --username [username] --jwt-key-file [path] --client-id [consumerKey]
--username
The username of the organization.
--jwt-key-file
The path to the server.key file.
--client-id
The consumer key of the connected app.
Sf command with parameters with my details look like this:sf org login jwt --username test-dagkpcprnyie@example.com --jwt-key-file "C:\Users\firat\Desktop\blog\certificate\server.key" --client-id 3MVG9od6vNol.eBhQ7Qs0Oe.9UNNAf6.ODNsQDdfFQnqAjfsNp4Im..sxBVumdCm6Lqi6qG_WD1PBG72AkKIM
Generate JWT
We’ve everything we need to create a JWT (JSON Web Token) which will be used for Salesforce Omnichannel Inventory APIs.
To generate JWT, I’ll be using the free website https://jwt.io/
1. Select RS256 as Algorithm
2. Build the payload data{
"iss":"[consumer key of the connected app]",
"aud": "[instance url login/test.salesforce.com]",
"sub": "[username of the org user]",
"exp": [numericDate]
}
The payload for me will look like this:{
"iss":"3MVG9od6vNol.eBhQ7Qs0Oe.9UNNAf6.ODNsQDdfFQnqAjfsNp4Im..sxBVumdCm6Lqi6qG_WD1PBG72AkKIM",
"aud": "test.salesforce.com",
"sub": "test-dagkpcprnyie@example.com",
"exp": 1714239022
}
3. Paste the content of public.key file (open it with any text editor)
4. Paste the content of server.key file (open it with any text editor)
5. Click Share JWT (somewhere temporarily)
Get Access Token From Salesforce By Using JWT
Before the final step, which is using Commerce APIs and updating inventory, we’ll need the access token from Salesforce by using JWT. For this step, I’ll use Postman to send HTTP requests but any API platform or client would work.
- Select POST
- Set the endpoint login/test.salesforce.com
- Click Body and select x-www-form-urlencoded
- Set param key grant_type and the value as urn:ietf:params:oauth:grant-type:jwt-bearer
- Set param key assertion and the value as the JWT we generated and stored somewhere temporarily
- Click Send
- If everything goes well, you’ll see a similar response. Copy access_token and store somewhere temporarily
Send Requests to Salesforce Omnichannel Inventory
Finally, we are here to send some requests to Salesforce Omnichannel Inventory and update some numbers. In this step, I’ll use the Get Availability API by using the access token we grabbed previously, just to see if our approach works.
Base URLhttps://{{shortCode}}.api.commercecloud.salesforce.com/{{apiFamily}}/{{apiName}}/v1/organizations/{{organizationId}}/
Get Availability URLhttps://{shortCode}.api.commercecloud.salesforce.com/inventory/availability/v1/organizations/{organizationId}/availability-records/actions/get-availability
shortCode and organizationId values are org related. Therefore, we’ll navigate back to org to grab those values.
Go to Setup > Omnichannel Inventory
organizationId
can be found in Tenant Group IDshortCode
can be found in Base URL for Inventory API Calls
After puting the values, the Get Availability endpoint will look like this:https://GB.api.commercecloud.salesforce.com/inventory/availability/v1/organizations/d8dbf810-64c5-4bf3-aa87-83a0831ad18e/availability-records/actions/get-availability
- Select POST
- Set the endpoint URL
- Click Authorization tab, select Bearer Token and as the value paste the access token we grabbed from Salesforce (see Get Access Token From Salesforce By Using JWT)
- Select Authorization tab
- Select Bearer Token
- Set the access token we grabbed from Salesforce as token (see Get Access Token From Salesforce By Using JWT)
- Select Body, for body raw and paste this JSON content
{"sku":"ProductSku1","group":"Warehouse"}
- Click Send
As you can see, we received an error saying “there is no location group as Warehouse” which is correct. Our goal was to accomplish the authorization & authentication which is working. The next steps will be using Commerce APIs directly to update our inventory data.
You can also download the Postman collection which we built along the way.