User Tools

Site Tools


webhooks

CCRM Webhook Documentation

Setup

To receive webhook events, you will need to provide a valid webhook URL to the CCRM system. The system will send POST requests to this URL with the event data in the request body. You can create as many or as few endpoints as you see fit, but each event will have a different payload, and require different business logic to process. So creating a single endpoint for each event is not recommended.

Validation and Authentication

To validate that the request is coming from CCRM, you can use the X-Signature header. The value of this header is a SHA256 hash of the request body, and will look something like this: t=<timestamp>,v1=<sha256 hash>

To validate the authenticity of the request, you will need to recompute the hash using the provided timestamp, request body, and secret key. Since trying to stringify the request body may end up resulting in a different hash, you will need to receive the request body as a raw string. You can then compare hashes using the following example. This example assumes you are using Node.js, but it should be the same idea for any other language:

const crypto = require('crypto')
 
function validateRequest(rawPayload, timestamp, signature) {
  const secretKey = SECRET_KEY;
  const signedPayload = `${timestamp}.${rawPayload}`;
 
  const hash = crypto
    .createHmac('sha256', secretKey)
    .update(signedPayload)
    .digest('hex');
 
  return hash === signature;
}

For extra security, you will want to also add your own payload validation logic, using the examples below to see what the payload schema should look like.

Webhook Events

1. inventory.update

Body:

{
  "id": "event ID as UUID",
  "eventName": "inventory.update",
  "payload": {
    "available": "number",
    "partNumber": "string",
    "manufacturer": "string",
    "maxUnitPrice": "number",
    "minUnitPrice": "number",
    "avgUnitPrice": "number"
  }
}

2. excess.create

Body:

{
  "id": "event ID as UUID",
  "eventName": "excess.create",
  "payload": {
    "excessName": "string",
    "excessNumber": "number",
    "excessDate": "string in format YYYY-MM-DD",
    "showAsStock": "boolean",
    "obscureQty": "boolean",
    "doNotMarket": "boolean",
    "vendor": "string",
    "lineItems": [
      {
        "quoteNumber": "number",
        "currencyChar": "string",
        "currencyCode": "string",
        "unitPrice": "number",
        "partNumber": "string",
        "internalPartNumber": "string",
        "manufacturer": "string",
        "quantity": "number",
        "totalStock": "number",
        "dc": "string",
        "rohs": "string",
        "leadTime": "string",
        "minimum": "number",
        "maximum": "number",
        "countryOfOrigin": "string",
        "package": "string",
        "certification": "string",
        "condition": "string"
      }
    ]
  }
}

3. excess.update

Body:

{
  "id": "event ID as UUID",
  "eventName": "excess.update",
  "payload": {
    "excessName": "string",
    "excessNumber": "number",
    "excessDate": "string in format YYYY-MM-DD",
    "showAsStock": "boolean",
    "obscureQty": "boolean",
    "doNotMarket": "boolean",
    "vendor": "string",
    "lineItems": [
      {
        "quoteNumber": "number",
        "currencyChar": "string",
        "currencyCode": "string",
        "unitPrice": "number",
        "partNumber": "string",
        "internalPartNumber": "string",
        "manufacturer": "string",
        "quantity": "number",
        "totalStock": "number",
        "dc": "string",
        "rohs": "string",
        "leadTime": "string",
        "minimum": "number",
        "maximum": "number",
        "countryOfOrigin": "string",
        "package": "string",
        "certification": "string",
        "condition": "string"
      }
    ]
  }
}

4. excess.delete

Body:

{
  "id": "event ID as UUID",
  "eventName": "excess.delete",
  "payload": {
    "excessNumber": "number"
  }
}

Error Handling

Proper error handling and response codes are important to ensure that the webhook does not unnecessarily make retry attempts for errors that will never pass (like authentication errors), as well as to help ensure that we are properly logging the errors, so we can fix any issues that are caused by our side.

webhooks.txt · Last modified: by admin

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki