Webhooks provide a mechanism for automated communication between applications. When specific events are triggered within your integration with our API, we send a notification containing an event payload with the relevant data.
For example, when a shipment status is updated for one of your users, our system will send an event that includes the shipment details and its new status. This allows you to deliver real-time updates to your users or process the payload as needed.
To enable event notifications, you must configure a webhook URL in your application settings. This can be done through our business web app by navigating to Settings > API Settings and updating your webhook URL. Proper configuration ensures your system receives event data promptly for further processing or integration with your workflow.
Rules to Know
When setting up a webhook for your application, keep the following considerations in mind:
Ensure that the endpoint is configured to accept POST requests.
The timeout for our webhook is 30 seconds. If your webhook processing is resource-intensive, consider handling it asynchronously to avoid timeouts.
Perform a test request on your endpoint to confirm it can successfully receive and process the payload.
Additionally, in production, webhooks are sent every 30 minutes, whereas in the Sandbox/Staging environment, webhooks are dispatched every 5 minutes.
Listening to Events
constcrypto=require('crypto');constexpress=require('express');constbodyParser=require('body-parser');constapp=express();app.use(bodyParser.raw({ type:'application/json' }));constsecret="your_secret_key";app.post('/webhook', (req, res) => {constpayload=req.body; // Raw bodyconstreceivedSignature=req.headers['x-signature'];// Generate the HMAC signature using the secret keyconstcalculatedSignature= crypto.createHmac('sha256', secret).update(payload).digest('hex');// Compare the calculated signature with the received oneif (crypto.timingSafeEqual(Buffer.from(calculatedSignature),Buffer.from(receivedSignature))) {// Signature is validres.status(200).send('Valid signature'); } else {// Invalid signatureres.status(403).send('Invalid signature'); }});app.listen(3000, () => {console.log('Server is listening on port 3000');});
import hmacimport hashlibfrom flask import Flask, request, abortapp =Flask(__name__)secret =b'your_secret_key'@app.route('/webhook', methods=['POST'])defwebhook(): payload = request.data received_signature = request.headers.get('X-Signature')# Generate the HMAC signature using the secret key calculated_signature = hmac.new(secret, payload, hashlib.sha256).hexdigest()# Compare the calculated signature with the received oneif hmac.compare_digest(calculated_signature, received_signature):return'Valid signature',200else:abort(403, 'Invalid signature')if__name__=='__main__': app.run(port=3000)
require'sinatra'require'openssl'secret ="your_secret_key"post '/webhook'do request.body.rewind payload = request.body.read received_signature = request.env['HTTP_X_SIGNATURE']# Generate the HMAC signature using the secret key calculated_signature =OpenSSL::HMAC.hexdigest('sha256', secret, payload)# Compare the calculated signature with the received oneif calculated_signature == received_signature status 200 body 'Valid signature'else status 403 body 'Invalid signature'endend
packagemainimport ("crypto/hmac""crypto/sha256""encoding/hex""fmt""io/ioutil""net/http")const secret ="your_secret_key"funcmain() { http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {// Get the raw POST body (payload) payload, err := ioutil.ReadAll(r.Body)if err !=nil { http.Error(w, "Cannot read payload", http.StatusBadRequest)return }// Get the signature from the headers receivedSignature := r.Header.Get("X-Signature")// Generate the HMAC signature using the secret key h := hmac.New(sha256.New, []byte(secret)) h.Write(payload) calculatedSignature := hex.EncodeToString(h.Sum(nil))// Compare the calculated signature with the received oneif hmac.Equal([]byte(calculatedSignature), []byte(receivedSignature)) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "Valid signature") } else { w.WriteHeader(http.StatusForbidden) fmt.Fprintf(w, "Invalid signature") } }) http.ListenAndServe(":3000", nil)}
<?php// Receiver side// The secret key (shared between the sender and receiver)$secret ="your_secret_key";// Get the signature from the headers$receivedSignature = $_SERVER['HTTP_X_SIGNATURE'];// Get the raw POST data (payload)$payload =file_get_contents('php://input');// Generate the hash using the same secret key$calculatedSignature =hash_hmac('sha256', $payload, $secret);// Compare the calculated signature with the received oneif (hash_equals($calculatedSignature, $receivedSignature)) {// Signature is valid, proceed with processing the webhook event} else {// Invalid signature, reject the requesthttp_response_code(403);exit('Invalid signature');}?>