Webhook documentation

How to add a webhook, its payload and security recommendations.

Shake Typing avatar
Written by Shake Typing
Updated over a week ago

Add a new webhook

1. Visit your workspace administration β€Ί Apps

Sign into your Shake dashboard and visit workspace apps administration.

2. Choose a desired app

Select the application for which you wish to add a webhook integration.

3. Add a webhook

In the "User feedback integrations" box β†’ click "Add New" β†’ select "Webhook"

4. Enter the endpoint URL

Put the URL where you want Shake to send requests whenever a new ticket arrives β†’ click "Connect" and you are done! From this point on, Shake will send POST requests to the entered URL for every new ticket.


Webhook payload

When a new ticket arrives, Shake will send a POST request to the webhook URL with a payload containing the ticket information. Here is an example of a payload object you will receive:

{
"app_id": "0c62c4c8-1721-4cc5",
"app_user": {
"banned": false,
"city": null,
"country": null,
"created": "2023-04-06T13:26:08.269624",
"end_user_id": "61A8272F-0969-4B91",
"id": "7d3fa7e2",
"metadata_": {
"cartItems": "3",
"cartTotal": "$25.33",
"email": "john.doe@email.com",
"first_name": "John",
"last_name": "Doe",
"status": "Active"
},
"permalink": "https://app.shakebugs.com/wsp/users/H9L/7d3fa",
"tickets_count": 0,
"updated": "2023-06-15T09:11:22.127302"
},
"app_user_id": "7d3fa7e2",
"app_version": "1.0",
"assignee": {
"assignee_id": null
},
"authentication": 1,
"available_disk_space": 488164.20703125,
"available_memory": 5652.546875,
"battery_level": 0.64,
"battery_status": 1,
"build_version": "11",
"city": "Zagreb",
"country": "Croatia",
"created": "2023-06-20T14:20:09.478958",
"current_view": "ShakingVC",
"custom_fields": [],
"device": "iPhone14,2",
"device_orientation": 1,
"files": [],
"font_scale": null,
"id": "6354ae0a-be5d-4a73",
"issue_reported_time": "2023-06-20T14:18:27.809000+00:00",
"key": 146,
"locale": "en_HR",
"low_power_mode": false,
"metadata_": null,
"network_name": "",
"network_type": "wifi",
"nfc": null,
"os_version": "16.3.1",
"permalink": "https://app.shakebugs.com/wsp/user-feedback/H9L/8",
"permissions": [],
"pretty_app_version": "1.0 (11)",
"pretty_authentication": "Required",
"pretty_battery_status": "64% \u2022 Unplugged",
"pretty_device_name": "iPhone 13 Pro",
"pretty_device_orientation": "Portrait",
"pretty_font_scale": null,
"pretty_is_portrait_mode": true,
"pretty_locale": "en-HR",
"pretty_location": "Zagreb, Croatia",
"pretty_low_power_mode": "Turned off",
"pretty_memory_status": "86% \u2022 4852 out of 5653 MB",
"pretty_network_status": "WiFi",
"pretty_nfc": null,
"pretty_os": "iOS 16.3.1",
"pretty_resolution": "2532 \u2715 1170 px",
"pretty_screen_density": null,
"pretty_screenshot_url": "https://shk.s3.amazonaws.com/5a.tiff",
"pretty_session": null,
"pretty_storage_status": "8% \u2022 40.4 out of 476.7 GB",
"pretty_tester_email": "Not available",
"pretty_time": "Jun 20, 2:18 PM",
"pretty_timezone": "Europe/Zagreb",
"pretty_title": "There\u2019s a bug on this pic.",
"pretty_used_application_memory": "72 MB",
"pretty_xcode_version": "Xcode 13.1 (13A1030d)",
"priority": {
"priority": "Medium"
},
"report_type": "manual",
"screen_density": null,
"screen_height": 2532,
"screen_width": 1170,
"screenshot_url": "https://shk.s3.amazonaws.com/5a.tiff",
"sdk_version": "15.1.0",
"status": {
"status": "New"
},
"tags": [
{
"active": true,
"created": "2021-12-30T16:02:28.237531",
"id": "5ebb2702-86ef-4d92-9c67",
"name": "suggestion",
"team_id": "5a41c131-4811-438e-b096",
"updated": "2021-12-30T16:02:28.237534"
},
{
"active": true,
"created": "2022-02-23T13:43:56.866333",
"id": "f83f26c5-516b-4a72-b701",
"name": "question",
"team_id": "5a41c131-4811-438e-b096",
"updated": "2022-02-23T13:43:56.866336"
}
],
"tester_email": "",
"timezone": "Europe/Zagreb",
"title": "There\u2019s a bug on this pic.",
"unique_fingerprint": "b5e515a7dfa016d196d678f9",
"updated": "2023-06-20T14:20:10.650667",
"used_application_memory": 71.90625,
"used_disk_space": 41407.62890625,
"used_memory": 4852.328125,
"video_url": null,
"xcode_build": "13A1030d",
"xcode_version": "1310"
}


Validation

For security purposes, it is recommended to validate the webhook payload to ensure the data is actually coming from Shake servers.

A webhook secret is generated as soon as you click "Connect" for the first time and is then available in the Webhooks settings. It is used to generate a signature on your server. By comparing this signature with the one sent by Shake, you can verify that the data is legitimate.

Here are two examples how you can generate the signature:

Python

import hmac
import hashlib

webhook_secret = "<WEBHOOK_SECRET>"
payload = "<PAYLOAD>"

webhook_secret_bytes = bytes(webhook_secret, 'utf-8')
payload_bytes = bytes(payload, 'utf-8')
signature = hmac.new(webhook_secret_bytes, payload_bytes, digestmod=hashlib.sha256).hexdigest()

JavaScript (Node.js)

const crypto = require("crypto")

const WEBHOOK_SECRET = "<WEBHOOK_SECRET>"
const rawBody = "<RAW_BODY>"
const signature = crypto.createHmac("sha256", WEBHOOK_SECRET).update(rawBody).digest("hex")

In these code snippets, replace <WEBHOOK_SECRET> with the Webhook Secret from Shake, and <PAYLOAD> or <RAW_BODY> with the body of the request sent to your server. To validate the data, after you have generated the signature on your server, compare it with the shakebugs-signature header sent in the request.

The Python and JavaScript examples above are two ways of generating the signature, but this can be done in any programming language that supports HMAC SHA256.

Did this answer your question?