@@ -28,18 +28,129 @@ Suppose you're using OpenSign to collect eSignatures:
2828** Step 1:** Log in to your OpenSign account using your credentials.
2929** Step 2:** Navigate to ** Settings → Webhook** .
3030
31- ![ Navigate to Add Webhook] ( https://github.com/user-attachments/assets/6b069b6c-d2b7-408b-b7c9-7fbeb55d6c98 )
31+ < img width = " 861 " height = " 407 " alt = " Navigate to Add Webhook " src = " https://github.com/user-attachments/assets/883dc914-9316-42b0-b59c-10b168265b38 " />
3232
3333** Step 3:** Click ** Add Webhook** .
3434
3535- A popup will appear. Enter your ** Webhook URL** and click ** Yes** to save it.
3636
3737> ** Note:** To enable ** Live Webhook** support, you must upgrade to a ** paid plan** — either the ** Professional** or ** Teams** plan.
3838
39- ![ Add Webhook] ( https://github.com/user-attachments/assets/ff68b255-a6e6-4a7d-9cef-6dd9e3b6d4e4 )
39+ ---
40+
41+ ## 🧭 How to Create a Webhook Security Key
42+
43+ A ** Webhook Security Key** (also called a webhook secret) is a shared secret used to verify that webhook requests are genuinely sent by OpenSign and have not been tampered with.
44+
45+ ### Steps to Create a Webhook Security Key
46+
47+ 1 . Log in to your ** OpenSign** account.
48+ 2 . Navigate to ** Settings → Webhooks** .
49+ 3 . Add or edit a webhook endpoint.
50+ 4 . Generate a Security Key by clicking Enable Authentication, then click the Generate button.
51+ The webhook security key has been generated.
52+ - Example: ` a50a904a2a329d761781dac27c984416a07396736ac5588b62c6fe226538fbca `
53+ 6 . Save the webhook configuration.
54+
55+ <img width =" 861 " height =" 600 " alt =" webhook security key " src =" https://github.com/user-attachments/assets/6f61a23e-25a1-4785-b241-657af0c1eeb1 " />
56+
57+ ⚠️ ** Important:** Store this key securely. Do not expose it in client-side code or public repositories.
58+
59+ ---
60+
61+ ## 🔐 How the Webhook Security Key Works
62+
63+ OpenSign signs every webhook request using your security key.
64+
65+ ### High-level Flow
66+
67+ 1 . An event occurs (e.g. create document, document viewed, signed, completed, and declined).
68+ 2 . OpenSign sends a webhook request to your configured endpoint.
69+ 3 . OpenSign generates a signature using:
70+ - The ** raw request payload**
71+ - Your ** webhook security key**
72+ - The ** HMAC-SHA256** algorithm
73+ 4 . The generated signature is sent in the request header:
74+
75+ ```
76+ x-webhook-signature
77+ ```
78+
79+ 5 . Your server recomputes the signature using the same payload and secret.
80+ 6 . If both signatures match, the request is verified as authentic.
81+
82+ ---
83+
84+ // Process webhook event
85+ ```
86+
87+ ---
88+
89+ ## 📦 Sample Webhook Payload
90+
91+ ```json
92+ const crypto = require("crypto");
93+
94+ function verifySignature(req, secret) {
95+ const receivedSignature = req.headers["x-webhook-signature"];
96+ const payload = req.body;
97+
98+ const expectedSignature = crypto
99+ .createHmac("sha256", secret)
100+ .update(JSON.stringify(payload))
101+ .digest("hex");
102+
103+ return receivedSignature === expectedSignature;
104+ }
105+
106+ console.log("Try programiz.pro", verifySignature({body: {
107+ "event": "created",
108+ "type": "request-sign",
109+ "objectId": "SBEbnHwfrN",
110+ "file": "https://legadratw3d.ams3.digitaloceanspaces.com/c3f0bc11b84a87e6265de6bf28e5015e_uoeksXXU6FI5Op2B.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=DO00QAPRB3CQRWHWQ8ZB%2F20251219%2Fus-west%2Fs3%2Faws4_request&X-Amz-Date=20251219T152806Z&X-Amz-Expires=900&X-Amz-Signature=9635dfb8ee8fde933f881905a97f869578ef7e99b337d4b21a0805b8317fd70d&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject",
111+ "name": "Sample Test Doc Line Compressed",
112+ "note": "Please review and sign this document",
113+ "description": "",
114+ "signers": [
115+ {
116+ "name": "Peter Mark",
117+ "email": "peter.mark@opensignlabs.com"
118+ },
119+ {
120+ "name": "kelvin bosch",
121+ "email": "kelvin.bosch@opensignlabs.com"
122+ }
123+ ],
124+ "createdAt": "Sat, 20 Dec 2025 00:58:20 GMT+9:30"
125+ }, headers:{"x-webhook-signature":"52958fd3900f19ba6485319eb2622ef0ec4cf5ddfe36509cbe95eb706ed6b8c2" }}, "0906e8cbc88da0d5a6fd78162eb8e5e57ba7bd99bdc472145dc089d7f82b0a4a"));
126+ ```
127+
128+ The corresponding signature is sent in the request header:
129+
130+ ```
131+ x-webhook-signature: bcf57b06dde0c030d9423639824bad17ab7dd09ea3bf0a743773b95254ecf78e
132+ ```
133+ If the script returns true, it means the webhook is valid and has not been tampered with.
134+
135+ ## ✅ Best Practices
136+
137+ - Always verify the webhook signature before processing the payload.
138+ - Use the ** raw request body** for signature calculation (avoid modifying it).
139+ - Rotate your webhook security key periodically.
140+ - Return a ** 2xx** HTTP status only after successful verification.
141+
142+ ---
143+
144+ ## 🧩 Common Issues
145+
146+ - ** Signature mismatch** : Ensure the payload is stringified exactly as received.
147+ - ** Missing header** : Confirm ` x-webhook-signature ` is present in the request.
148+ - ** Wrong secret** : Verify the same security key is used on both sides.
40149
41150---
42151
152+ This mechanism ensures webhook requests are secure, tamper-proof, and trustworthy.
153+
43154## 🧪 Sandbox Webhook
44155
45156- You can also add webhook for the ** Sandbox** environment on the same page.
0 commit comments