Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Crafting a Great Webhooks Experience
Search
John Sheehan
August 21, 2014
Technology
0
200
Crafting a Great Webhooks Experience
Presented at API Craft SF on 8/21/14
John Sheehan
August 21, 2014
Tweet
Share
More Decks by John Sheehan
See All by John Sheehan
My Favorite API Tools (Other than Runscope)
johnsheehan
0
170
Crafting a Great Webhooks Experience
johnsheehan
2
530
Glue 2015: Microservices - More than just a buzzword.
johnsheehan
2
740
Scale-Oriented Architecture with Microservices
johnsheehan
2
350
The rise of distributed applications.
johnsheehan
2
470
Zen and the Art of API Maintenance
johnsheehan
2
2.5k
Building API integrations you can live with.
johnsheehan
0
130
Free API debugging and testing tools you should know about.
johnsheehan
5
850
Modern Tools for Modern Applications
johnsheehan
1
200
Other Decks in Technology
See All in Technology
『君の名は』と聞く君の名は。 / Your name, you who asks for mine.
nttcom
1
130
Oracle Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
2
450
なぜ あなたはそんなに re:Invent に行くのか?
miu_crescent
PRO
0
230
AWSの新機能をフル活用した「re:Inventエージェント」開発秘話
minorun365
2
510
ハッカソンから社内プロダクトへ AIエージェント ko☆shi 開発で学んだ4つの重要要素
leveragestech
0
380
Snowflake導入から1年、LayerXのデータ活用の現在 / One Year into Snowflake: How LayerX Uses Data Today
civitaspo
0
2.6k
100以上の新規コネクタ提供を可能にしたアーキテクチャ
ooyukioo
0
290
Oracle Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
3
200
株式会社ビザスク_AI__Engineering_Summit_Tokyo_2025_登壇資料.pdf
eikohashiba
1
130
Entity Framework Core におけるIN句クエリ最適化について
htkym
0
130
"人"が頑張るAI駆動開発
yokomachi
1
650
AI with TiDD
shiraji
1
320
Featured
See All Featured
Abbi's Birthday
coloredviolet
0
4k
Code Reviewing Like a Champion
maltzj
527
40k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
32
Fireside Chat
paigeccino
41
3.8k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Reality Check: Gamification 10 Years Later
codingconduct
0
2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
180
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
120
Faster Mobile Websites
deanohume
310
31k
Transcript
Crafting a Great Webhooks Experience John Sheehan CEO, @Runscope Tuesday,
October 7, 14
Tuesday, October 7, 14
Tuesday, October 7, 14
Tuesday, October 7, 14
Tuesday, October 7, 14
Tuesday, October 7, 14
"user defined callbacks made with HTTP POST" Tuesday, October 7,
14
"Webhooks are the easiest way to remotely execute code." --
Jeff Lindsay once when we were talking Tuesday, October 7, 14
HTTP Push Notifications Tuesday, October 7, 14
A Reverse API Tuesday, October 7, 14
Provider makes request to URL when an event happens. Consumer
sets up a server to listen for callbacks. Consumer registers callback URL with provider. Tuesday, October 7, 14
Provider makes request to URL when an event happens. Consumer
sets up a server to listen for callbacks. Consumer registers callback URL with provider. Tuesday, October 7, 14
Provider makes request to URL when an event happens. Consumer
sets up a server to listen for callbacks. Consumer registers callback URL with provider. Tuesday, October 7, 14
Tuesday, October 7, 14
Implementing Webhooks Tuesday, October 7, 14
url = get_callback_url() data = get_webhook_payload_json() try: resp = requests.post(url,
data=data) if not resp.ok: _logger.error(resp.content) except Exception as e: _logger.error(e) Tuesday, October 7, 14
Problem #1: Error Handling Tuesday, October 7, 14
> POST /callback < 400 Bad Request Tuesday, October 7,
14
> POST /callback < 302 Found < Location: http:// Tuesday,
October 7, 14
> POST /callback < 200 OK < Content-Type: text/plain <
<Response></Response> Tuesday, October 7, 14
Error Handling Suggestions Tuesday, October 7, 14
Be lenient in what you accept back if you can
reasonably guess. Retry failed callbacks with exponential back off. Decide if redirects are to be followed or not. Tuesday, October 7, 14
Be lenient in what you accept back if you can
reasonably guess. Retry failed callbacks with exponential back off. Decide if redirects are to be followed or not. Tuesday, October 7, 14
Be lenient in what you accept back if you can
reasonably guess. Retry failed callbacks with exponential back off. Decide if redirects are to be followed or not. Tuesday, October 7, 14
Problem #2: Flooding Tuesday, October 7, 14
Tuesday, October 7, 14
Active Queues ↪ ↪ Tuesday, October 7, 14
Problem #3: Security Tuesday, October 7, 14
> POST http://localhost:3000 Tuesday, October 7, 14
> POST http://foo.lvh.me Tuesday, October 7, 14
DoS Attack Vector Tuesday, October 7, 14
Proving the Source Tuesday, October 7, 14
Validation Techniques Tuesday, October 7, 14
Key Sharing Tuesday, October 7, 14
Request Signing Tuesday, October 7, 14
Re-fetch > POST /callback > { id: 123 } >
GET /users/123 < { id: 123 } Webhook Callback App Code Tuesday, October 7, 14
Security Suggestions Tuesday, October 7, 14
Validate your requests. Document it well! Resolve IPs before making
request. Consider proxying. Consider subscription validation for high-volume cases. Tuesday, October 7, 14
Validate your requests. Document it well! Resolve IPs before making
request. Consider proxying. Consider subscription validation for high-volume cases. Tuesday, October 7, 14
Validate your requests. Document it well! Resolve IPs before making
request. Consider proxying. Consider subscription validation for high-volume cases. Tuesday, October 7, 14
Developer Experience Tuesday, October 7, 14
Payload Design Tuesday, October 7, 14
Fat vs.Thin Tuesday, October 7, 14
- or - { } payload= Tuesday, October 7, 14
- or - data = JSON.loads(request.body) name = data["name"] name
= request.form.get("name") Tuesday, October 7, 14
payload = request.form.get("payload") data = JSON.loads(payload) name = data["name"] Tuesday,
October 7, 14
Mirror API Resources Tuesday, October 7, 14
Complete Documentation! Tuesday, October 7, 14
Tooling Tuesday, October 7, 14
Accept Multiple Callback URLs Tuesday, October 7, 14
Hooks API Tuesday, October 7, 14
Debugger & Logs Tuesday, October 7, 14
Manual Retries Tuesday, October 7, 14
Generate Test Callbacks Tuesday, October 7, 14
Tunneling Tuesday, October 7, 14
Thank you! Questions? Try Runscope free: runscope.com Tuesday, October 7,
14