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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
John Sheehan
August 21, 2014
Technology
0
210
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
180
Crafting a Great Webhooks Experience
johnsheehan
2
550
Glue 2015: Microservices - More than just a buzzword.
johnsheehan
2
760
Scale-Oriented Architecture with Microservices
johnsheehan
2
350
The rise of distributed applications.
johnsheehan
2
480
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
860
Modern Tools for Modern Applications
johnsheehan
1
200
Other Decks in Technology
See All in Technology
Devinを導入したら予想外の人たちに好評だった
tomuro
0
760
なぜAIは組織を速くしないのか 令和の腑分け
sugino
82
53k
パネルディスカッション資料 (at Tableau Now! - 2026-02-26)
yoshitakaarakawa
0
1k
男(監査)はつらいよ - Policy as CodeからAIエージェントへ
ken5scal
5
700
Eight Engineering Unit 紹介資料
sansan33
PRO
1
6.9k
LINEヤフーにおけるAI駆動開発組織のプロデュース施策
lycorptech_jp
PRO
0
380
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
15
95k
Serverless Agent Architecture on Azure / serverless-agent-on-azure
miyake
1
120
Secure Boot 2026 - Aggiornamento dei certificati UEFI e piano di adozione in azienda
memiug
0
130
問い合わせ自動化の技術的挑戦
recruitengineers
PRO
2
110
「使いにくい」も「運用疲れ」も卒業する UIデザイナーとエンジニアが創る持続可能な内製開発
nrinetcom
PRO
1
770
マネージャー版 "提案のレベル" を上げる
konifar
7
2.5k
Featured
See All Featured
Faster Mobile Websites
deanohume
310
31k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
My Coaching Mixtape
mlcsv
0
63
Six Lessons from altMBA
skipperchong
29
4.2k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
130
The SEO Collaboration Effect
kristinabergwall1
0
380
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.1k
Optimizing for Happiness
mojombo
378
71k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
460
Into the Great Unknown - MozCon
thekraken
40
2.3k
Prompt Engineering for Job Search
mfonobong
0
180
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