Integrations & API

Webhooks

Real-time event notifications, payload formats, and security verification.

4 min readUpdated 2025-01-14

When someone buys a ticket to your kirtan evening, checks in at the door of your weekend retreat, or transfers a ticket to a friend, that action happens instantly inside BrightStar. A webhook is how your own tools find out about it just as fast, without you having to log in and check. Instead of polling BrightStar's dashboard every few minutes to see if a new order came in, BrightStar sends a message directly to a URL you control the moment the event happens. You configure that endpoint once, and BrightStar handles delivering real-time updates on orders, check-ins, and more to it going forward. This matters most for organizers running check-in tools, attendee databases, or automated follow-up flows around retreats, festivals, and ceremony gatherings — anywhere you need your own systems to stay in sync with what's actually happening at the door.

What events can trigger a webhook?

BrightStar groups webhook events around the three things that actually change during a gathering: orders, tickets, and the event listing itself.

Order events cover order.created, order.refunded, and order.cancelled — the moments someone buys in, gets money back, or backs out entirely. If you're syncing a spreadsheet of paid attendees for a retreat, order.created is the one you'll lean on most.

Ticket events cover ticket.checked_in and ticket.transferred. ticket.checked_in fires the instant a ticket is scanned at your kirtan door or festival gate, useful if you're feeding a live headcount into another system. ticket.transferred fires when someone sends their ticket to a new owner, which matters if your check-in tool needs the current attendee's name rather than whoever originally bought the ticket.

Event events — event.published, event.updated, event.cancelled — track the listing itself, useful if you mirror your event details onto your own site or app.

What's inside a webhook payload?

Every webhook BrightStar sends is a POST request with the same basic shape: an id for that specific delivery, a type telling you which event it is (order.created, ticket.checked_in, and so on), a created_at timestamp, and a data object holding the actual resource.

For an order event, that data includes the order's own id, the event_id it belongs to, the total and currency charged, and an array of tickets — each with its own id, ticket type, attendee name, and attendee email. That's enough detail to build an attendee list, print a badge, or reconcile a payment without a second call back to BrightStar. Because the same shape applies across every event type, you can write one parser and branch on type rather than treating each event as a special case.

Because your webhook URL is public, anything can POST to it — including someone trying to impersonate BrightStar and send a fake order.created to trick your system into, say, marking a ticket as paid. That's what the X-BrightStar-Signature header is for. BrightStar signs the raw payload with your webhook secret using HMAC-SHA256, and sends the result in that header, prefixed with sha256=. Your endpoint computes the same HMAC over the payload it received and compares it against the header using a timing-safe comparison, not a simple string equality check — a naive comparison can leak timing information an attacker could use to guess the signature piece by piece. If the signature doesn't match, reject the request with a 401 and don't process it. A mismatched signature means the payload wasn't actually sent by BrightStar, or was altered in transit.

What happens when delivery fails?

BrightStar gives your endpoint 30 seconds to respond and expects an HTTP 2xx status back. If your server is down, times out, or returns an error, BrightStar doesn't give up immediately — it retries, spacing the attempts out: 1 minute, then 5 minutes, then 30 minutes, then 2 hours, then 24 hours after the failure. That widening gap gives you room to notice and fix a broken endpoint without your inbox getting flooded with repeated attempts. If all five retries fail, BrightStar disables the webhook rather than continuing indefinitely. Once you've fixed whatever was wrong with your endpoint, you re-enable the webhook yourself under Settings → Webhooks — BrightStar won't silently start retrying an endpoint it has already given up on.

Best practices for handling webhooks

A few habits keep webhook handling reliable, especially once you're relying on it for check-in or attendee data at a live event:

  1. 1Verify the signature before you do anything else with the payload
  2. 2Respond with a 200 immediately, then do the actual processing asynchronously, so a slow database write doesn't cause BrightStar to think the delivery failed
  3. 3Use the webhook's id to recognize and ignore duplicate deliveries, since retries can mean the same event arrives more than once
  4. 4Log every webhook you receive so you have something to check against if data seems out of sync
  5. 5Only use HTTPS endpoints
  6. 6Keep your webhook secret out of your codebase rather than hardcoding it

Common questions

What events can BrightStar webhooks notify me about?

BrightStar sends order events for order.created, order.refunded and order.cancelled, ticket events for ticket.checked_in and ticket.transferred, and event events for event.published, event.updated and event.cancelled. Each is delivered as a POST to the webhook URL you configure.

Read more

Grouping events this way means you don't have to build one giant listener; you can subscribe your check-in tablet only to ticket.checked_in, your accounting spreadsheet only to order events, and your public site to event.published and event.updated, so each part of your stack only reacts to the changes it actually cares about.

How do I verify a webhook actually came from BrightStar?

BrightStar signs every webhook and sends the signature in the X-BrightStar-Signature header. Compute an HMAC-SHA256 of the raw payload using your webhook secret, prefix the hex digest with sha256=, and compare it against the header using a timing-safe comparison. Always verify before processing, and reject with a 401 if the signature does not match.

Read more

Skipping this step means your endpoint will trust any POST that arrives at its URL, including one crafted by someone who found the address and wants to fake a refund or a check-in. The timing-safe comparison matters too — a plain string comparison can return faster or slower depending on how many characters match, a subtle leak an attacker could exploit over many attempts.

What happens if my webhook endpoint is down when BrightStar tries to deliver?

BrightStar allows 30 seconds for the initial delivery and expects an HTTP 2xx response. On failure it retries five times, after 1 minute, 5 minutes, 30 minutes, 2 hours and 24 hours. After five consecutive failures the webhook is disabled, and you re-enable it in Settings once the endpoint is fixed.

Read more

This staggered schedule exists so a brief outage — a deploy, a restart, a blip in your hosting — doesn't cost you the notification entirely. It also means you shouldn't expect a webhook to keep trying forever; once the five attempts are exhausted, BrightStar stops and waits for you to re-enable it, rather than retrying indefinitely on its own.

Where can I see whether my BrightStar webhooks are being delivered?

Delivery logs live under Settings then Webhooks in BrightStar. Because webhooks are disabled after five consecutive failures, it is worth monitoring your endpoint health and checking those logs if you stop receiving notifications.

Read more

Checking these logs is the fastest way to tell whether a missing notification is a BrightStar-side delivery problem or something wrong on your end, like an endpoint that changed URLs or started rejecting the signature. If you notice webhooks have gone quiet, that log is where to start before assuming something is broken elsewhere.

What does a BrightStar webhook payload look like?

BrightStar posts a JSON body containing an id such as whk_abc123xyz, a type such as order.created, a created_at timestamp, and a data object holding the resource. For an order that data includes the order ID, event ID, total, currency, and an array of tickets with each ticket's ID, type, attendee name and attendee email.

Read more

Keeping the envelope — id, type, created_at — identical across every event type is deliberate: it means you can write one piece of code that checks type and routes to the right handler, rather than parsing a completely different structure for an order.created event versus a ticket.checked_in event. Only the contents of data change shape depending on what happened.

How should I handle duplicate webhook deliveries?

BrightStar recommends using the webhook ID included in every payload to detect and ignore duplicates. Alongside that, respond with a 200 immediately and process asynchronously, log all received webhooks for debugging, use HTTPS endpoints only, and keep your webhook secret out of your code.

Read more

Duplicates aren't a bug — they're a normal consequence of a retry system that would rather send an event twice than risk you missing it once. Treating the webhook id as a unique key, the same way you'd treat an order number, is what lets you safely ignore the second copy without extra coordination with BrightStar.

Ready to get started?

Create your first event on EveryEvent Bangkok — it’s free.