Guide to Datacake Webhooks: Features and Best Practices
Datacake is an IoT platform that collects data from LoRaWAN, MQTT, Particle and other devices, decodes it and stores it as measurements. Outgoing webhooks are how that data leaves Datacake: each time a measurement is recorded, a payload decoder runs or a downlink is sent, Datacake can post the details to your own system.
This guide covers how Datacake webhooks are configured and authenticated, what each of the three events contains, what Datacake leaves undocumented, and the practices that keep a Datacake receiver reliable.
What are Datacake webhooks?
A Datacake webhook belongs to a workspace. It has an endpoint URL, an optional description, a list of events to send and optional custom headers. When one of the chosen events happens anywhere in the workspace, Datacake sends a POST over HTTPS with a JSON body that names the event and carries its data.
Datacake does not sign webhooks. Its recommended way to authenticate them is a header you add yourself: a name such as Authorization and a secret value known only to Datacake and your receiver. Your endpoint compares the header with the value it has stored and rejects anything else. Datacake advises against IP allowlisting, because its cloud infrastructure scales up and down and the sending addresses are not reliable.
Two common uses are syncing measurements into your own database, and acting on decoder output that Datacake does not store, which avoids paying for that storage.
Datacake webhook features
| Feature | Details |
|---|---|
| Configuration | Workspace sidebar > Integrations > Webhooks |
| Scope | Per workspace, with the events you choose under Events to send |
| Method and format | POST over HTTPS, JSON body |
| Body | { "event": ..., "data": ... } |
| Events | device_measurement, decoder_output, downlink |
| Authentication | A custom header you add under Headers, such as Authorization: Bearer <token> |
| Signature and timestamp | None |
| Retries and timeout | Not documented |
| Source IPs | Not published; Datacake says IP allowlisting is unreliable |
| Monitoring | Seven-day request chart and error rate per webhook, plus recent requests with your server's responses |
Events and payloads
Every body has the same two keys: event, which names the event, and data, whose shape depends on it. Dispatch on event.
Device measurements
device_measurement fires only when new measurement values are written to the database. data is an array of rows, and it holds only the fields inserted by the device's last message, not every field on the device. A device that sends one field per MQTT message produces one row per webhook.
{
"data": [
{
"field": "TEMPERATURE",
"value": 19.141228,
"device": "f7384fd1-9e7f-4540-b4ed-5fa5810bcc27",
"timestamp": 1647852981
},
{
"field": "HUMIDITY",
"value": 66.95572,
"device": "f7384fd1-9e7f-4540-b4ed-5fa5810bcc27",
"timestamp": 1647852981
}
],
"event": "device_measurement"
}
timestamp is in Unix seconds and device is the Datacake device ID. In Datacake's longer example the same field appears more than once with different timestamps, so store each row rather than assuming one value per field.
Decoder output
decoder_output carries the raw output of a device's payload decoder, the same data you see in the device debug view. data.result is the array the decoder returned, data.log holds console output and data.device holds device information for LoRaWAN and Particle device types. Both log and device can be null, and a row whose field had no value has no value key.
{
"data": {
"log": null,
"device": null,
"result": [
{
"field": "PM25",
"value": 4.88,
"device": "dev:864475044240892"
},
{
"field": "RSSI",
"device": "dev:864475044240892"
}
],
"product": "ef6275c7-3e9b-4134-9bef-24bc276a9592",
"execution_time": 664535
},
"event": "decoder_output"
}
A decoder normally returns a list of field, value and device entries for Datacake to store. Because the webhook forwards whatever the decoder returns, you can add extra information that Datacake ignores but your system uses.
Downlinks
downlink fires whenever a downlink is sent to a LoRaWAN or MQTT device, whether someone sent it by hand or a rule sent it automatically.
{
"data": {
"meta": {
"type": "lorawan",
"fport": 1,
"downlink": "a6895656-8198-41fe-9c0e-f49074311190"
},
"device": "a52e6324-2cf9-4534-b523-819d94299414",
"payload": "AQI=",
"product_id": "4e8e8623-18c4-4798-9877-699058a00e24",
"product_slug": "temperatur-dach"
},
"event": "downlink"
}
payload is the downlink bytes in base64.
Inspect Datacake webhooks as they arrive. Point a webhook at a Hookdeck Inspect URL to see each request's headers and body, with no account or setup required.
Setting up Datacake webhooks
Generate a long random token first, for example with openssl rand -hex 32.
- In the workspace sidebar, open Integrations > Webhooks and click Add Webhook.
- Enter your HTTPS Endpoint URL and, if you like, a Description.
- Under Events to send, choose the events you need.
- Under Headers, add your secret header. Datacake's example uses the name
Authorizationand the valueBearer ABC123; use your own token in place ofABC123. Any header name works. - Click Create Webhook.
To route through Hookdeck, create a Hookdeck source with the Datacake type and use its URL as the webhook's endpoint URL. Datacake webhooks are not signed, so add a secret header under Headers on the webhook and enter it in the source:
- API Key Header: the header name you used in Datacake, such as
Authorization. Hookdeck looks it up case-insensitively. - API Key: the header's whole value, exactly as you typed it in Datacake. If the value is
Bearer <token>, enterBearer <token>, includingBearerand the space.
The source accepts POST only, which is the method Datacake uses.
Securing Datacake webhooks
Read the header you chose, compare its whole value with the one you stored in constant time, and reject the request if either is missing. Do the check before you parse the body.
const crypto = require('crypto');
const express = require('express');
const HEADER_NAME = process.env.DATACAKE_WEBHOOK_HEADER || 'Authorization';
const HEADER_VALUE = process.env.DATACAKE_WEBHOOK_SECRET; // e.g. "Bearer <token>"
function safeEqual(received, expected) {
const a = Buffer.from(received, 'utf8');
const b = Buffer.from(expected, 'utf8');
// timingSafeEqual throws on unequal lengths, so check first.
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
const app = express();
app.post('/webhooks/datacake', express.raw({ type: '*/*' }), (req, res) => {
const received = req.get(HEADER_NAME);
if (!HEADER_VALUE || typeof received !== 'string' || !safeEqual(received, HEADER_VALUE)) {
return res.sendStatus(401);
}
let body;
try {
body = JSON.parse(req.body.toString('utf8'));
} catch {
return res.sendStatus(400);
}
// Store body.event and body.data, respond, then process asynchronously.
res.sendStatus(200);
});
The same check in Python:
import hmac
import os
HEADER_NAME = os.environ.get("DATACAKE_WEBHOOK_HEADER", "Authorization")
HEADER_VALUE = os.environ.get("DATACAKE_WEBHOOK_SECRET", "") # e.g. "Bearer <token>"
def verify_datacake_request(headers) -> bool:
if not HEADER_VALUE:
return False # never accept when unconfigured
received = headers.get(HEADER_NAME) # case-insensitive in Starlette and Flask
if not received:
return False
# Compare bytes: compare_digest raises TypeError on a non-ASCII str.
return hmac.compare_digest(received.encode("utf-8"), HEADER_VALUE.encode("utf-8"))
The header value is static. It authenticates the sender, not the body, and with no timestamp a captured request can be replayed. Datacake sends every request over HTTPS, so the token is encrypted in transit; keep it out of repositories and shared documents, and rotate it if it might have leaked. Datacake also suggests rotating tokens periodically.
Make Datacake webhooks production-ready. Hookdeck Event Gateway checks the header you configure, stores every measurement durably, and retries delivery to your service on a schedule you set.
Datacake webhook limitations and pain points
Delivery guarantees are not documented
The Problem: You cannot tell from the docs what happens to a measurement when your endpoint is down or slow.
Why It Happens: Datacake documents the events and the payloads, but not a timeout, a retry policy or a way to resend a failed request. The webhook list shows the error rate and the recent requests with your server's responses, which tells you something failed but not whether Datacake tried again.
Workarounds:
- Respond with a
2xxas quickly as you can and process the data afterwards. - Check the error rate in the webhook list after deployments and outages.
- If you need a complete history, compare what you received with the data stored in Datacake after an outage.
How Hookdeck Can Help: Hookdeck accepts each request as soon as it arrives and stores it, then delivers to your service with retries you configure. You can replay any request after a fix, and issues tell you when deliveries start failing.
One webhook carries the whole workspace
The Problem: A single endpoint receives measurements from every device, and the volume grows with your fleet.
Why It Happens: Webhooks are configured per workspace and per event, not per device or product. Every measurement from every device that records one is sent, and a device that sends a field per message produces a request per field.
Workarounds:
- Choose only the events you need under Events to send.
- Batch database writes on your side instead of writing each row as it arrives.
How Hookdeck Can Help: Hookdeck filters can route on event, on a device ID or on a field, and you can cap the delivery rate to your service so a burst of uplinks never overwhelms it.
The payload is not a stable schema
The Problem: Code that expects every field to have a value, or one row per field, breaks on real data.
Why It Happens: decoder_output forwards whatever the decoder returns, including fields with no value, null logs and extra keys your decoder adds. device_measurement contains only the fields in the latest message and can repeat a field with different timestamps.
Workarounds:
- Treat a missing
valueas "no reading", not zero. - Key stored rows on device, field and timestamp.
- Version your decoder's extra output if other systems depend on it.
How Hookdeck Can Help: Hookdeck transformations can normalise the body, for example by dropping rows with no value, before it reaches your service.
No signature and no stable IPs
The Problem: You have only a static header to tell Datacake's requests apart from anyone else's.
Why It Happens: Datacake does not sign the body and does not publish a stable set of sending IPs.
Workarounds:
- Use a long random token, compare it in constant time and rotate it periodically.
- Store measurements idempotently, so a replayed request does no harm.
How Hookdeck Can Help: Hookdeck's Datacake source compares the header you name with the exact value you enter. Hookdeck answers with a 200 either way, but requests that fail the check are recorded as failed verification and never reach your service.
Best practices
Always add a secret header
A webhook without one sends nothing your endpoint can check. Use a long random value, and give each environment its own.
Compare the whole value
If you typed Bearer <token> in Datacake, compare against Bearer <token>, not the token alone. Datacake's own troubleshooting notes warn about whitespace and encoding problems in the header value, so copy it exactly.
Store measurements idempotently
Use device, field and timestamp as a natural key so the same row arriving twice is written once. See our guide to webhook idempotency.
Acknowledge fast and process asynchronously
Check the header, store the body, return 200, and do the database work afterwards. See why to process webhooks asynchronously.
Watch the error rate
Datacake's webhook list shows the error rate and your server's recent responses. Check it after every deployment of your receiver.
Conclusion
Datacake sends device_measurement, decoder_output and downlink events as JSON POST requests over HTTPS, with no signature and no documented retry policy. Add a long random secret header to every webhook, compare its whole value in constant time, respond quickly, and store measurements so that repeats do no harm.
Hookdeck Event Gateway checks the header, keeps every request, and retries and replays delivery to your service, so an outage on your side does not leave gaps in your device data.
Get started with Hookdeck for free and handle Datacake webhooks reliably in minutes.