Using Webhooks
Published by Jake Hookom on April 4, 2021
Last updated on May 23, 2024
The OrderCloud API supports user-defined HTTP callbacks, known as webhooks. Webhooks are easy to register for your entire marketplace or on an application specific level. You can choose exactly which OrderCloud API endpoints will trigger your hook, the roles to be passed onto the configured Base URL, and any additional configuration data OrderCloud may need to authenticate into 3rd party systems.
Webhooks can only be triggered by OrderCloud endpoints that write to the database (POST, PUT, PATCH, DELETE). The request body sent to the OrderCloud endpoint (if any) will be passed along to the webhooks that use it.
There are two types of webhooks you can use with OrderCloud:
Post-Hook ideal for replicating state changes to another database (analytics) or firing other events, such as sending a text notification to a user
Pre-Hook used for validating incoming requests, such as validating an address being written or updated
Creating Your Webhook
Webhooks can be written in any language to receive an HTTPS request, but we recommend you use OrderCloud Catalyst to ease creation of strongly typed webhooks in C# (which also includes examples).
To better understand what OrderCloud sends in webhooks, here is an update to a buyer v1/buyers/buyer_10
:
1{2 "Route": "v1/buyers/{buyerID}",3 "RouteParams": {4 "buyerID": "buyer_10"5 },6 "QueryParams": {}7 "Verb": "PUT",8 "Date": "2021-04-04T19:41:39.6504645+00:00",9 "LogID": "71ce120a-17d5-4833-89f6-4f9a33ddd42f",10 "UserToken": "...",11 "Request": {12 "Body": {13 "Active": true,14 "Name": "New Name Updated",15 "xp": {16 "segment": "Foo"17 }18 },19 "Headers": null20 },21 "Response": {22 "Body": {},23 "Headers": null24 },25 "ConfigData": {26 "config_key": "config_value"27 }28}
Route the original route requested against OrderCloud
RouteParams the passed path identifiers for requests like PUT which update objects
QueryParams: the passed query parameters on the url route
Verb the type of request used
Date the timestamp of the request
LogID for correlating back to any support with OrderCloud
UserToken the JWT token of the user who requested the original request
Request.Body what was passed in the original request, be mindful that PATCH can be partially populated requests
Request.Headers passed headers from the original request
Response if this was a Post-Webhook, then this would be populated with the response from OrderCloud
ConfigData optional data you configure with your original webhook within OrderCloud
Verifying the Webhook Request
OrderCloud will optionally pass an x-oc-hash
header which is a fingerprint for the request, based on a secret you can optionally define when you register your webhook in OrderCloud. You may want to do this in order to verify that any request sent to your webhook can be trusted and is actually from OrderCloud.
Verifying this fingerprint happens automatically when you use OrderCloud Catalyst (code sample below), but you can do this yourself with a SHA256
using your registered secret, and hashing the passed request and comparing the Base64
value to the value passed in the x-oc-hash
header.
1public bool VerifyWebhookHashAsync(string requestHash, string requestBody, OrderCloudWebhookAuthOptions options)2{3 Require.That(!string.IsNullOrEmpty(options.HashKey),4 new InvalidOperationException("OrderCloudWebhookAuthOptions.HashKey was not configured."));56 Require.That(!string.IsNullOrEmpty(requestBody), new WebhookUnauthorizedException());7 Require.That(!string.IsNullOrEmpty(requestHash), new WebhookUnauthorizedException());89 var bodyBytes = Encoding.UTF8.GetBytes(requestBody);10 var keyBytes = Encoding.UTF8.GetBytes(options.HashKey);11 var hash = new HMACSHA256(keyBytes).ComputeHash(bodyBytes);12 var computed = Convert.ToBase64String(hash);1314 Require.That(requestHash == computed, new WebhookUnauthorizedException());15 return true;16}
Sending a Pre-hook Response
Only applicable for pre-webhooks, you return a basic JSON structure on if you should proceed
true or false, and an optional body
which can be any JSON object or literal value.
1{2 "proceed": false,3 "body": {4 "customMessage": "Not a Valid Address",5 "suggestions": [6 ...7 ]8 }9}
If you set proceed
to false
, then an error message will be sent back to the original caller and includes the body
data you provided for the client to act upon or use.
Register Your Webhook
Back in the OrderCloud Console create a new webhook
General Information
Name internally available name or label to use
Description optional information you want to add on your webhook
Secret relates to the
x-oc-hash
where OrderCloud will use this secret to generate a fingerprint you can validate againstPayload URL where your webhook is publicly available
Pre-hook if you want this hook to fire before updating OrderCloud is done processing
DeliveryConfigID if you wish to delivery the webhook request payload using the Delivery Configuration mechanism of your choice. This type does not support the Pre-hook option. When specified, Secret and Payload URL are ignored.
API Client Assignments
Webhooks will only fire for the API Clients you specify. This is ideal when you may have multiple API clients setup, representing different store fronts and behavior. If you want the webhook to fire for all your different API clients, then simply check each one in the portal UI.
Configuration Data
These are optional key value pairs you can setup and will be passed with each request. Think in terms of shared plugins where you may want to pass other registration or account information to a 3rd party tax or shipping service.
Trigger Events
This is where you register one or more operations you want to attach your webhook to in OrderCloud. Example, if you want to listen for all updates to Buyers, you would want to register POST, DELETE, PATCH, and PUT
Elevated Roles
Elevated roles relay an access_token
with higher permissions than the client that triggered the webhook. For example, if an authenticated user only had the UserAdmin role but our webhook needed to list Categories and perform some other action, we would add CategoryReader to the ElevatedRoles
. For this example we will choose FullAccess here and save the webhook.
Webhook Registration Example
The following example registers a webhook for all of the Buyer endpoints
1{2 "ID": "...",3 "Name": "sample-webhook",4 "Description": "Sample Description",5 "Url": "https://.../mywebhook",6 "HashKey": "...",7 "ElevatedRoles": [8 "BuyerAdmin"9 ],10 "ConfigData": {11 "config_key": "config_value"12 },13 "BeforeProcessRequest": true,14 "ApiClientIDs": [15 "...."16 ],17 "WebhookRoutes": [18 {19 "Route": "v1/buyers",20 "Verb": "POST"21 },22 {23 "Route": "v1/buyers/{buyerID}",24 "Verb": "DELETE"25 },26 {27 "Route": "v1/buyers/{buyerID}",28 "Verb": "PATCH"29 },30 {31 "Route": "v1/buyers/{buyerID}",32 "Verb": "PUT"33 }34 ]35}
Creating Reusable Plugins
3rd parties looking to create reusable plugins to replicate data or validate data written to OrderCloud could offer URLs where support for multiple OrderCloud customers or organizations could be based on the following:
Secret an agreed secret that will be used to validate the incoming
x-oc-hash
headerConfig Data you can specify one or more properties to be passed from OrderCloud which may represent your services ID the mutual customer is registered under
Deployment of these services could either be through GitHub as integration code the customer could deploy themselves and freely modify to map extended properties (XP) or other fields they may map differently per instance, or as a global service endpoint that you host and OrderCloud customers simply point at and use.
In both cases, the deployment would ideally be a serverless function which keeps cost and maintenance down to nothing to provide reusable integrations.
Still have questions?
Ask in our Community Channel