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.