Webhooks Overview

Webhooks provide a mechanism for you to receive an event notification when something occurs in your account or a partner's account.  Webhooks push information to an account's destination instead of requiring you to continuously pull information via the Dsco API to stay up-to-date.

Callback Definition

A callback is the process of the Dsco system sending data to a customer's system via a URL (http://some.customer.com/callback/url) when something of interest to the customer occurs in the Dsco system.

Event Types

Currently, Dsco will send an event notification for three types of Dsco data changes...

  • ORDER_CREATED
    Dsco will trigger ORDER_CREATED registered webhooks when a new order is created inside the Dsco system for any reason - file-imported order, manually created via the portal
  • ORDER_UPDATED
    Dsco will trigger ORDER_UPDATED registered webhooks when an order is updated inside the Dsco system for any reason - file-imported order, manually updated via the portal
  • INVOICE_CREATED
    Dsco will trigger ORDER_UPDATED registered webhooks when a new invoice is created inside the Dsco system.
  • INVOICE_UPDATED
    Dsco will trigger INVOICE_UPDATED registered webhooks when an invoice is updated inside the Dsco system.
  • INVENTORY_UPDATED
    Dsco will trigger INVENTORY_UPDATED registered webhooks when a item is updated inside the Dsco system (by default triggered when any attribute of an item changes)
    • quantityStateChangeOnly
      If true, DSCO will only trigger these webhooks when the quantity of an item changes from 0 to greater than 0 or when the quantity changes from greater than 0 to 0 or when the quantity was 0 and an update from a supplier occurs that keeps the inventory at 0
    • quantityChangeOnly
      If true, DSCO will trigger these webhooks only when the quantity changes
  • ORDER_LINE_ITEM_STATUS_UPDATED
    The purpose of this type of webhook is to allow a customer to be aware when a line item of an order ships or is cancelled.

    Dsco will only trigger this event you have done both of these things...
    • Contact Support and Turn On Capability
      Email support at support@dsco.io and ask them to turn on the ORDER_LINE_ITEM_STATUS_UPDATED webhook capability.
    • Create webhook
      Create a webhook whose event type is ORDER_LINE_ITEM_STATUS_UPDATED.

And when the following condition is met...

  • An order Line Item ships or is cancelled associated with you
    Each time DSCO detects an order line item is newly shipped or cancelled whose order is associated with you are one of your partners the webhook will be trigger and you will receive a WebhookEvent.

Anatomy of a Webhook

The Dsco system will make an HTTP POST to the callback URL specified in a webhook.  The body of the HTTP Post will contain the Webhook Event JSON object that contains either an Order if the webhook event is for ORDER_CREATED or ORDER_UPDATED or an ItemInventory object if the webhook event is for INVENTORY_UPDATED.  Note that the content type of the HTTP request made to your callback requires that your server accept JSON.  Also note that the content is encoded using UTF-8.  Below you will find the raw HTTP request made to a callback URL...

POST / HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=UTF-8
charset: utf-8
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_65
Host: my.mock.host.com
Content-Length: 693
Content-MD5: NTc3MTlkMDA3MDE5NzNmNmYzZWVmZWNlOWM1MTZlZWE=

{"webhookUuid":"eee79154-0622-4597-bfbb-2e3ebc846659","event":"ORDER_UPDATED","eventDate":"2015-05-18T16:32:04.610+0000","payload":{"poNumber":"12345","lineItems":[{"dscoItemId":9981717171,"sku":"ABCDSku","quantity":1},{"dscoItemId":992824222,"sku":"ABCDESku","quantity":1}],"shipping":{"attention":"","firstName":"Jane","lastName":"Doe","company":"","address1":"100 Main Street","address2":"","city":"Coppell","region":"TX","postal":"75019","country":"US","phone":"2147001111","email":""},"shipInstructions":"","dscoOrderId":101,"dscoStatus":"created","dscoRetailerId":102,"dscoSupplierId":101,"dscoCreateDate":"2015-05-14T18:50:39.000+0000","dscoLastUpdate":"2015-05-14T18:50:40.000+0000"}}

The customer's callback URL should return a succes (200) http status code.  Any non-200 status code will be ignored, although it will be logged in the Dsco system.

Webhook Security

DSCO Webhooks include an HTTP request header named Content-MD5 which is a hash of the JSON body of the webhook using the partner's OAuth Access Token.  Partners should hash the JSON payload of the Webhook and compare the generated hash to the value in the Content-MD5 header and if different should ignore the Webhook as invalid.

 The following explains the exact algorithm partners should use to generate the hash...

 Get the JSON body of the request as a string

  1. Use the HMAC sha256 alrogrithm using the partner's OAuth Access Token and the JSON string to generate the hash.
  2. Convert the hash into a hex string
  3. Compare the generated hash to the one provided in the Content-MD5 http request header
  4. If not the same, discard the request

Here's a few code examples...

//********** Node JS Complete Sample
var http = require('http');
var crypto = require('crypto');

var server = http.createServer(function(req, res)
{
    var accessToken = "dda73bd8-4163-429c-ab8d-4f5bd9ce87c1";
    var fullBody = '';
    
    req.on('data', function(chunk)
    {
        fullBody += chunk.toString();
    });
    
    req.on('end', function()
    {
      res.writeHead(200, 'OK', {'Content-Type': 'text/html'});

      console.log(fullBody);
      
      var receivedHash = req.headers['content-md5'];
      var generatedHash = crypto.createHmac('sha256', accessToken).update(fullBody).digest('hex').toString();
      
      console.log('Received hash: ' + receivedHash);
      console.log('Generated hash: ' + generatedHash);
      
      if (receivedHash.toLowerCase() == generatedHash.toLowerCase())
      {
          console.log('Hashes match - this is a valid request!');
      }
      else
      {
          console.log('Hashes don\'t match - this is NOT a valid request!');
      }
      
      res.end();
    });
});
server.listen(8080);

// Console output from the above web server receiving a webhook

{"webhookUuid":"8f223cf7-ecbc-4686-a30e-5d9f40d8589e","event":"INVENTORY_UPDATED","eventDate":"2016-09-14T19:00:00.397+0000","payload":{"dscoItemId":11,"dscoSupplierName":"my acme supplier","dscoSupplierId":102,"dscoCreateDate":"2012-05-11T15:00:00.000+0000","dscoLastQuantityUpdateDate":"2012-05-11T15:00:00.000+0000","dscoLastCostUpdateDate":"2012-05-11T15:00:00.000+0000","dscoLastUpdateDate":"2012-05-11T15:00:00.000+0000","sku":"acme101","title":"my acme 101 product","quantityAvailable":100,"cost":2.33,"status":"in-stock","estimatedAvailabilityDate":"2012-05-11T15:00:00.000+0000","quantityOnOrder":500,"currencyCode":"USD"}}
Received hash: 3F0FBD5C41ACD795CBE3702AFBE6EDBDCFBB14D44BFCD90FEDF68E678FE084B0
Generated hash: 3f0fbd5c41acd795cbe3702afbe6edbdcfbb14d44bfcd90fedf68e678fe084b0
Hashes match - this is a valid request!

//**********End Node JS Sample

// PHP Sample
hash_hmac("sha256", $jsonPayloadAsString, $partnerOauthAccessToken);

// Python Sample
import hashlib, hmac
hmac.new(partnerOauthAccessToken, jsonPayloadAsString, hashlib.sha256).hexdigest();

Custom Http Headers

Partners may include one or more custom http headers that will be included as an http request header on the http post of the webhook by adding the desired headers to the customHttpHeaders attribute of a webhook.

Webhook Best Practices

Partners should make an API call to DSCO to verify that all data was sent to the Partner.  For example, lets assume a supplier has registered a webhook that should send all new orders to the supplier.  Assume the supplier's server had a hiccup when DSCO tried to send a new order to the partner's API endpoint and the order couldn't be sent.  What happens in this case?  DSCO does not retry webhooks.

 To ensure all orders are received, the supplier should periodically call the Get New Orders API to find any orders that have not been handled yet.  Of course, this means that for each new order received from a webhook the supplier should turn around and acknowledge the order by calling the Acknowledge Order API to change its status from "New" to "Acknowleged" and ensure that the received order would not be returned in subsequent calls to the Get New Orders API.

Webhook Scenarios

Dsco uses the webhookAccountId attribute of a registered webhook to determine which webhooks match and should be triggered.  Here are a few scenarios...

Supplier Account ID: 101

Supplier Callback URL: http://acme.supplier.com/callbacks

Retailer Account ID: 102

Retailer Callback URL: http://acme.retailer.com/callbacks

Relationship: Supplier 101 fulfills orders for supplier 102

Retailer wants a callback when own orders are created

If a retailer wanted to receive callbacks to his own system for some reason whenever a new order was created in his own account in Dsco then the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me of my own created orders",
    "event":"ORDER_CREATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Supplier wants a callback when trading partner orders are created

If a supplier (account ID 101) wanted to receive callbacks whenever his trading partner (account ID 102) created an order in the Dsco system the supplier would create the following Webhook:

{
    "owningAccountId":101,
    "webhookAccountId":102,
    "description":"Notify me when my trading partner creates orders",
    "event":"ORDER_CREATED",
    "callbackUrl":"http://acme.supplier.com/callbacks"
}

Supplier wants a callback when trading partner orders are created in a specific assortment

If a supplier (account ID 101) wanted to receive callbacks whenever his trading partner (account ID 102) creates an order in the Dsco system only for those orders in assortment 200 or 201 the retailer would create the following Webhook:

{
    "owningAccountId":101,
    "webhookAccountId":102,
    "description":"Notify me when my trading partner creates orders in assortments 200 or 201",
    "event":"ORDER_CREATED",
    "callbackUrl":"http://acme.supplier.com/callbacks",
    "assortmentIds":[200,201]
}

Supplier wants a callback when trading partner orders are updated

If a supplier (account ID 101) wanted to receive callbacks whenever his trading partner (account ID 102) updated an order in the Dsco system the supplier would create the following Webhook:

{
    "owningAccountId":101,
    "webhookAccountId":102,
    "description":"Notify me when my trading partner updates orders",
    "event":"ORDER_UPDATED",
    "callbackUrl":"http://acme.supplier.com/callbacks"
}

Supplier wants a callback when trading partner orders are updated in a specific assortment

If a supplier (account ID 101) wanted to receive callbacks whenever his trading partner (account ID 102) updates an order in the Dsco system only for those orders in assortment 200 or 201 the retailer would create the following Webhook:

{
    "owningAccountId":101,
    "webhookAccountId":102,
    "description":"Notify me when my trading partner updates orders in assortments 200 or 201",
    "event":"ORDER_UPDATED",
    "callbackUrl":"http://acme.supplier.com/callbacks",
    "assortmentIds":[200,201]
}

Retailer wants a callback when any of its orders is updated

If a retailer (account ID 102) wanted to receive callbacks whenever any order created by the retailer is updated, regardless of which supplier the order is associated with , the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me when any of my orders are updated",
    "event":"ORDER_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback when trading partner inventory is updated

If a retailer (account ID 102) wanted to receive callbacks whenever his trading partner (account ID 101) updates item inventory in the Dsco system the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":101,
    "description":"Notify me when my trading partner updates inventory",
    "event":"INVENTORY_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback when trading partner inventory is updated in a specific catalog

If a retailer (account ID 102) wanted to receive callbacks whenever his trading partner (account ID 101) updates item inventory in the Dsco system only for those items in catalog 200 or 201 the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":101,
    "description":"Notify me when my trading partner updates inventory",
    "event":"INVENTORY_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks",
    "catalogIds":[200,201]
}

Retailer wants a callback when trading partner inventory quantity changes state

If a retailer (account ID 102) wanted to receive callbacks whenever his trading partner (account ID 101) updates item inventory in the Dsco system such that the inventory quantity changes from less than 1 to more than zero or vice versa the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":101,
    "description":"Notify me when my trading partner inventory changes quantity state",
    "event":"INVENTORY_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks",
    "quantityStateChangeOnly": true
}

Retailer wants a callback when any trading partner's inventory quantity changes state

If a retailer (account ID 102) wanted to receive callbacks whenever any of his trading partner's item inventory udpates in the Dsco system such that the inventory quantity changes from less than 1 to more than zero or vice versa the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me when any of my trading partner's inventory changes quantity state",
    "event":"INVENTORY_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks",
    "quantityStateChangeOnly": true,
    "applyToPartners": true
}

Retailer wants a callback when any trading partner's inventory quantity changes

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me when any of my trading partner's inventory changes quantity state",
    "event":"INVENTORY_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks",
    "quantityChangeOnly": true,
    "applyToPartners": true
}

Supplier wants a callback when own invoices are created

If a supplier wanted to receive callbacks to his own system for some reason whenever a new invoice was created in his own account in Dsco then the supplier would create the following Webhook:

{
    "owningAccountId":101,
    "webhookAccountId":101,
    "description":"Notify me of my own created invoices",
    "event":"INVOICE_CREATED",
    "callbackUrl":"http://acme.supplier.com/callbacks"
}

Retailer wants a callback when trading partner invoices are created

If a retailer (account ID 102) wanted to receive callbacks whenever his trading partner (account ID 101) created an invoice in the Dsco system the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":101,
    "description":"Notify me when my trading partner creates invoices",
    "event":"INVOICE_CREATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback when any trading partner invoices are created

If a retailer (account ID 102) wanted to receive callbacks whenever any of his trading partner's invoices are created in the Dsco system the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me when my any of my trading partners creates invoices",,
    "event":"INVOICE_CREATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback when trading partner invoices are updated

If a retailer (account ID 102) wanted to receive callbacks whenever his trading partner (account ID 101) updated an invoice in the Dsco system the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":101,
    "description":"Notify me when my trading partner updates invoices",
    "event":"INVOICE_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback when any trading partner invoices are updated

If a retailer (account ID 102) wanted to receive callbacks whenever any of his trading partner's invoices are updated in the Dsco system the retailer would create the following Webhook:

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me when my any of my trading partners updates invoices",,
    "event":"INVOICE_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback whenever an order line item ships or is cancelled for any order the retailer created

{
    "owningAccountId":102,
    "webhookAccountId":102,
    "description":"Notify me when an order line items ships or is cancelled for any order I created",
    "event":"ORDER_LINE_ITEM_STATUS_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Retailer wants a callback whenever an order line item ships or is cancelled that was fulfilled by a given supplier

{
    "owningAccountId":102,
    "webhookAccountId":101,
    "description":"Notify me when any order line items ships or is cancelled for an order fulfilled by the given supplier",
    "event":"ORDER_LINE_ITEM_STATUS_UPDATED",
    "callbackUrl":"http://acme.retailer.com/callbacks"
}

Supplier wants a callback whenever an order the supplier fulfilled ships or is cancelled

{
"owningAccountId":101,
"webhookAccountId":101,
"description":"Notify me when an order line items ships or is cancelled that I fulfilled",
"event":"ORDER_LINE_ITEM_STATUS_UPDATED",
"callbackUrl":"http://acme.retailer.com/callbacks"
}

Supplier wants a callback whenever an order line item ships or is cancelled that was created by given retailer and fulfilled by the supplier

{
"owningAccountId":101,
"webhookAccountId":102,
"description":"Notify me when an order line items ships or is cancelled that was created by the given retailer and that I fulfilled",
"event":"ORDER_LINE_ITEM_STATUS_UPDATED",
"callbackUrl":"http://acme.retailer.com/callbacks"
}
Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.