Webhooks
Receive real-time careCycle events at your own HTTPS endpoints.
Webhooks let careCycle push events to your systems the moment they happen — when a customer is created or updated, or when a call finishes — so you can keep a CRM in sync, trigger downstream automations, or build your own reporting without polling the API.
Each event is delivered as a signed POST request to the endpoint(s) you
register. careCycle only sends events to clients that have configured at least
one endpoint, so there's nothing to opt out of if you don't use webhooks.
Setting up webhooks
Webhooks are managed from Developer Settings → Webhooks in the dashboard.
Enable webhooks
Go to the Webhooks page and click Get started. This provisions webhook delivery for your organization.
Add an endpoint
Click Add Endpoint, enter the HTTPS URL that should receive events, and optionally choose which events to subscribe to. Leave the event selection empty to receive every event type.
Verify delivery
Trigger an event (for example, update a customer) and open the endpoint to see the delivery under Message attempts. Click into any message to inspect the payload, the response your endpoint returned, and the request headers.
Endpoint URLs must be publicly reachable over HTTPS. You can use a tool like webhook.site to experiment before pointing webhooks at your own service.
Verifying signatures
Every request includes signature headers so you can confirm it genuinely came from careCycle and was not tampered with:
| Header | Description |
|---|---|
svix-id | Unique identifier for the message |
svix-timestamp | Unix timestamp (seconds) of the send |
svix-signature | Space-delimited list of HMAC-SHA256 signatures |
Each endpoint has its own Signing Secret (prefixed with whsec_), visible
on the endpoint's detail page. Verify the signature over the raw request body
before trusting a payload. The signing scheme is the open
Standard Webhooks spec, so you don't have
to implement HMAC verification by hand — an official library does it for you.
Get the verification library
careCycle signs with the same scheme Svix uses, so the maintained
svix libraries work directly. They're
published on each language's standard package registry under the name svix
(the standardwebhooks
libraries are byte-for-byte compatible if you prefer the vendor-neutral name):
npm install svix
# or: pnpm add svix / yarn add svixpip install svixgo get github.com/svix/svix-webhooks/gogem install svixcomposer require svix/svixcargo add svixVerify an incoming request
Pass the raw request body and the three svix-* headers to the library. It
recomputes the HMAC with your signing secret and throws / returns an error if
the signature doesn't match. On success you get the verified payload back.
import { Webhook } from "svix"
const wh = new Webhook(process.env.CARECYCLE_WEBHOOK_SECRET) // whsec_...
// `payload` MUST be the raw request body string, not the parsed object.
const event = wh.verify(payload, {
"svix-id": req.headers["svix-id"],
"svix-timestamp": req.headers["svix-timestamp"],
"svix-signature": req.headers["svix-signature"],
})from svix.webhooks import Webhook
wh = Webhook(os.environ["CARECYCLE_WEBHOOK_SECRET"]) # whsec_...
# `payload` is the raw request body (bytes or str), not the parsed dict.
event = wh.verify(payload, {
"svix-id": request.headers["svix-id"],
"svix-timestamp": request.headers["svix-timestamp"],
"svix-signature": request.headers["svix-signature"],
})import svix "github.com/svix/svix-webhooks/go"
wh, err := svix.NewWebhook(os.Getenv("CARECYCLE_WEBHOOK_SECRET")) // whsec_...
if err != nil {
return err
}
// `body` is the raw request body bytes. `r.Header` carries the svix-* headers.
if err := wh.Verify(body, r.Header); err != nil {
http.Error(w, "invalid signature", http.StatusBadRequest)
return
}require "svix"
wh = Svix::Webhook.new(ENV["CARECYCLE_WEBHOOK_SECRET"]) # whsec_...
# `payload` is the raw request body string.
json = wh.verify(payload, {
"svix-id" => request.headers["svix-id"],
"svix-timestamp" => request.headers["svix-timestamp"],
"svix-signature" => request.headers["svix-signature"],
})use Svix\Webhook;
$wh = new Webhook(getenv("CARECYCLE_WEBHOOK_SECRET")); // whsec_...
// $payload is the raw request body string.
$json = $wh->verify($payload, [
"svix-id" => $_SERVER["HTTP_SVIX_ID"],
"svix-timestamp" => $_SERVER["HTTP_SVIX_TIMESTAMP"],
"svix-signature" => $_SERVER["HTTP_SVIX_SIGNATURE"],
]);use svix::webhooks::Webhook;
let wh = Webhook::new(&secret)?; // whsec_...
// `body` is the raw request body bytes; `headers` is the http::HeaderMap.
wh.verify(&body, &headers)?;Verify against the raw, unparsed request body. Re-serializing the JSON before
verifying will change the bytes and the signature check will fail — most web
frameworks parse JSON automatically, so reach for the raw-body accessor (e.g.
express.raw(), await request.body(), request.get_data()).
Delivery, retries, and replay
- Respond quickly with a
2xx. Any2xxstatus is treated as success. Do your heavy processing asynchronously and acknowledge fast. - Failed deliveries are retried automatically with exponential backoff.
- Replay anytime. From the endpoint or message detail page you can replay an individual delivery — useful after fixing an outage on your side.
- Order is not guaranteed. Use the event payload (and
svix-idfor idempotency) rather than assuming events arrive in the order they occurred.
Next, see the full list of events and example payloads.