🕸 Building webhooks
We’ve been asked by a number of our customers to build webhooks, so that they can build their own services on top of Zeplo. Given that webhooks are a primary use case for Zeplo - it really makes sense to implement our own. Hopefully we can use Zeplo to power Zeplo’s own webhooks.
Before getting started on any new feature, I always create a new doc with the following headings. I fill it out as much as possible, but as new things come up they get added - it’s a living document, you can’t predict everything ahead of time!
- Why - why do we need this new feature? what was the use case or customer request that is driving this
- Questions - these are unknowns which we will need to figure out. I usually write out a few possible options, before reviewing and turning them into decisions. This is great when returning to understand WHY you made a certain decision.
- Requirements / decisions - once a question has been answered, I move the output here for clarity
- Actions - the individual steps (design, development, etc) that are required to build this feature (this usually comes a little later in the flow)
- Customers want to use Zeplo in their customer facing apps, and therefore need to show the user the current state of messages in the queue
- Customers want to listen for failed events (e.g. dead letter queue) so they can handle/alert in the case that the message will never be delivered again
What events should we trigger for?
- ❌ request.create request.update - I think it’s better to be more explicit
- ❌ request.create request.update request.attempt
- ✅ request.create request.update request.success request.error request.failed request.activate request.deactivate
Should we log every event regardless of whether a webhook is listening? E.g. create an event resource type that serves as an audit for all activity. This could be useful anyway in the requests page to see a history of what happened to the request
- ✅ Yes - provides a great audit history which provides value to the request view - any pending request can be updated
- ❌ No - most of the information is available in the request and some of it can’t be changed anyway.
Should request.update be for user based updates only OR for all updates? Should we differentiate between these?
- ❌ Provide a reason type field which details why the change occurred
- ✅ We could use request.update only for user updates, and then create separate events such as request.success or `request.
For any given underlying event, should we allow more than one hook event to be created - for example when a request errors we publish request.error but on the last error when there are no more retries remaining we might want to send both request.error and request.failed at the same time - both with the same data/state:
- ✅ Yes - allow the same underlying action/event to trigger multiple hook events - this makes more sense from a users perspective. For example, a user may only be interested in request.failed not request.error
- ❌ No - it could be confusing to receive the same data multiple times, especially if the user chooses to receive all events - in that case we would have the following options - also all of the required data for error/failed is available in the record update
Should we re-use the request model for our own webhook events?
- ✅ Yes - we could create a new source WEBHOOK that is created for sending out webhook events (seems kind of beautiful)
- ❌ No - could be confusing to re-use it, we might have to add a filter to the request - although this could easily be handled by adding a filter
Requirements / Decisions
- User can create and edit a webhook
- User can easily setup dead letter webhook
- User can request:
- Send me everything
- Specific events
- User can retry sending a webhook
- Webhooks are signed, webhook key is provided to the user
- Webhooks will be delivered as JSON only
- Webhook events: request.create request.update request.success request.error request.failed request.activate request.deactivate
Out of scope
- Local testing of webhooks via the CLI (although we hope to add this soon)
- Filters - no ability to add filters or aggregate
Update docs (and add link)