Event webhooks
Beam pushes signed events to your endpoint the moment things happen: replies, sends, bookings, handoffs, opt-outs.
Setup
Settings → Event webhooks → paste any HTTPS endpoint → Save. Beam generates a signing secret, shown right there. Every event is a POST with a JSON body and a Beam-Signature header. Respond with any 2xx quickly and process async.
Envelope
{
"id": "evt_8c1f2a9d64b34e0f9a12",
"type": "message.received",
"timestamp": 1787340000,
"data": { ... event specific ... }
}Event catalog
| Type | When | data |
|---|---|---|
message.received | A contact texted you | from, to, body, channel, attachments |
message.sent | Any outbound went out (first touch, inbox, assistant, API) | id, to, from, body, channel, sender |
message.failed | An outbound could not be delivered | id, to, body |
contact.opted_out | A contact texted STOP | phone |
assistant.booked | The assistant booked a call | phone, window, appointment_id, slot |
assistant.handoff | The assistant needs a human | phone, reason |
Example: reply notifications in your own system
Bun.serve({
port: 3000,
async fetch(req) {
const raw = await req.text();
if (!verifyBeamSignature(raw, req.headers.get("Beam-Signature"), process.env.BEAM_WEBHOOK_SECRET)) {
return new Response("bad signature", { status: 401 });
}
const event = JSON.parse(raw);
if (event.type === "assistant.booked") {
// ping the sales floor, update the CRM, fire the AI call...
notifyTeamChannel(`🎉 call booked with ${event.data.phone}: ${event.data.window}`);
}
return new Response("OK");
},
});