3PL Warehouse Manager

Updated on January 19th, 2023

Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

  • Extensiv Hub
    Getting Started Using Hub Technical Issues & FAQs
  • 3PL Warehouse Manager
    Receiving Operations Inventory Management Shipping Operations System Configuration Scanning Operations Integrations Content Best Practice Resources Release Notes
  • Warehouse Manager
    Getting Started Admin Console Shipping Order Picking & Packing Receiving Customer Portal Cycle Counting Kit Building Managing Users Barcode Scanner Import/Export Integrations Barcoding Wave Picking Bin Move Mobile Receiving and Picking Settings
  • Order Manager
    Dashboard Orders Inventory Purchase Orders Shipments Customers Products Analytics Settings API API Integrations Accessing and Navigating Order Manager Error Messages Order Manager
  • Integration Manager
    General Support Order Sources Order Destinations Troubleshooting API Documentation Extras & Addons
  • FAQs
  • Support
+ More
  • Help Center
  • 3PL Warehouse Manager
  • Integrations Content
  • REST API
  • Integrations Content
    • EDI Processes
        • Getting Started with an EDI Integration
        • Extensiv Carton Label Library
        • EDI Processing
        • Setting Up FTP Email Notifications
        • Sending Receipt Advice
        • Printing UCC Labels
        • Sending an ASN
        • Troubleshooting ASN Errors
        • Using the Customer Error Log
        • Understanding Common EDI Errors
    • API Shopping Cart Integrations
        • Getting Started with Shopping Cart Integrations
        • ShipStation Integration
        • Shopify Shopping Cart Connection
        • WooCommerce Shopping Cart Connection
        • Amazon Shopping Cart Connection
        • Magento 2.x Shopping Cart Connection
        • Volusion Shopping Cart Connection
        • eBay Shopping Cart Connection
    • REST API
        • Getting Started with Credential Management
        • Providing REST API Access
        • Webhooks FAQs
        • Configuring Webhooks
        • Implementing Webhooks
    • QuickBooks Desktop
        • Connecting a QuickBooks Desktop Account
        • Connecting Customers to QuickBooks Desktop
        • Understanding Class Tracking
        • Understanding QuickBooks Desktop Billing Setup
    • QuickBooks Online
        • Connecting a QuickBooks Online Account
        • Connecting Customers to QuickBooks Online
        • Configuring Invoice Settings
        • Defining International Tax Codes
        • Understanding QuickBooks Online Billing Setup
    • SmartDock
        • Understanding SmartDock
        • SmartDock FAQs
        • Scheduling with an Existing Receipt
        • Scheduling and Creating a Receipt
        • Scheduling with an Existing Order
    • General Information
        • Whitelisting IP Addresses

Implementing Webhooks

To make the best use of webhook events, there are some general requirements and best practices that we recommend. This article reviews what external developers need to know to properly implement webhooks.

Recommendations

First and foremost, it is important to ensure that the HTTP endpoint (destination URL) is working properly before configuring webhooks.  Extensiv's webhooks system attempts to resend data in the case of failure, ensuring that the endpoint is working properly beforehand will save costs by reducing the data usage expended on message retries for failing endpoints.

We highly recommend the endpoint validates the validity of the message via its RSA signature before accepting and processing any data. (Read RSA signature and validation below.)

General process

Extensiv's webhooks are designed to wait for an endpoint's response for a maximum of three seconds before flagging the request as a delivery failure and forwarding the request to the retry mechanism. Because of this, endpoints should operate in the following order:

  1. Perform RSA validation to validate the message source
  2. Reply with an HTTP 20x success message
  3. Parse the message and process the message content

If your endpoint responds with an error (or if the webhook system fails to receive a success response from your endpoint), a linear retry mechanism will resend the message at regular intervals to allow the endpoint to recover. After the first failure at 180 seconds, the Lambda waits 180 x (number of attempts) until it has attempted to send the message a total of 15 times. This give the endpoint a six hour window to respond successfully to the message.

Any messages that fail 15 times are pushed to the "dead letter queue" where they are stored by Extensiv. If you need to access these messages, please contact api@3plcentral.com.

Payload structure

A webhook message contains the payload of an HTTP POST to the target URI with Content-Type: application/json. The message is used as the body of the request that the webhook Lambda forwards to the provided URL.

So that you can understand how to properly parse and access the data, below is an example of the message and resource structure of a webhook payload:

{
  "headers": {
    "Signature": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
"body": {
    "tplId": 2,
    "wmsEventId": 2070354,
    "dateTime": "2022-01-07T19:54:15.4770000",
    "eventType": "OrderConfirm",
    "resource": {
      "rel": "orders/order",
      "href": "/orders/206568?detail=OrderItems",
      "body": "{//<body content>}"
    },
    "links": "{\"uiproperties/user\": {\"LastModifiedBy\": \"/uiproperties/users/-1\"},\"customers/customer\":\"/customers/143\",\"properties/facility\":\"/properties/facilities/10\"}",
    "data": "{\"OrderId\":\"206568\"}",
    "tags": "Shipped"
  }
}
  • tplId: Unique 32-bit integer value assigned in the TPL master database when a TPL is created
  • wmsEventId: Primary key to the WMSEvent table—64-bit integer value unique within the TPL
  • dateTime: When the event occurred in UTC
    • Note: The webhooks system may deliver requests in a non-chronologic order—therefore, endpoints should not rely on delivery order of messages to be chronological. Instead, you sohuld utilize the dateTime value included in the payload for this purpose.
  • eventType: Member of the EventType enumeration in string form
  • resource: Specifies the resource that was the object of the eventType
    • rel: Reference to this kind of resource in the Rel documentation
    • href: Relative URL to GET the resource
    • body: Present only if IncludeResource=true (in the webhook configuration)—if present, its format is as described in the referenced Rel documentation
  • links: String in escaped-json form, containing selected Rel/Href pairs relevant to the resource
  • data: String in escaped-json form, containing selected fields relevant to the event
  • tags: If present, a comma-delimited list of tags describing the state of the resource as of the event

The JSON payload always comes through in UTF-8 for counting purposes. Extensiv counts the message size based on the content read in UTF-8, not including the RSA signature.

 

RSA signature and validation

To ensure that webhook messages have not been tampered with, a header named "Signature" is included in the http POST request. The RSA signature is created by the webhook Lambda, using SHA256 encryption against an internal RSA private key and passphrase to sign the message body into a base 64 string:

"headers":{
"Signature":"AG17G6BQpQOuzmYi6YXXvXip11DkU8/QQvaF+piYGbLJjtIP6883aU3klOGgGIF1tuSLACNwiXLmalk7z4W9gbtcgg=="
}

On the client-side, the following validation process can be used to ensure that the message body has not been tampered with:

Step 1: Retrieve the RSA public key through an HTTP GET request using endpoint https://secure-wms.com/events/webhook/key.

  • A "publicKey" attribute is returned, which contains the RSA public key's value.
  • A second attribute "retrievalDateISO" can be recorded client-side to track the date/time that the public key was last retrieved.
  • "previousRetrievalDateISO" may be included as an optional parameter in the body of the POST request. When included, a 304 status code and an empty request body will be returned in the case that the public key has not been updated since the previous retrieval date/time.

Step 2: Using a cryptography library that supports RSA validation, perform RSA validation on the request's message body using SHA256 encryption and base64 string format, validating with the RSA signature and public key. Ensure that validation on the message body using the header.Signature and retrieved RSA public key yields a successful validation. Here is an example of implementation in typescript:

  • RSA signature format: SHA256 encryption, base64 string
  • Public key format: pem
  • Public key type: spki
  • RSA signature: headers.Signature
  • RSA public key: Retrieved in Step 1 above

If validation fails, it may be due to using an outdated RSA public key. Options to avoid this situation include the following:

  • Ensure that the validation process always checks for an updated public key (Step 1 above) before attempting validation, or
  • Implement a fail-safe mechanism to retrieve the public key (from Step 1 above) and attempt validation a second time upon failing once.
/**
* @description Validates the RSA signed signature passed in with the request event using public key
* @param {requestEvent} request - The request event which should contain a body and a headers.Signature
* @returns true if validation is successful, false if validation fails
*/
function validateMessage(request: requestEvent): boolean {
//Check that the request has a body and a headers.Signature
if(request.body && request.headers && request.headers.Signature) { 
//Create the publicKey
const publicKey: KeyObject = createPublicKey({
'key': <RSA_Public_Key_Retrieved_From_Endpoint_In_Step_1>,
'format': 'pem',
'type': 'spki',
});
//Returns true if validation is successful, false if unsuccessful
return createVerify('SHA256').update(request.body)
.verify(publicKey, request.headers.Signature, 'base64')
}
return false;
}

Was this article helpful?

Yes
No
Share additional feedback about this article

Related Articles

  • Scheduling with an Existing Order
  • Adjusting Order Charges
  • July 8, 2020 – Minor Release Notes

Not finding the help you need?

Contact Support
Solutions
  • Solutions for Brands
  • Solutions for 3PLs
  • Solutions for 4PLs
  • Solutions for B2B
Products
  • Extensiv 3PL Warehouse Manager
  • Extensiv Warehouse Manager
  • Extensiv Order Manager
  • Extensiv Integration Manager
  • Extensiv Network Manager
Products
  • Customer Success
  • Implementation
  • Consulting
Ecosystem
  • Fulfillment Marketplace
  • Integrations
  • Partners
  • Become a Partner
Resources
  • Resource Library
  • Blog
  • Market Insights
  • What is a 3PL?
  • What is a 4PL?
  • What is a WMS?
  • Why a Cloud-based WMS?
  • Glossary
Help
  • Help Center
  • API Documentation
  • Extensiv Univerisity
  • Community
  • System Status
  • Extensiv Logo
  • 100 N Pacific Coast Hwy, Suite 1100, El Segundo, CA 90245
  • |
  • Contact Us:
  • 83-EXTENSIV 888.375.2368 (main)
  • |
  • 310.844.7570 (local)
  • Copyright © 2023 Extensiv
  • |
  • All rights reserved.
  • Privacy Policy
  • |
  • Terms of Service
  • Follow Us:
Expand