Setup Webhooks in ChannelDock
Last updated
Why use webhooks?
ChannelDock provides webhooks to inform your system immediately when something changes in your account. Instead of polling the API on a schedule, you automatically receive a notification when an order is created or updated, a shipment is created, stock levels change or a return is registered. Webhooks help you automate processes and reduce unnecessary API requests.
Key features
- Event timing: Webhooks fire some minutes after an event occurs, giving you near realtime updates.
- Payload consistency: The JSON payload of a webhook matches the structure returned by the corresponding API endpoint.
- Automatic retries: If ChannelDock can’t deliver a webhook, up to five attempts are made with increasing delays (0, 30, 60, 120 and 240 seconds). After ten failed deliveries the webhook is disabled for safety.
- Security: Each webhook can have its own secret key. When a secret is set, ChannelDock signs every delivery with an HMAC-SHA256 signature in the
X-Channeldock-Signatureheader, so you can verify that a request really came from ChannelDock.
Setting up a webhook
-
Navigate to the settings: Log in to ChannelDock and go to Settings → API & Webhooks. You will see two sections: API keys and Webhooks.
-
Create a new webhook: Click Create new webhook. A “Webhook Configuration” window appears.
-
Fill in the fields:
- Webhook name: Choose a descriptive internal name (for example, “Order updates”).
- Webhook URL: Enter the URL of your endpoint where ChannelDock may send an HTTP POST request to. Make sure this URL is publicly reachable and responds within 5 seconds.
- Event to trigger webhook: Select the type of event you want notifications for. Possible events include
order.created,order.updated,order.status.changed,order.picking,order.picked,order.deleted,shipment.created,stock.updated,return.created,return.handledandreturn.product.updated. - Status: Leave this set to Active. Webhooks are automatically deactivated after 10 failed delivery attempts.
- Webhook secret (optional but recommended): Provide your own secret or click Generate to create a strong secret. ChannelDock uses this secret to sign every delivery, so you can verify that the request came from ChannelDock and was not changed along the way.
-
Save: Click Save webhook. ChannelDock stores your webhook and will send events of the type you selected to your endpoint.
Payload structure and events
When a chosen event occurs, ChannelDock sends a JSON payload to your endpoint. The payload contains at least the following fields:
{
"event": "order.created",
"payload": {
...
},
"signature": "<hash>" (legacy, see below)
}
- event – the event for which the webhook was configured (for example
order.created). - payload – contains details of the order, shipment, return or stock mutation. The structure matches the API response for the corresponding object.
- signature – only present when a secret is configured. This is the old signature and it is deprecated; verify the
X-Channeldock-Signatureheader instead.
Verifying the signature
Your webhook URL has to be publicly reachable, and the request carries no other proof of who sent it — no API key, no password. So anything that reaches that URL looks like a genuine ChannelDock delivery to your endpoint: a URL that leaked through a log file, a proxy or a support ticket, or an earlier delivery that someone captured and sent again. If you act on the contents without checking, a faked stock.updated could set your stock to zero, or a faked order.updated could mark an order as shipped in your own system.
The signature is the missing proof. Only you and ChannelDock know the secret, so only the two of you can produce a value that matches the delivery in front of you.
When you set a webhook secret, every delivery for that webhook arrives with an extra HTTP header:
X-Channeldock-Signature: sha256=8b415f2c0cd241a21109e007942b6ce43cbfcf97f7b2d7829084258c0ae0a66f
That value is an HMAC-SHA256 hash of the request body, calculated with your secret as the key. You calculate the same hash on your side and check that the two are identical. If no secret is set, the header is not sent.
Verifying the signature in your application
- Read the raw body. Take the request body as text or bytes, before the JSON is parsed. Most frameworks parse JSON and throw the original text away, so ask for it explicitly:
php://inputin PHP,$request->getContent()in Laravel,request.get_data()in Flask,request.bodyin Django,request.raw_postin Rails, orexpress.json({ verify: (req, res, buf) => { req.rawBody = buf } })in Express. - Read the header. Take
X-Channeldock-Signatureand remove thesha256=prefix. Look the header up case-insensitively — depending on the connection it can arrive asx-channeldock-signature. - Calculate your own hash. An HMAC-SHA256 of the raw body with your webhook secret as the key, written as hexadecimal. In PHP that is
hash_hmac('sha256', $raw, $secret). - Compare using a constant-time function such as
hash_equals. If the two are identical the delivery is genuine and you can process it. If not, return HTTP 401 and ignore the body. Only parse the JSON once this step succeeds.
Important: hash the body exactly as you received it. A signature is a hash of bytes, not of the meaning of the JSON. So do not parse the JSON and convert it back to text in order to hash it. Two languages can write JSON that means exactly the same thing but is not the same text: PHP writes a forward slash as c\/o where Node.js and Python write c/o. Those read back as identical data, but produce completely different hashes. Do not remove the signature field before hashing either — it is part of the body that was signed.
The legacy signature field
Before the header existed, ChannelDock put a signature field in the body itself. It is still sent and unchanged, so existing integrations keep working, but it is deprecated. Verifying it means removing the field and rebuilding the rest of the JSON as text exactly the way PHP writes it, including PHP’s habit of writing / as \/, which is nearly impossible to get right in another language.
Build new integrations against the header. If you verify the field today nothing breaks: both are sent on every delivery, so you can switch whenever it suits you. The two values are never the same, because they cover different data — never compare one against the other.
Tips for secure processing
- Assign each webhook its own secret and rotate it regularly.
- Use a constant‑time comparison function (for example
hash_equalsin PHP orcrypto.timingSafeEqualin Node.js) to prevent timing attacks. - Verify the signature before you act on the contents of the payload.
- Perform additional checks on the contents of the payload (for example verify that the order exists) before executing any actions.
Best practices
ChannelDock recommends several practices to process webhooks safely and reliably:
- HTTP‑200 response: Let your endpoint return an HTTP 200 OK as soon as the payload has been successfully received. Otherwise ChannelDock sees the attempt as failed and tries again.
- Idempotency: Webhook messages may sometimes be sent twice (for example due to network issues or retries). Make sure your processing logic is idempotent so duplicate messages don’t cause duplicate work.
- Monitoring: Use the ChannelDock dashboard to monitor the status of your webhooks and identify any errors.
- Payload handling: Ensure that your endpoint can handle large payloads and responds within a reasonable time (≤ 5 seconds). Webhooks are automatically deactivated after ten failed deliveries.
Was this helpful?