Skip to main content

Webhook integration (subscriber guide)

This page describes what your HTTPS endpoint receives from Briq when SMS webhooks are enabled for your app. It does not assume access to Briq’s internal systems or source code.

Overview

Briq sends asynchronous HTTP callbacks when SMS-related events occur—for example, after a provider accepts a message for routing, or when a delivery report updates final status. Each callback is an HTTP POST to the URL you registered, with a JSON body (the event envelope). Callbacks are sent only when:
  1. The SMS was sent using credentials linked to your developer app, and
  2. You have configured a webhook for that app and channel (for SMS, the channel is sms).
If webhooks are not configured or the message is not tied to your app, no callback is sent for that event.

Request shape

Outbound headers

Briq sends the following headers on each delivery attempt: If no secret is configured (or the secret is empty), X-Briq-Signature is omitted.

JSON envelope (top-level fields)

The body is one JSON object with stable key ordering and no extra whitespace between tokens (compact JSON). Briq signs exactly those bytes. Signing: Always verify the HMAC using the raw HTTP body as received. Re-serializing parsed JSON may change spacing or key order and will break verification.

Verifying signatures

Secret

Use the webhook signing secret shown to you when you create or rotate the webhook in the Briq developer console (or that your Briq operator provisioned for you). Store it securely (secret manager, environment variable, never in client-side code).

Algorithm

  1. Take the raw request body as bytes (use your framework’s raw body buffer, not a pretty-printed string).
  2. Read X-Briq-Signature. It has the form sha256=<lowercase_hex>.
  3. Compute HMAC-SHA256(secret_as_utf8_bytes, raw_body_bytes) and hex-encode the result.
  4. Compare your hex string to the value after sha256= using a constant-time comparison.
Do not verify by parsing JSON and calling JSON.stringify / json.dumps unless you can reproduce Briq’s exact canonical JSON; prefer raw body only.

Edge cases

Example (Python)

Example (Node.js)


Idempotency and event id

The same logical event may be delivered more than once if your server returns an error, times out, or Briq retries after a network failure. The envelope id is stable for that delivery attempt’s payload. Recommendation: Deduplicate using id, or a composite such as id + event + data.message_id. For application correlation between your send handler and webhook processing, use data.job_id (and data.recipient or data.message_id when one instant send has multiple recipients).

SMS events

Correlating webhooks with the send response

When you call POST /v1/message/send-instant (or another send endpoint that returns a job id), a successful response includes a job_id. Store it for the in-flight operation. Webhook payloads include data.job_id for submit-time events (sms.sent, submit-time sms.failed). That value is the same as the job_id returned by the send API for that job, so you can match asynchronous callbacks to the HTTP request that queued the send. For batch instant sends (multiple recipients in one request), expect one webhook per recipient for submit-time events: data.job_id is typically shared across those callbacks, while data.message_id and data.recipient differ per message. DLR events (sms.delivered, sms.failed, sms.expired) are keyed in this guide primarily by data.message_id, which is the stable id for message log and detail APIs. Use job_id to tie submit-time webhooks back to the send response; use message_id (and event) to follow a single message through delivery outcomes.

Product semantics

  • sms.sent — Briq (or the upstream provider) has accepted the message for routing after submit. This is not the same as confirmed delivery to the handset.
  • sms.delivered, sms.failed, sms.expired — Reflect delivery-report (DLR) outcomes when Briq processes a final or terminal status from the carrier path.

When you might not get a DLR event

Briq only emits DLR webhooks when the reported status maps to delivered (sms.delivered) or failed / expired (sms.failed, sms.expired). Intermediate states (e.g. still pending at the carrier) do not produce those events until a qualifying update exists.

Submit-time events

Emitted when the send pipeline finishes its submit step for your message. data object (submit-time path, e.g. sms.sent): Example data for sms.sent:

DLR (delivery report) events

Emitted when Briq applies a delivery report and maps it to a terminal-style outcome. data object (DLR path): Exact status strings match Briq’s internal lifecycle labels; treat them as opaque enums and branch on event first.

What your endpoint must return

The response body is not interpreted by Briq for success. 204 No Content or 200 OK with an empty body is sufficient.

Typical retry behavior

Unless your Briq environment is configured differently, defaults are often in this range: Exact limits are set on the Briq side. If you need numbers for SLAs or capacity planning, ask Briq support or your account contact for your deployment.

Security checklist

  1. HTTPS only — Webhook URLs must use https://. Briq rejects non-HTTPS URLs and common unsafe targets (e.g. localhost, addresses that resolve to private or loopback networks) at registration time.
  2. Verify X-Briq-Signature when your webhook has a secret.
  3. Check app_id (and X-Briq-App-ID) match the app you expect.
  4. Replay policy — The payload includes created_at. Briq does not publish a standard replay window for integrators; if you need time-based rejection, define your own rule (e.g. ignore events older than N minutes) and document it internally.

Worked example (sms.sent)

Your path and host will differ; proxy headers (e.g. X-Forwarded-*) depend on your edge.
Pretty-printed body (Briq sends compact JSON; verify signatures on the wire format):
Return 2xx after you have validated and accepted the event (or queued it internally).

Optional: inspecting deliveries

Some Briq setups expose dashboard or API features to list webhook delivery attempts, view errors, or trigger retries. Availability, URLs, and authentication are deployment- and product-specific. Use whatever your Briq operator documents—do not rely on internal or test-only routes unless explicitly provided to you.