Skip to main content

What are webhooks?

Webhooks are an efficient, automated way for one application to push data to another in real time. They let different systems communicate specific events without the receiving application having to poll for them. Instead, the application that generates the event sends a notification, usually an HTTP POST request, to a URL the receiving application configured in advance.

What do webhooks do?

Webhooks notify your application about events that happen in another application or service. Some common tasks handled by webhooks include:
  • Real-time notifications: the receiving application is notified immediately when something happens, such as a new order, a status change, or a new message.
  • Process automation: they let you automate responses or actions in your application when certain events happen, without constantly querying the API.
  • System integration: they make it easy to integrate different systems, letting events in one system trigger automatic actions in another.

How do webhooks work?

  1. Setup: first, the receiving application sets up an endpoint (a public URL) ready to receive webhook notifications.
  2. Webhook registration: the sending application is configured to send notifications to the webhook endpoint whenever a specific event happens.
  3. Event delivery: when the configured event happens, the sending application sends an HTTP POST request to the webhook endpoint, including the relevant event data in the request body.
  4. Event processing: the receiving application processes the received information and can take several actions in response, such as updating a database, sending an email, or triggering another internal process.

One webhook, many instances

A webhook on Zapster is a destination you register once (the URL that will receive events) and reuse across as many instances as you want. Each instance decides, on its own, which events it wants to receive at that destination. It helps to understand two concepts that work together:
  • The webhook (on your account): holds the URL, a name, and the status (on or off). It is the address notifications are sent to. It belongs to your account, not to a specific instance.
  • The association with each instance: every instance that uses the webhook gets its own association. That is where the subscribed events and per-instance settings live (enable/disable, test mode). The same webhook can be associated with several instances at once.

Why share a webhook

The main reason is centralized maintenance. If you have dozens of instances sending events to the same system, registering the URL once and reusing it avoids repeating configuration. When the URL needs to change (new server, new domain, route adjustment), you update it in one place and the change applies to every instance that uses that webhook.

How to do it in practice

The same endpoint (POST /wa/instances/:id/webhooks) covers both paths. The difference is in the request body:
  • Send url to create a new webhook and associate it with the instance right away. Use this for the first instance.
  • Send webhook_id to reuse a webhook that already exists. Use this for the remaining instances.
The body accepts url OR webhook_id, never both together. If both are sent, Zapster prioritizes webhook_id. The events field is always required and must have at least one event.
1. First instance: create the webhook with url
2. Remaining instances: reuse with webhook_id Use the webhook_id returned in the previous step to associate the same webhook with another instance. Note that the events can be different: each instance subscribes to what makes sense for it.

Editing and removing: what changes

Because the webhook and the association are distinct things, editing or removing has different scopes. It is worth knowing each operation before applying changes in production.
Editing the webhook propagates to everyone. Changing the URL or the name through the account endpoint (PATCH /webhooks/:id) affects every associated instance. If you need a different URL for a single instance, create a new webhook instead of editing the existing one.
Disassociating is not the same as deleting. DELETE /wa/instances/:id/webhooks/:whId only turns the webhook off for that instance; it stays active on the others and on your account. To delete the webhook for good, use DELETE /webhooks/:id.

How to tell the origin apart on the receiver

Each instance delivers events independently, even when they share the same webhook. To know where each notification came from, use the HTTP headers:
  • X-Instance-ID: identifies the instance that generated the event (the real origin).
  • X-Webhook-ID: identifies the shared webhook that delivered the notification.
Because the subscribed events can differ per instance, the same webhook may receive message.received from one instance and message.sent from another. Always look at X-Instance-ID to route or log the event correctly.

When to share and when to separate

Sharing a webhook makes sense when:
  • All instances deliver to the same system (a CRM, a queue, a central endpoint).
  • You want to change the destination URL in one place in the future.
  • The processing on the receiver already uses X-Instance-ID to separate origins.
Separate webhooks per instance make more sense when:
  • Each instance belongs to a different customer or product, with its own URL.
  • You need to turn a single instance’s destination on or off without touching the others.
  • Separate environments (production and staging) must not mix.

Best practices

  • Store the webhook_id returned at creation; it is what you reuse on the next instances.
  • Use the webhook name to make its purpose clear (for example, “CRM production”).
  • On the receiver, treat X-Instance-ID as the source of truth for the event’s origin.
  • Before editing the URL of a shared webhook, confirm which instances will be affected with the list webhooks endpoint.

Frequently asked questions

Not through the webhook edit endpoint, which is account-scoped and propagates to every associated instance. For a dedicated URL, create a new webhook by sending url at creation and associate it with the desired instance only.
No. DELETE /wa/instances/:id/webhooks/:whId only turns the webhook off for that instance. It stays active on the others and on your account. To delete it for good, use DELETE /webhooks/:id.
No. Events are defined per instance, in the association. One can subscribe to message.received and another to message.sent, even pointing to the same webhook.
Through the X-Instance-ID header, present in every notification. X-Webhook-ID indicates the webhook that made the delivery.
Send only one of them. If both are provided, Zapster prioritizes webhook_id and ignores url.
For the details of each endpoint, check the API reference: create/associate webhook, edit the instance association, disassociate from the instance, edit the webhook, and delete the webhook.

Failure handling and retries

In an ideal scenario, the receiving application receives and processes the webhook request without issues. However, failures can happen for various reasons, such as server downtime, network problems, or processing errors. To make sure important notifications are not lost, we implement a retry mechanism. If the receiving application responds with an HTTP status code greater than 400 (indicating an error), the sending application will retry the webhook notification up to 5 times.

Retry details

  • Failure criterion: any response with an HTTP status code greater than or equal to 400.
  • Number of retries: up to 5 attempts.
  • Interval between retries: the interval between each retry grows progressively with a factor of 2.5. The intervals in seconds are:
    • 1st attempt: 2.5 seconds (2.5^1)
    • 2nd attempt: ~6 seconds (2.5^2)
    • 3rd attempt: ~15 seconds (2.5^3)
    • 4th attempt: ~39 seconds (2.5^4)
    • 5th attempt: ~97 seconds (2.5^5)
    Each interval is calculated as 2.5^n, where n is the attempt number.

Custom HTTP headers

Every webhook notification sent by the Zapster API includes custom HTTP headers that identify the origin and context of the event. These headers are useful for validation, logging, and firewall rules.

Validation and allowlisting

You can use the custom HTTP headers to validate the origin of received notifications. Because the webhook is delivered via POST to your server, the examples below show the receiving endpoint in each language (cURL and browser code do not receive webhooks, so they are not shown here):
Allowlisting in a WAF/firewall: if you use a Web Application Firewall (WAF) or firewall rules, configure it to accept POST requests that carry the X-Instance-ID, X-Message-ID, X-Attempt-Count, and User-Agent headers with the Zapsterapi/ prefix.