Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
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
190
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
120
Free API debugging and testing tools you should know about.
johnsheehan
5
850
Modern Tools for Modern Applications
johnsheehan
1
190
Other Decks in Technology
See All in Technology
How native lazy objects will change Doctrine and Symfony forever
beberlei
1
390
技術以外の世界に『越境』しエンジニアとして進化を遂げる 〜Kotlinへの愛とDevHRとしての挑戦を添えて〜
subroh0508
1
260
知っていると得する!Movable Type 9 の新機能を徹底解説
masakah
0
220
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
37k
AI活用によるPRレビュー改善の歩み ― 社内全体に広がる学びと実践
lycorptech_jp
PRO
1
130
生成AI・AIエージェント時代、データサイエンティストは何をする人なのか?そして、今学生であるあなたは何を学ぶべきか?
kuri8ive
2
1.9k
グレートファイアウォールを自宅に建てよう
ctes091x
0
110
「え?!それ今ではHTMLだけでできるの!?」驚きの進化を遂げたモダンHTML
riyaamemiya
10
4.5k
ML PM Talk #1 - ML PMの分類に関する考察
lycorptech_jp
PRO
1
600
シンプルを極める。アンチパターンなDB設計の本質
facilo_inc
1
1.3k
手動から自動へ、そしてその先へ
moritamasami
0
240
最近のLinux普段づかいWaylandデスクトップ元年
penguin2716
0
190
Featured
See All Featured
Java REST API Framework Comparison - PWX 2021
mraible
34
9k
Building an army of robots
kneath
306
46k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Designing Experiences People Love
moore
142
24k
4 Signs Your Business is Dying
shpigford
186
22k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
700
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
700
How STYLIGHT went responsive
nonsquared
100
5.9k
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