Webhooks
Introduction
Webhooks are how services notify each other of events. At its core, a webhook is simply a POST request to a pre-determined endpoint. The endpoint can be any URL you want, such as a Zapier webhook trigger or your own API.
You can use Tightknit’s webhooks to tell inform another service that something has happened, such as a user registering for a Calendar Event, in order to trigger an external process.
Webhooks can be managed through the webhooks portal, which you can access through the Webhooks module.
Adding an Endpoint
Adding an endpoint is as simple as providing a URL that you control and selecting the event types that you want to listen to. If you don’t specify any event types, by default, your endpoint will receive all events, regardless of type. While this is helpful for getting started and for testing, we recommend changing this later on to the minimum required subset of events in order to avoid receiving extraneous messages.
If you don’t have an endpoint ready yet, you can press the “with Svix Play” button to have a unique testing URL generated for you. You’ll be able to view and inspect webhooks sent to your Svix Play URL, making it effortless to get started.
It’s important to disable CSRF protection for your endpoint if the framework you use enables them by default.
Testing endpoints
Once you’ve added an endpoint, you’ll want to make sure its working.
The “Testing” tab lets you send test events to your endpoint.
After sending an example event, you can click into the message to view the message payload, all of the message attempts, and whether it succeeded or failed.
If successful, the endpoint is expected to respond with with a 2xx (status code 200-299) response within a reasonable time-frame (15s).
Verifying Webhooks
Webhook signatures let you verify that webhook messages are actually sent by Tightknit and not a malicious actor.
For a more detailed explanation, check out this article on why you should verify webhooks.
Our webhook partner Svix offers a set of useful guides that make verifying webhooks very simple. Check it out here: https://docs.svix.com/receiving/verifying-payloads/how
Retries
If a webhook message delivery results in failure, messages are sent based on a retry schedule with exponential backoff.
Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:
- Immediately
- 5 seconds
- 5 minutes
- 30 minutes
- 2 hours
- 5 hours
- 10 hours
- 10 hours (in addition to the previous)
If an endpoint is removed or disabled delivery attempts to the endpoint will be disabled as well.
For example, an attempt that fails three times before eventually succeeding will be delivered roughly 35 minutes and 5 seconds following the first attempt.
Manual Retries
You can also use the webhooks portal to manually
retry each message at any time, or automatically retry (“Recover”) all failed
messages starting from a given date.
Troubleshooting
Below are some common reasons why your webhook endpoint may be failing.
Not using the raw payload body
This is the most common issue. When generating the signed content, we use the raw string body of the message payload.
If you convert JSON payloads into strings using methods like stringify, different implementations may produce different string representations of the JSON object, which can lead to discrepancies when verifying the signature. It’s crucial to verify the payload exactly as it was sent, byte-for-byte or string-for-string, to ensure accurate verification.
Sending the wrong response codes
When we receive a response with a 2xx HTTP status code, we interpret that as a successful delivery even if you indicate a failure in the response payload. Make sure to use the right response status codes so we know when message are supposed to succeed vs fail.
Responses timing out
We will consider any message that fails to send a response within a timely manner a failed message. If your endpoint is also processing complicated workflows, it may timeout and result in failed messages.
We suggest having your endpoint simply receive the message and add it to a queue to be processed asynchronously so you can respond promptly and avoiding getting timed out.