Outgoing Webhooks
11 min
push real time entity events from custify to your own systems with signed, retried, observable https deliveries overview outgoing webhooks let your engineering team subscribe to changes that happen inside custify and receive them as signed json payloads on your own https endpoints whenever a note is added on a customer 360 profile, a task is updated, a survey response comes in, or a customer portal link is created, custify pushes the event to every endpoint that subscribed to it — no polling, no glue layers, no zapier in the middle who it's for engineering teams connecting custify to data warehouses, bi pipelines, internal cs tooling, or backend automations that need to react in real time how it's different from playbook webhooks playbook webhooks are configured inside a specific automation flow and fire as one step in that sequence outgoing webhooks are independent they fire on entity level changes (created, updated, received), independent of any automation the capabilities you get from this module include configure multiple endpoints with their own url, event subscriptions, custom headers, and signing secret subscribe to a defined catalog of entity events covering notes, tasks https //kb custify com/tasks , surveys https //kb custify com/surveys , and customer portal https //kb custify com/customer portal links sign every payload with hmac sha256, so your receiver can verify authenticity retry failed deliveries automatically with exponential backoff (up to 5 attempts) auto disable broken endpoints after 50 consecutive failures inspect every delivery in a built in log with request and response bodies send a test payload from the ui to validate your endpoint setup custify tip outgoing webhooks are most useful when your team already has a backend service that owns the source of truth for customer data if your goal is to push customer attributes back into a crm, the integrations docid\ jffsupfbyhwcg43nhfbl7 you have configured may be a simpler route use webhooks when you need raw event data delivered as it happens creating a webhook endpoint to configure your first endpoint, navigate to settings developer outgoing webhooks and click new endpoint the creation modal walks you through four sections identity, destination, event subscriptions, and custom headers the fields you fill in during creation are name a short label that identifies this endpoint in the list and in delivery logs use something descriptive like "data warehouse sync" or "internal cs dashboard " destination url the https url custify will post payloads to http urls are rejected — your endpoint must terminate tls localhost urls are not accepted in production subscribed events a checkbox list of every event you want this endpoint to receive you can subscribe to as many or as few as you need; events that are not checked are simply not delivered custom headers optional key/value pairs added to every outgoing request common uses are an authorization token for your own server, a routing tag, or a tenant identifier once you click save endpoint, custify generates a signing secret and displays it once in a one time reveal panel copy this secret immediately into your secret manager after you close the modal, the secret is masked everywhere in the ui and cannot be retrieved — only rotated observation the signing secret is shown only at creation time and after a rotation if you lose it before saving it on your side, you will need to regenerate the secret, which invalidates the old one within the rotation window plan to capture it as part of your endpoint setup procedure after saving, your new endpoint appears in the list with a status toggle, a health indicator, and an action menu click send test on the row to dispatch a test ping payload to your url — this is the fastest way to confirm your receiver is reachable and your custom headers are wired correctly before you depend on real events custify tip you need the settings manage app permission to create, edit, delete, or toggle endpoints users with settings view data can open settings developer outgoing webhooks and inspect endpoints and delivery logs, but they cannot make changes review your role configuration under settings https //kb custify com/settings before rolling this out to a wider team subscribed events and payload format the event catalog is organized by the entity that changed the current set of events you can subscribe to is note created / note updated — fired when a note is added or modified on a company or person record, including notes posted by a playbook https //kb custify com/playbooks step task created / task updated — fired when a task is created or its fields change (status, assignee, due date, priority, tags) survey response received — fired when a survey https //kb custify com/surveys response (nps or csat) is recorded on a person's profile portal link created / portal link updated — fired when a customer portal https //kb custify com/customer portal link is generated, or its template/configuration is changed every payload follows the same envelope the body is a json object with a top level id , type , created at , account id , and a data field containing the entity itself the shape of data matches the same structure you would see for that entity through the api, so anything you already do with sending data to custify docid\ diwcguzvhzr94xmqqqax8 and the public api will feel familiar on the receiving side every request also carries a fixed set of http headers the headers custify always sends include content type always application/json; charset=utf 8 x custify signature the hmac sha256 signature of the raw request body x custify event the event type string (for example, task updated ) x custify delivery a unique delivery id you can use for idempotency on your side observation x custify signature and content type are reserved headers if you add a custom header with the same name in the endpoint configuration, the reserved value wins, and your override is silently dropped this is intentional — it guarantees that signature verification on your side never breaks because of a misconfigured custom header verifying signatures every payload is signed with hmac sha256 using your endpoint's signing secret as the key and the raw request body as the message your receiver should compute the same signature on its side and compare it to the value in x custify signature before trusting the payload the verification flow your endpoint should follow is straightforward read the raw request body as bytes (do not parse and re serialize the json — whitespace differences will break the comparison) compute hmac sha256(secret, raw body) and hex encode the result compare it to the x custify signature header using a constant time comparison if they match, process the event if they do not, return a 4xx response and do not act on the payload when you need to rotate the secret — for example, after a team member with access leaves — open the endpoint and click rotate secret custify generates a new secret, shows it once, and keeps the previous secret valid for a 24 hour rotation window during those 24 hours, signatures generated with either secret are accepted, which gives you time to deploy the new secret to your receiver without missing deliveries after the window closes, only the new secret is valid treat your signing secret like a production credential anyone who holds it can forge payloads that pass your verification check store it in your secret manager, scope access tightly, and rotate it any time you suspect it has been exposed delivery, retries, and health when an event fires, custify dispatches it to every active endpoint subscribed to it a delivery is considered successful when your receiver returns a 2xx response within the timeout window any other outcome — a 4xx, a 5xx, a connection refused, a tls handshake failure, or a timeout — is treated as a failure and queued for retry the retry schedule follows an exponential backoff custify retries up to 5 times, with delays growing from 1 minute to 12 hours between attempts once the 5 retries are exhausted, the delivery is marked as permanently failed and stays in the log for manual retry each endpoint also tracks a rolling consecutive failure count when that count reaches 50, the endpoint is automatically disabled and its health badge flips to failing the health indicator on each endpoint reflects recent delivery behavior healthy (green) recent deliveries are succeeding degraded (amber) some recent deliveries are failing, but the endpoint is still active failing (red) the endpoint has hit the auto disable threshold and is no longer receiving deliveries no data the endpoint is new or has not received any events yet observation when an endpoint auto disables, queued events are not held forever new events that fire while the endpoint is disabled are not delivered and are not replayed when you re enable it if you need to backfill, query the relevant entities through the api after fixing the receiver and bringing the endpoint back online to bring a disabled endpoint back, fix the underlying issue on your receiver, then toggle the endpoint on again the consecutive failure counter resets on the first successful delivery after re enabling managing endpoints and viewing delivery logs each endpoint row in settings developer outgoing webhooks exposes the management actions you need day to day from the action menu you can edit the endpoint, rotate its secret, disable it temporarily with the status toggle, or delete it to see what is actually happening on the wire, click delivery logs on the endpoint row or open the central log under settings developer outgoing webhooks view logs the log lists every delivery attempt with its event type, timestamp, response code, response time, and final status (delivered, retrying, or failed) click any entry to expand the full request body, response body, response headers, and the timeline of retry attempts for any failed delivery, click retry in the detail panel to dispatch the same payload again this is useful when you have already fixed your receiver and want to replay a specific event without waiting for a fresh one to occur delivery logs are retained for 14 days older entries are automatically cleaned up, so if you need a longer audit trail, forward the events into your own log store or warehouse from the receiver observation deleting an endpoint immediately stops all deliveries to that url and removes the signing secret deleted endpoints cannot be restored if you only want to pause deliveries while you investigate an issue on your side, use the status toggle instead — that way, the endpoint configuration, signing secret, and recent delivery logs remain intact
