Webhooks: real-time call and SMS delivery events
Get every call and text delivery pushed to your CRM or portal the moment it happens, signed so you know it came from Call Bullet.
Events
- call.created — A call has started ringing a tracking number.
- call.completed — The call ended: answered, missed or failed. Use this for most CRMs.
- call.updated — Details changed after the call, e.g. attribution, transcript or lead status.
- sms.sent — A text was accepted by the mobile network. Payload: data.message.
- sms.delivered — The handset confirmed receipt — instant delivery proof, no polling.
- sms.failed — A text failed or expired; error_code and error_detail explain why.
- sms.clicked — A tracked link in a text was opened (send with track_links:true). Simulated tests never fire webhooks; live tests do.
- sms.sender.approved — A sender name or number was approved. Payload: data.sender. Resume go-live automatically.
- sms.sender.rejected — A sender was rejected; data.sender.status_reason explains why.
Set up
- Sign in → Integrations → Developer API → Webhooks.
- Enter an HTTPS URL, choose events and the client workspaces it covers.
- Copy the signing secret into your server's secret storage.
Headers
X-Call-Bullet-Event: call.completed X-Call-Bullet-Delivery: <event UUID> X-Call-Bullet-Timestamp: <Unix seconds> X-Call-Bullet-Signature: v1=<HMAC-SHA256(secret, timestamp + "." + raw_body)>
Verify the signature (Node.js)
const expected = "v1=" + crypto.createHmac("sha256", secret)
.update(timestamp + "." + rawBody).digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return 401;Retries and idempotency
Reply 2xx within 10 seconds. Failed deliveries retry with backoff and every attempt is logged. Store X-Call-Bullet-Delivery and ignore repeats. A webhook only ever receives calls and messages for the workspaces and numbers it was set up for.