Blueticks

Receiving webhooks

Get Blueticks events — message delivery, incoming WhatsApp messages, group activity, sessions, campaigns — POSTed to your server in real time.

Webhooks push Blueticks events to your server over HTTPS, in near real time — so you can react to message delivery, incoming WhatsApp messages, group activity, session changes, and campaign progress without polling the API.

This guide assumes you have an API key (Authentication) and an SDK client set up (Quickstart).

1. Register a webhook

Point an HTTPS endpoint at Blueticks and subscribe it to the events you care about (pick any from the catalog below). You can register several endpoints, each with its own event list.

created = bt.webhooks.create(
    url="https://api.your-server.com/bt-webhooks",
    events=["message.delivered", "message.failed"],
    description="prod",
)
print(created.id)
const webhook = await bt.webhooks.create({
  url: 'https://api.your-server.com/bt-webhooks',
  events: ['message.delivered', 'message.failed'],
});
$created = $bt->webhooks->create(
    url: 'https://api.your-server.com/bt-webhooks',
    events: ['message.delivered', 'message.failed'],
);
echo $created->id;
created = client.webhooks.create(
  url: "https://api.your-server.com/bt-webhooks",
  events: ["message.delivered", "message.failed"],
  description: "prod",
)
puts created.id
created, _ := c.Webhooks.Create(context.Background(), blueticks.CreateWebhookParams{
	URL:         "https://api.your-server.com/bt-webhooks",
	Events:      []string{"message.delivered", "message.failed"},
	Description: "prod",
})
fmt.Println(created.ID)
curl -X POST https://api.blueticks.co/v1/webhooks \
  -H "Authorization: Bearer BLUETICKS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":"https://api.your-server.com/bt-webhooks",
    "events":["message.delivered","message.failed"]
  }'

Prefer no code? You can also add and toggle webhooks from the dashboard under Settings → API → Webhooks.

2. What you receive

Each event is a single HTTPS POST. The body is always the same envelope — only type and data change:

{
  "id": "evt_01h7za9c8m...",
  "type": "message.delivered",
  "created_at": "2026-04-23T16:42:00.000Z",
  "data": { /* fields specific to this event type */ }
}

with these headers:

Content-Type: application/json
Blueticks-Webhook-Id: 6a380a8258bece30b485036e
  • id is unique per delivery — store it and ignore repeats, since a retry can re-deliver an event your server already handled (see Reliability).
  • Blueticks-Webhook-Id is the id of your webhook that matched — handy when one server backs several endpoints.
  • Respond 2xx within 10 seconds. Anything else (or a timeout) is treated as a failure and retried. Do heavy work after you respond.

3. Events you can subscribe to

You only receive the events you subscribe to. Group them however you like across one or more endpoints.

Message delivery — lifecycle of messages you send: message.queued · message.sending · message.delivered · message.read · message.failed

Incoming WhatsApp activity:

  • new_message_received_webhook — someone messaged you
  • reply_to_my_message_webhook — a reply to one of your messages
  • message_edited_webhook · message_deleted_revoked_webhook — a message was edited / deleted
  • message_reaction_webhook — an emoji reaction
  • poll_vote_webhook — a vote on your poll
  • ack_changed_webhook — a message's delivered/read status changed

Group & chat activity:

  • participant_joined_via_link_webhook · participant_added_by_admin_webhook · participant_left_group_webhook · participant_kicked_from_group_webhook
  • group_admin_changed_webhook · group_name_changed_webhook · group_description_changed_webhook · group_message_pinned_webhook

Sessionssession.connected · session.disconnected

Campaignscampaign.started · campaign.paused · campaign.resumed · campaign.completed · campaign.aborted

The Create webhook reference lists the exact accepted enum.

4. Verify requests really came from Blueticks

Blueticks does not sign webhook payloads. To confirm a request is genuinely from us, register a URL containing a secret only you know — a hard-to-guess path segment or query string — and reject any POST that doesn't carry it:

https://api.your-server.com/bt-webhooks?token=ek3f9q2...

Always serve the endpoint over HTTPS so that secret stays private in transit.

5. Reliability: retries & auto-disable

  • Each delivery attempt must complete within 10 seconds.
  • A non-2xx response or a timeout is retried — up to 8 attempts total (the first delivery plus 7 retries) over roughly 21 hours, with growing backoff between attempts: 1m → 5m → 15m → 1h → 2h → 6h → 12h.
  • Because of retries, the same event can arrive more than once — dedupe on the delivery id.
  • After 8 consecutive failures, the endpoint auto-disables. Once your server is healthy, re-enable it by patching status: "enabled" (next section).

6. Manage your webhooks

List every endpoint, fetch one by id, change its URL / events / status, or delete it:

curl -X GET 'https://api.blueticks.co/v1/webhooks' \  -H 'Authorization: Bearer BLUETICKS_API_KEY'
import blueticksbt = blueticks.Blueticks(api_key="BLUETICKS_API_KEY")result = bt.webhooks.list()
import { Blueticks } from 'blueticks';const bt = new Blueticks({ apiKey: 'BLUETICKS_API_KEY' });const result = await bt.webhooks.list();
use Blueticks\Blueticks;$bt = new Blueticks(['apiKey' => 'BLUETICKS_API_KEY']);$result = $bt->webhooks->list();
require "blueticks"client = Blueticks::Client.new(api_key: "BLUETICKS_API_KEY")result = client.webhooks.list()
import (	"context"	blueticks "github.com/serenix-com/blueticks-go")client, _ := blueticks.NewClient(blueticks.WithAPIKey("BLUETICKS_API_KEY"))result, _ := client.Webhooks.List(context.Background())
curl -X GET 'https://api.blueticks.co/v1/webhooks/string' \  -H 'Authorization: Bearer BLUETICKS_API_KEY'
import blueticksbt = blueticks.Blueticks(api_key="BLUETICKS_API_KEY")result = bt.webhooks.get(    "id_01H7...",)
import { Blueticks } from 'blueticks';const bt = new Blueticks({ apiKey: 'BLUETICKS_API_KEY' });const result = await bt.webhooks.get('id_01H7...');
use Blueticks\Blueticks;$bt = new Blueticks(['apiKey' => 'BLUETICKS_API_KEY']);$result = $bt->webhooks->retrieve('id_01H7...');
require "blueticks"client = Blueticks::Client.new(api_key: "BLUETICKS_API_KEY")result = client.webhooks.get(  "id_01H7...",)
import (	"context"	blueticks "github.com/serenix-com/blueticks-go")client, _ := blueticks.NewClient(blueticks.WithAPIKey("BLUETICKS_API_KEY"))result, _ := client.Webhooks.Get(context.Background(), "id_01H7...")
curl -X PATCH 'https://api.blueticks.co/v1/webhooks/string' \  -H 'Authorization: Bearer BLUETICKS_API_KEY' \  -H 'Content-Type: application/json' \  -d '{  "url": "https://example.com",  "events": [    "message.queued"  ],  "description": "string",  "status": "enabled"}'
import blueticksbt = blueticks.Blueticks(api_key="BLUETICKS_API_KEY")result = bt.webhooks.update(    "id_01H7...",    # request body fields…,)
import { Blueticks } from 'blueticks';const bt = new Blueticks({ apiKey: 'BLUETICKS_API_KEY' });const result = await bt.webhooks.update('id_01H7...', { /* … */ });
use Blueticks\Blueticks;$bt = new Blueticks(['apiKey' => 'BLUETICKS_API_KEY']);$result = $bt->webhooks->update('id_01H7...', /* opts */);
require "blueticks"client = Blueticks::Client.new(api_key: "BLUETICKS_API_KEY")result = client.webhooks.update(  "id_01H7...",  # request body fields…,)
import (	"context"	blueticks "github.com/serenix-com/blueticks-go")client, _ := blueticks.NewClient(blueticks.WithAPIKey("BLUETICKS_API_KEY"))result, _ := client.Webhooks.Update(context.Background(), "id_01H7...", params)
{  "url": "https://example.com",  "events": [    "message.queued"  ],  "description": "string",  "status": "enabled"}
curl -X DELETE 'https://api.blueticks.co/v1/webhooks/string' \  -H 'Authorization: Bearer BLUETICKS_API_KEY'
import blueticksbt = blueticks.Blueticks(api_key="BLUETICKS_API_KEY")result = bt.webhooks.delete(    "id_01H7...",)
import { Blueticks } from 'blueticks';const bt = new Blueticks({ apiKey: 'BLUETICKS_API_KEY' });const result = await bt.webhooks.delete('id_01H7...');
use Blueticks\Blueticks;$bt = new Blueticks(['apiKey' => 'BLUETICKS_API_KEY']);$result = $bt->webhooks->delete('id_01H7...');
require "blueticks"client = Blueticks::Client.new(api_key: "BLUETICKS_API_KEY")result = client.webhooks.delete(  "id_01H7...",)
import (	"context"	blueticks "github.com/serenix-com/blueticks-go")client, _ := blueticks.NewClient(blueticks.WithAPIKey("BLUETICKS_API_KEY"))result, _ := client.Webhooks.Delete(context.Background(), "id_01H7...")

To re-enable an auto-disabled endpoint, PATCH it with status: "enabled" once your server is healthy again.