Webhooks Documentation
Changes from v1.4
- Transfer mode 2 is now described as Cellular, including NB-IoT connections.
The webhook JSON structure and numeric transfer-mode values are unchanged from v1.4.
About
traplinked offers webhooks to be notified instantly about different device related events.
Setting up a webhook
Webhooks are managed in the traplinked web app under Integrations → Webhooks. Access is controlled by the Locations permissions of your role for the organization:
| Locations permission | Allows |
|---|---|
| Read | Open the Integrations page and view the webhook list. |
| Create | Create a webhook. |
| Update | Edit a webhook, including enabling and disabling it. |
| Delete | Delete a webhook. |
The predefined roles Administrator (Organization admin), Manager (Management user), Technician and Location management user have all four. Viewer and Read only user can only view webhooks. A custom role needs the corresponding Locations permissions.
- Open Integrations → Webhooks and click Create webhook.
-
Fill in the fields:
Field What to enter Name A label for your own reference. URL The HTTPS endpoint that should receive the events, e.g. https://example.com/webhooks/traplinked.Method POST(default, recommended).PUT,PATCH,GETandDELETEare also available. The method only changes the HTTP verb: the event is always sent as a JSON body, even withGETandDELETE. UsePOSTunless your endpoint requires otherwise: proxies and frameworks often drop the body ofGETandDELETErequests, which breaks signature verification.Report types The event types you want to receive. Only events of the selected types are delivered. Enabled Leave off until your endpoint is ready, then switch on. Nothing is delivered while the webhook is disabled. -
In the Headers section, select the webhook version (
traplinked-Version). Choose the latest version unless you have a specific reason to use an older one. The version determines the payload format described on this page. - Optionally add further headers with Add header. Every row you add is sent unchanged with each request, except for the reserved keys listed under request headers. Use this for your own authentication, for example
Authorization: Bearer <token>. - To enable signature verification, add a header row with the key
traplinked-HMAC-Secretand your shared secret as the value. See configuring the HMAC secret. This header is not sent to your endpoint; it is only used to compute the signature. - Save the webhook and switch it to Enabled.
All header values are stored encrypted. After saving, the web app shows them as ******** and the stored value is never returned to the browser. Only the version is shown in clear, in the picker. When you edit a webhook:
- Rows you leave untouched keep their stored value.
- To change a value, type the new value over the mask.
- If you rename a key, the stored value cannot be carried over and you must enter the value again.
The webhook list shows the last response code and the time of the last request, which helps when checking whether your endpoint accepts the requests.
If you cannot use the web app, contact us at api@traplinked.com and we will register the webhook for you.
Event types
The following table lists all supported event types together with applicable device types.
| Name | Device types | Description |
|---|---|---|
| trap_triggered | JERRY, TrapMe | A trap has triggered. Supported devices change their status to false triggered or catch detected, other devices follow the previous behavior receiving the status triggered. |
| catch_detected | TrapMe, Trapsensor, JERRY LoRa | A catch has been detected. |
| rearmed | JERRY, JERRY LoRa, JERRY Bait Rat, TrapMe, Trapsensor | A trap was rearmed / Bait has been replaced |
| offline | JERRY, JERRY LoRa, JERRY Bait Rat, TOM, Trapsensor | A device is offline. |
| online | JERRY, JERRY LoRa, JERRY Bait Rat, TOM, Trapsensor | A device is back online. |
| configured | JERRY, TOM | A device was configured. |
| maintained | JERRY, TOM | A device was maintained. |
| battery_low | JERRY, JERRY LoRa, JERRY Bait Rat, TOM, TrapMe, Trapsensor | The battery of a device is low. |
| image_received | TOM | An image was received. |
| false_triggering | JERRY LoRa, TOM, Trapsensor | False triggering event. |
| activity_noticed | JERRY Bait Rat | Activity was noticed on the bait pad. |
| activity_threshold_reached | JERRY Bait Rat | Activity threshold has been reached. |
| bait_low | JERRY Bait Rat | Bait level is low. |
| activity_threshold_reached_and_bait_low | JERRY Bait Rat | Activity threshold reached and bait is low. |
Requests
- Requests use the method selected for the webhook in the web app:
POSTby default, orPUT,PATCH,GETorDELETE. - The payload is sent as a JSON body with every method, including
GETandDELETE. - Responses are expected to be received within two seconds.
- No redirects are allowed.
Request Headers
Custom headers are configured per webhook in the web app and are sent unchanged with every request, with these exceptions:
traplinked-Versionis not entered as a custom header. It is selected with the version picker in the web app and is sent with every request.Content-Type,User-Agentandtraplinked-Request-Timestampare always set by traplinked. A custom header with one of these keys is replaced.traplinked-HMAC-Secretis removed before the request is sent. It is only used to compute the signature.traplinked-HMAC-SHA256is set by traplinked when an HMAC secret is configured and replaces any custom value. Without a secret, a custom row with this key is sent as entered, so never put your secret under this key.
All other keys are sent exactly as entered. Keys must be unique per webhook. Keys are case-sensitive: enter reserved keys exactly as written here, otherwise they are treated as ordinary custom headers and sent to your endpoint.
Generic Headers
The following standard headers are set:
| Name | Description | Value |
|---|---|---|
| User-Agent | User agent of the traplinked webhook. | traplinked-webhook/v1.5 |
| Content-Type | Content type of the request. | application/json |
traplinked Headers
traplinked specific headers always start with the prefix traplinked-. Currently the following headers are sent:
| Name | Description |
|---|---|
| traplinked-Version | Required. The version of the webhook, as selected in the web app. Example: v1.5 |
| traplinked-Request-Timestamp | The UTC timestamp when the request was sent. A new value is set for every request, including retries. Example: 2022-01-01T00:00:00 |
| traplinked-HMAC-SHA256 | HMAC-SHA256 of the request in hex format. Only computed by traplinked if an HMAC secret is configured for the webhook. Example: 3a07d62d5bbd… |
One further key is used for configuration only and is never sent:
| Name | Description |
|---|---|
| traplinked-HMAC-Secret | The shared secret used to compute traplinked-HMAC-SHA256. Entered as a header row in the web app and removed before sending.See configuring the HMAC secret. |
HMAC
It's recommended to verify each request using an HMAC. The hash algorithm used is SHA-256, the signature is sent hex-encoded in the traplinked-HMAC-SHA256 header. The signature is computed over the raw request body with the value of traplinked-Request-Timestamp appended directly, without a separator:
HMAC-SHA256(secret, request_body + traplinked-Request-Timestamp)
To verify a request, compute the same value with your copy of the secret and compare it to the header. Use the raw body bytes as received; re-serializing the JSON may change the byte sequence and break the comparison.
Configuring the HMAC secret
The secret is configured per webhook in the web app. Add a header row with the key traplinked-HMAC-Secret and the secret as the value (see setting up a webhook). Any string can be used as the secret; we recommend at least 32 random bytes, for example the output of openssl rand -hex 32.
traplinked-HMAC-Secret is a configuration key only. It is removed before the request is sent and never reaches your endpoint. Do not enter the secret under the key traplinked-HMAC-SHA256: that key is reserved for the signature, and no signature is computed without a traplinked-HMAC-Secret entry.
Without an HMAC secret traplinked does not add the traplinked-HMAC-SHA256 header. See request headers for how a custom row with this key is handled.
Example
Using the secret 12345 and the traplinked-Request-Timestamp 2022-01-01T00:00:00, the resulting HMAC-SHA256 is
3a07d62d5bbd79505f3e672018000d84676330a73db96ca7052708006d8b62db
if the following request body was sent:
{"event":{"type":"trap_triggered","uuid":"080c1300-fbfe-4d11-8b86-bdd4ad2d92b4","timestamp":"2022-01-01T00:00:00","data":{"device":{"serial_number":"TESTDEVICE1","name":"TESTDEVICE1","type":0,"description":"","battery_status":1,"status":3,"last_heartbeat":"2022-01-01T00:00:00","transfer_mode":0,"operation_mode":0,"trap_1":true,"trap_2":false}}}}
Computation is performed on the concatenation of the request body and the request timestamp:
{"event":{"type":"trap_triggered","uuid":"080c1300-fbfe-4d11-8b86-bdd4ad2d92b4","timestamp":"2022-01-01T00:00:00","data":{"device":{"serial_number":"TESTDEVICE1","name":"TESTDEVICE1","type":0,"description":"","battery_status":1,"status":3,"last_heartbeat":"2022-01-01T00:00:00","transfer_mode":0,"operation_mode":0,"trap_1":true,"trap_2":false}}}}2022-01-01T00:00:00
Request Body
The request body is sent in JSON format containing a single event object which contains the following fields:
| Name | Description |
|---|---|
| type | The event type as described in event types. Example: trap_triggered |
| uuid | A unique identifier. Example: 080c1300-fbfe-4d11-8b86-bdd4ad2d92b4 |
| timestamp | Date and time in UTC the event was triggered. Example: 2022-02-22T20:22:22 |
| data | The payload object. See event data for details. |
Event data
The content of the event data depends on the event type and the device type of the event. In this version the data object itself consists of a device object. The device object has the following fields.
| Name | Type | Required | Description |
|---|---|---|---|
| name | String | yes | Name of the device. |
| serial_number | String | yes | Serial number of the device. Example: 1A2B3C4D |
| type | Integer | yes | The device type. See device type section. |
| status | Integer | yes | The status of the device. See device status section. |
| battery_status | Decimal | yes | Battery status of the device. A value between 0.0 and 1.0. |
| transfer_mode | Integer | yes | Connection type. See transfer mode section for further details. |
| operation_mode | Integer | yes | Device operation mode. See operation mode section for further details. |
| description | String | no | Device description. |
| last_heartbeat | Datetime | no | Last time the device connected to the server in UTC. Example: 2022-01-01T00:00:00 |
| latitude | Decimal | no | Latitude of the device. |
| longitude | Decimal | no | Longitude of the device. |
| trap_1 | Bool | no | Status of trap_1true for triggered, false for not triggered. null for JERRY Bait Rat devices. |
| trap_2 | Bool | no | Status of trap_2true for triggered, false for not triggered. null for JERRY Bait Rat devices. |
| image_timestamp | Datetime | no | Date and time the image was taken in UTC. Example: 2022-01-01T00:00:00 |
| image_data | String | no | Data URI of the image. Example: data:image/jpeg;base64,... |
| is_bait_monitoring_enabled | Bool | no | Whether bait monitoring is enabled. Only available for JERRY Bait Rat devices, null for other device types. |
| bait_low_count | Integer | no | Bait low count. Only available for JERRY Bait Rat devices, null for other device types. |
| bait_pad_activity_count | Integer | no | Bait pad activity count. Only available for JERRY Bait Rat devices, null for other device types. |
| activity_alert_threshold | Object | no | Activity alert threshold. See activity alert threshold section for further details. Only available for JERRY Bait Rat devices, null for other device types. |
| bait_manufacturer_and_type | String | no | Bait manufacturer and type. Only available for JERRY Bait Rat devices, null for other device types. |
| bait_weight_grams | Integer | no | Bait weight in grams. Only available for JERRY Bait Rat devices, null for other device types. |
| bait_calibration_weight_grams | Integer | no | Remaining bait weight (threshold) calibration in grams. Only available for JERRY Bait Rat devices, null for other device types. |
| last_bait_replaced_at | Datetime | no | Last time bait was replaced in UTC. Example: 2022-01-01T00:00:00. Only available for JERRY Bait Rat devices, null for other device types. |
| last_bait_replaced_by_name | String | no | Name of user who last replaced bait. Only available for JERRY Bait Rat devices, null for other device types. |
| last_activity_reset_at | Datetime | no | Last time activity was reset in UTC. Example: 2022-01-01T00:00:00. Only available for JERRY Bait Rat devices, null for other device types. |
| last_activity_reset_by_name | String | no | Name of user who last reset activity. Only available for JERRY Bait Rat devices, null for other device types. |
| is_bait_available | Bool | no | Whether bait is available. Only available for JERRY Bait Rat devices, null for other device types. |
Device Type
| Type | Description |
|---|---|
| 0 | JERRY |
| 1 | JERRY LoRa |
| 2 | TrapMe |
| 3 | TOM |
| 4 | Trapsensor |
| 5 | JERRY Bait Rat |
Device Status
| Status | Description |
|---|---|
| 0 | Device is inactive. |
| 1 | Device is active / Bait is available (JERRY Bait Rat) |
| 2 | Heartbeat failed |
| 3 | Device has been triggered. |
| 4 | Battery is low. |
| 6 | Unstable Wi-Fi connection |
| 7 | Light infestation |
| 8 | Severe infestation |
| 9 | False triggered |
| 10 | Activity warning |
| 11 | Activity critical |
| 12 | Catch detected |
| 13 | Bait low |
| 14 | Activity critical and bait low |
For JERRY Bait Rat devices, "Activity critical" (status 11) and "Activity critical and bait low" (status 14) indicate that the configured activity threshold has been reached. The activity threshold defines the number of activity events within a specific timeframe (see activity alert threshold) that triggers the status change.
Transfer Mode
| Mode | Description |
|---|---|
| 0 | Wi-Fi |
| 1 | LoRa |
| 2 | Cellular |
Operation Modes
| Mode | Description |
|---|---|
| 0 | Snaptrap mode |
| 1 | Movement mode |
| 2 | Insect mode |
| 3 | Bait mode |
Activity Alert Threshold
The activity alert threshold is an object with the following fields. This field is only available for JERRY Bait Rat devices and null for other device types.
| Name | Type | Description |
|---|---|---|
| threshold_value | Integer | Activity threshold. When the number of activities exceeds this value within the specified timeframe, the device receives status 11 and report type 22 is sent |
| timeframe_value | Integer | Number of days or hours during which activities are counted toward the threshold |
| timeframe_type | String | Unit of the timeframe. Possible values: "d" (days), "h" (hours) |
Example
{
"event": {
"type": "trap_triggered",
"uuid": "080c1300-fbfe-4d11-8b86-bdd4ad2d92b4",
"timestamp": "2022-01-01T00:00:00",
"data": {
"device": {
"serial_number": "TESTDEVICE1",
"name": "TESTDEVICE1",
"type": 0,
"description": "",
"battery_status": 1,
"status": 3,
"last_heartbeat": "2022-01-01T00:00:00",
"transfer_mode": 0,
"operation_mode": 0,
"trap_1": true,
"trap_2": false,
"is_bait_monitoring_enabled": null,
"bait_low_count": null,
"bait_pad_activity_count": null,
"activity_alert_threshold": null,
"bait_manufacturer_and_type": null,
"bait_weight_grams": null,
"bait_calibration_weight_grams": null,
"last_bait_replaced_at": null,
"last_bait_replaced_by_name": null,
"last_activity_reset_at": null,
"last_activity_reset_by_name": null,
"is_bait_available": null
}
}
}
}
Response
A successful response returns a response code between 200 and 299 with a response body of at most 2000 bytes; an empty body is fine. Your endpoint should respond within two seconds; redirects are not followed.
Retries
If the endpoint responds with any other status code, is unreachable, times out, or returns a response body larger than 2000 bytes, the request is queued and retried up to 5 times. Retries are at least one minute apart. Each retry is a new request:
traplinked-Request-Timestampandtraplinked-HMAC-SHA256are recomputed for every attempt, so the signature must be verified against the timestamp of that attempt.event.uuidandevent.timestampstay the same across all attempts of the same event. Useevent.uuidto deduplicate if your endpoint acknowledged a request after our timeout.
After the fifth failed attempt the event is dropped and not delivered again. The webhook stays enabled, and the last response code in the webhook list shows the latest failure.