Skip to content

Commit b836f94

Browse files
committed
Add DevRev webhooks demo
1 parent de95801 commit b836f94

File tree

4 files changed

+432
-0
lines changed

4 files changed

+432
-0
lines changed

webhooks/README.md

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
# DevRev Webhooks Test Server
2+
3+
This is a simple server to test DevRev webhooks. It handles webhook verification
4+
and processes webhook events for work created, updated, and deleted.
5+
Detailed documentation on webhooks can be found [here](https://developer.devrev.ai/public/guides/webhooks).
6+
7+
## Setup
8+
9+
1. Start ngrok:
10+
```bash
11+
ngrok http 3000
12+
```
13+
14+
2. Register your webhook with DevRev using the ngrok URL:
15+
```bash
16+
curl --request POST 'https://api.devrev.ai/webhooks.create' \
17+
--header "Authorization: Bearer $DEVREV_TOKEN" \
18+
--header 'Content-Type: application/json' \
19+
--data-raw '{
20+
"event_types": [
21+
"work_created",
22+
"work_updated",
23+
"work_deleted"
24+
],
25+
"url": "your-ngrok-url"
26+
}'
27+
```
28+
29+
3. Start the webhook server:
30+
31+
The `WEBHOOK_SECRET` environment variable is required. It will be available as
32+
`secret` in the response of the above `webhooks.create` API call.
33+
34+
```bash
35+
WEBHOOK_SECRET=your_webhook_secret_here go run main.go
36+
```
37+
38+
## Example webhook payload
39+
40+
The following is an example of a `work_updated` webhook payload. Note that
41+
`work_updated` contains `old_work` and `work` fields.
42+
43+
```
44+
{
45+
"id": "don:integration:dvrv-us-1:devo/11FVC3ScK:webhook/1jGzMh1N:webhook_event/U7gbBDxjiWM",
46+
"timestamp": "2025-07-02T13:07:40.937074Z",
47+
"webhook_id": "don:integration:dvrv-us-1:devo/11FVC3ScK:webhook/1jGzMh1N",
48+
"work_updated": {
49+
"old_work": {
50+
"type": "issue",
51+
"applies_to_part": {
52+
"type": "product",
53+
"display_id": "PROD-2",
54+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:product/2",
55+
"id_v1": "don:DEV-11FVC3ScK:product:2",
56+
"name": "prod-foo",
57+
"owned_by": [
58+
{
59+
"type": "dev_user",
60+
"display_handle": "shivansh-rai",
61+
"display_id": "DEVU-1",
62+
"display_name": "shivansh-rai",
63+
"email": "[email protected]",
64+
"full_name": "Shivansh Rai",
65+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/1",
66+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-1",
67+
"state": "active",
68+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Shivansh%20Rai.png"
69+
}
70+
],
71+
"stage": {
72+
"name": ""
73+
}
74+
},
75+
"body": "\u003cdon:core:dvrv-us-1:devo/11FVC3ScK:issue/98\u003e",
76+
"created_by": {
77+
"type": "dev_user",
78+
"display_handle": "shivansh-rai",
79+
"display_id": "DEVU-1",
80+
"display_name": "shivansh-rai",
81+
"email": "[email protected]",
82+
"full_name": "Shivansh Rai",
83+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/1",
84+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-1",
85+
"state": "active",
86+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Shivansh%20Rai.png"
87+
},
88+
"created_date": "2025-06-14T13:20:46.963Z",
89+
"custom_fields": {
90+
"ctype__color": "Blue",
91+
"tnt__a_rich_text_field": "A new issue \u003cdon:core:dvrv-us-1:devo/11FVC3ScK:issue/91\u003e",
92+
"tnt__a_text_field": ""
93+
},
94+
"custom_schema_fragments": [
95+
"don:core:dvrv-us-1:devo/11FVC3ScK:tenant_fragment/503",
96+
"don:core:dvrv-us-1:devo/11FVC3ScK:custom_type_fragment/480"
97+
],
98+
"display_id": "ISS-98",
99+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:issue/98",
100+
"id_v1": "don:DEV-11FVC3ScK:issue:98",
101+
"modified_by": {
102+
"type": "dev_user",
103+
"display_handle": "shivansh-rai",
104+
"display_id": "DEVU-1",
105+
"display_name": "shivansh-rai",
106+
"email": "[email protected]",
107+
"full_name": "Shivansh Rai",
108+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/1",
109+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-1",
110+
"state": "active",
111+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Shivansh%20Rai.png"
112+
},
113+
"modified_date": "2025-07-02T13:04:12.1Z",
114+
"owned_by": [
115+
{
116+
"type": "dev_user",
117+
"display_handle": "gowtham-tg",
118+
"display_id": "DEVU-10",
119+
"display_name": "gowtham-tg",
120+
"email": "[email protected]",
121+
"full_name": "Gowtham Gopinath",
122+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/10",
123+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-10",
124+
"state": "active",
125+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Gowtham%20Gopinath.png"
126+
}
127+
],
128+
"priority": "p1",
129+
"priority_v2": {
130+
"id": 2,
131+
"label": "P1",
132+
"ordinal": 2
133+
},
134+
"references": [
135+
{
136+
"type": "issue",
137+
"display_id": "ISS-98",
138+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:issue/98",
139+
"id_v1": "don:DEV-11FVC3ScK:issue:98",
140+
"owned_by": [
141+
{
142+
"type": "dev_user",
143+
"display_handle": "gowtham-tg",
144+
"display_id": "DEVU-10",
145+
"display_name": "gowtham-tg",
146+
"email": "[email protected]",
147+
"full_name": "Gowtham Gopinath",
148+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/10",
149+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-10",
150+
"state": "active",
151+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Gowtham%20Gopinath.png"
152+
}
153+
],
154+
"priority": "p2",
155+
"priority_v2": {
156+
"id": 3,
157+
"label": "P2",
158+
"ordinal": 3
159+
},
160+
"stage": {
161+
"name": "prioritized",
162+
"stage": {
163+
"display_name": "Prioritized",
164+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:custom_stage/27",
165+
"name": "prioritized"
166+
}
167+
},
168+
"title": "issue with a subtype"
169+
}
170+
],
171+
"stage": {
172+
"display_name": "Prioritized",
173+
"name": "prioritized",
174+
"notes": "",
175+
"ordinal": 3600,
176+
"stage": {
177+
"display_name": "Prioritized",
178+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:custom_stage/27",
179+
"name": "prioritized"
180+
},
181+
"state": {
182+
"display_name": "Open",
183+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:custom_state/1",
184+
"is_final": false,
185+
"name": "open"
186+
}
187+
},
188+
"state": "open",
189+
"stock_schema_fragment": "don:core:dvrv-us-1:stock_sf/5774789",
190+
"subtype": "test",
191+
"title": "issue with a subtype"
192+
},
193+
"work": {
194+
"type": "issue",
195+
"applies_to_part": {
196+
"type": "product",
197+
"display_id": "PROD-2",
198+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:product/2",
199+
"id_v1": "don:DEV-11FVC3ScK:product:2",
200+
"name": "prod-foo",
201+
"owned_by": [
202+
{
203+
"type": "dev_user",
204+
"display_handle": "shivansh-rai",
205+
"display_id": "DEVU-1",
206+
"display_name": "shivansh-rai",
207+
"email": "[email protected]",
208+
"full_name": "Shivansh Rai",
209+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/1",
210+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-1",
211+
"state": "active",
212+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Shivansh%20Rai.png"
213+
}
214+
],
215+
"stage": {
216+
"name": ""
217+
}
218+
},
219+
"body": "\u003cdon:core:dvrv-us-1:devo/11FVC3ScK:issue/98\u003e",
220+
"created_by": {
221+
"type": "dev_user",
222+
"display_handle": "shivansh-rai",
223+
"display_id": "DEVU-1",
224+
"display_name": "shivansh-rai",
225+
"email": "[email protected]",
226+
"full_name": "Shivansh Rai",
227+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/1",
228+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-1",
229+
"state": "active",
230+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Shivansh%20Rai.png"
231+
},
232+
"created_date": "2025-06-14T13:20:46.963Z",
233+
"custom_fields": {
234+
"ctype__color": "Blue",
235+
"tnt__a_rich_text_field": "A new issue \u003cdon:core:dvrv-us-1:devo/11FVC3ScK:issue/91\u003e",
236+
"tnt__a_text_field": ""
237+
},
238+
"custom_schema_fragments": [
239+
"don:core:dvrv-us-1:devo/11FVC3ScK:tenant_fragment/503",
240+
"don:core:dvrv-us-1:devo/11FVC3ScK:custom_type_fragment/480"
241+
],
242+
"display_id": "ISS-98",
243+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:issue/98",
244+
"id_v1": "don:DEV-11FVC3ScK:issue:98",
245+
"modified_by": {
246+
"type": "dev_user",
247+
"display_handle": "shivansh-rai",
248+
"display_id": "DEVU-1",
249+
"display_name": "shivansh-rai",
250+
"email": "[email protected]",
251+
"full_name": "Shivansh Rai",
252+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/1",
253+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-1",
254+
"state": "active",
255+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Shivansh%20Rai.png"
256+
},
257+
"modified_date": "2025-07-02T13:07:40.704Z",
258+
"owned_by": [
259+
{
260+
"type": "dev_user",
261+
"display_handle": "gowtham-tg",
262+
"display_id": "DEVU-10",
263+
"display_name": "gowtham-tg",
264+
"email": "[email protected]",
265+
"full_name": "Gowtham Gopinath",
266+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/10",
267+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-10",
268+
"state": "active",
269+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Gowtham%20Gopinath.png"
270+
}
271+
],
272+
"priority": "p2",
273+
"priority_v2": {
274+
"id": 3,
275+
"label": "P2",
276+
"ordinal": 3
277+
},
278+
"references": [
279+
{
280+
"type": "issue",
281+
"display_id": "ISS-98",
282+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:issue/98",
283+
"id_v1": "don:DEV-11FVC3ScK:issue:98",
284+
"owned_by": [
285+
{
286+
"type": "dev_user",
287+
"display_handle": "gowtham-tg",
288+
"display_id": "DEVU-10",
289+
"display_name": "gowtham-tg",
290+
"email": "[email protected]",
291+
"full_name": "Gowtham Gopinath",
292+
"id": "don:identity:dvrv-us-1:devo/11FVC3ScK:devu/10",
293+
"id_v1": "don:DEV-11FVC3ScK:dev_user:DEVU-10",
294+
"state": "active",
295+
"thumbnail": "https://api.dev.devrev-eng.ai/internal/display-picture/Gowtham%20Gopinath.png"
296+
}
297+
],
298+
"priority": "p2",
299+
"priority_v2": {
300+
"id": 3,
301+
"label": "P2",
302+
"ordinal": 3
303+
},
304+
"stage": {
305+
"name": "prioritized",
306+
"stage": {
307+
"display_name": "Prioritized",
308+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:custom_stage/27",
309+
"name": "prioritized"
310+
}
311+
},
312+
"title": "issue with a subtype"
313+
}
314+
],
315+
"stage": {
316+
"display_name": "Prioritized",
317+
"name": "prioritized",
318+
"notes": "",
319+
"ordinal": 3600,
320+
"stage": {
321+
"display_name": "Prioritized",
322+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:custom_stage/27",
323+
"name": "prioritized"
324+
},
325+
"state": {
326+
"display_name": "Open",
327+
"id": "don:core:dvrv-us-1:devo/11FVC3ScK:custom_state/1",
328+
"is_final": false,
329+
"name": "open"
330+
}
331+
},
332+
"state": "open",
333+
"stock_schema_fragment": "don:core:dvrv-us-1:stock_sf/5774789",
334+
"subtype": "test",
335+
"title": "issue with a subtype"
336+
}
337+
},
338+
"type": "work_updated"
339+
}
340+
```

webhooks/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module devrev-webhooks
2+
3+
go 1.24.1
4+
5+
require github.com/joho/godotenv v1.5.1

webhooks/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
2+
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=

0 commit comments

Comments
 (0)