Webhooks
Learn how to set up webhooks for your application.
How Webhooks Work
cside Webhooks are an easy way to get notifications about important events in your cside account. Webhooks can be used to trigger actions in your application, send messages to your Discord or Slack channels, and more.
When you create a webhook endpoint, we will send a POST request to the URL you have specified. The request will contain a JSON payload with information about the event that triggered the webhook.
The Data Structure
We will always send you a structured JSON payload with the following fields:
Prop
Type
Events
Below is the event IDs and their payloads that will be sent with webhooks.
Event IDs
| ID | Name | data Object |
|---|---|---|
| alert.created | Alert Created | Alert Object |
Event Objects
HMAC Secret (aka x-cside-signature)
We compute an HMAC on the fly, using a SHA256 hash of the payload and your webhook secret that was provided to you when you first created the webhook endpoint. This signature is included in the x-cside-signature header of the request.
WE HIGHLY SUGGEST YOU USE THIS TO VERIFY THE REQUEST IS COMING FROM cside: Not doing so could leave you vulnerable to replay attacks.
Verifying the HMAC secret
If you are using JavaScript, we suggest you use our JavaScript Package to help you verify the signature. We have provided examples on that page that will help you get started with it.
If you are not using JavaScript, you can verify the signature by computing the HMAC SHA256 hash of the request body using your webhook secret, and comparing it to the header (x-cside-signature) that we send with every request.
Here are a few examples in different languages:
async function verifyHmac(body: string, signature: string, secret: string) { const encoder = new TextEncoder(); const encodedBody = encoder.encode(body); const key = await crypto.subtle.importKey( "raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"] ); const signatureBuffer = await crypto.subtle.sign("HMAC", key, encodedBody); const finalSig = Array.from(new Uint8Array(signatureBuffer)) .map((byte) => byte.toString(16).padStart(2, "0")) .join(""); return signature.toLowerCase() === finalSig;}fn verify_hmac(body: &str, signature: &str, secret: &str) -> Result<(), &'static str> { let mut mac = HmacSha256::new_from_slice(secret.as_bytes()).map_err(|_| "Invalid secret")?; mac.update(body.as_bytes()); let result = mac.finalize(); let code_bytes = result.into_bytes(); let final_sig = hex::encode(code_bytes); if signature.to_lowercase() == final_sig { Ok(()) } else { Err("Invalid signature") } } // Add to Cargo.toml: // [dependencies] // hmac = "0.12" // sha2 = "0.10" // hex = "0.4"package mainimport ( "crypto/hmac" "crypto/sha256" "encoding/hex" "strings")func verifyHmac(body, signature, secret string) bool { h := hmac.New(sha256.New, []byte(secret)) h.Write([]byte(body)) finalSig := hex.EncodeToString(h.Sum(nil)) return strings.ToLower(signature) == finalSig}defmodule HmacVerifier do def verify_hmac(body, signature, secret) do final_sig = :crypto.mac(:hmac, :sha256, secret, body) |> Base.encode16(case: :lower) String.downcase(signature) == final_sig endendimport hmacimport hashlibimport secretsdef verify_hmac(body: str, signature: str, secret: str) -> bool: final_sig = hmac.new( secret.encode('utf-8'), body.encode('utf-8'), hashlib.sha256 ).hexdigest() return signature.lower() == final_sigHow is this doc?