What are Coachful webhooks and why do they matter?
If you've ever wanted your coaching platform to automatically talk to your CRM, fire a Slack notification when a client books a session, or trigger a Zapier workflow the moment someone enrolls in your program — webhooks are how you make that happen. Sending Coachful events to webhooks lets you push real-time data from your Coachful workspace to any external system that can receive an HTTP POST request.
Unlike polling (where an external app repeatedly asks "anything new?"), webhooks are event-driven. Coachful sends a payload the moment an event occurs — a new booking, a completed task, a payment — so your automations stay in sync without delay and without wasted API calls.
TL;DR
- Webhooks are configured in Coach Dashboard → Settings → Integrations → Webhooks.
- You provide a public HTTPS endpoint URL; Coachful sends a signed JSON POST to that URL when subscribed events fire.
- Each payload includes an
eventtype, atimestamp, and adataobject with the relevant resource. - Verify the
X-Coachful-Signatureheader on every incoming request to prevent spoofed events. - Retry logic is built in — failed deliveries are retried up to 5 times with exponential backoff.
Supported webhook events
Coachful emits webhooks across all major platform areas. Below is the current catalogue of event types you can subscribe to. Each event name follows a resource.action convention so they're easy to filter programmatically.
Booking & scheduling events
booking.created— a client books a 1:1, group call, or intake session.booking.cancelled— a booking is cancelled by the coach or client.booking.rescheduled— a booking is moved to a new time slot.booking.completed— a session is marked as completed.
Program & enrollment events
enrollment.created— a client enrolls in a program (paid or free).enrollment.completed— a client completes all tasks in a program.task.completed— a client checks off a task inside a program week/day.goal.achieved— a tracked goal is marked as achieved.habit.checked_in— a client logs a habit check-in.
Billing & payment events
payment.succeeded— a charge succeeds (one-time or recurring).payment.failed— a charge attempt fails.subscription.created— a client starts a recurring subscription offer.subscription.cancelled— a subscription is cancelled.coupon.redeemed— a client applies a coupon at checkout.
Client & squad events
client.created— a new client record is created in your workspace.client.updated— a client's profile information changes.squad.member_joined— a member joins a cohort or community squad.squad.member_left— a member leaves or is removed from a squad.message.sent— a message is sent in a squad channel (use sparingly — high volume).
How to add a webhook endpoint in Coachful
Setting up your first webhook takes about two minutes. Before you start, make sure your receiving server is publicly accessible over HTTPS — Coachful will not deliver events to plain HTTP or localhost URLs in production. For local testing, use a tunnel tool like ngrok or Smee.io to expose a local port.
- Open your Coach Dashboard and navigate to Settings → Integrations → Webhooks.
- Click Add endpoint.
- Paste your endpoint URL (must be
https://). Example:https://yourdomain.com/coachful/webhook. - Under Events to send, choose specific events or select All events. For high-traffic workspaces, we recommend subscribing only to the events you need — this reduces noise and processing overhead on your server.
- Optionally add a Description to remind yourself what this endpoint does (e.g., "Syncs new enrollments to HubSpot").
- Click Save endpoint. Coachful immediately generates a unique signing secret for this endpoint — copy it now and store it securely (you won't be able to see it again).
- Click Send test event to fire a sample payload to your endpoint and confirm delivery.
You can register up to 10 webhook endpoints per workspace on the Scale plan, and up to 3 on the Growth plan. Each endpoint can subscribe to a different subset of events, so you can route booking events to one system and payment events to another.
Pro tip: If you're building automations with no-code tools, Coachful webhooks pair perfectly with Zapier, Make (formerly Integromat), or n8n. Create a "Webhooks by Zapier" trigger, paste that URL into Coachful, and you can push enrollment data into Google Sheets, add clients to Mailchimp, or send a Slack DM — all without writing a single line of code.
Understanding the webhook payload structure
Every Coachful webhook POST request shares the same envelope structure. Here's an annotated example for a booking.created event:
{
"id": "wh_01HZ9XMPQ4EFGR7KYBVD3N",
"event": "booking.created",
"timestamp": "2025-01-15T14:32:00Z",
"workspace_id": "ws_abc123",
"data": {
"booking": {
"id": "bk_99XYZABC",
"type": "one_on_one",
"status": "confirmed",
"start_at": "2025-01-20T10:00:00Z",
"end_at": "2025-01-20T11:00:00Z",
"client": {
"id": "usr_clientid",
"name": "Jane Smith",
"email": "jane@example.com"
},
"coach": {
"id": "usr_coachid",
"name": "Alex Rivera"
}
}
}
}
Key fields to know:
id— a unique identifier for this specific delivery attempt. Use this to deduplicate events if your server receives a retry.event— the event type string. Filter on this first in your handler.timestamp— ISO 8601 UTC time the event was generated on Coachful's servers.workspace_id— useful when a single endpoint receives events from multiple Coachful workspaces.data— the resource object relevant to the event. The shape varies by event type; see the full schema reference in Webhook event schemas.
Verifying webhook signatures
Anyone who knows your endpoint URL could theoretically POST fake events to it. To prevent this, Coachful signs every delivery with a X-Coachful-Signature header. Always verify this signature before processing the payload — it's a one-minute implementation that protects your automations from spoofed data.
How the signature works
Coachful computes an HMAC-SHA256 hash of the raw request body using your endpoint's signing secret as the key. The result is hex-encoded and sent in the X-Coachful-Signature header as sha256=<hash>.
Verification example (Node.js)
const crypto = require('crypto');
function verifySignature(rawBody, signatureHeader, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
Use the raw request body (before any JSON parsing) and crypto.timingSafeEqual (or its equivalent in your language) to avoid timing attacks. If the signature doesn't match, return a 401 and discard the payload.
Need help setting this up? Ask Michelle, Coachful's built-in AI assistant, to walk you through webhook configuration directly inside your dashboard. Just type "help me set up a webhook" in the Michelle panel and she'll guide you step by step — or even pre-fill the settings form for you.
Retry behavior and delivery guarantees
Coachful delivers webhooks with an at-least-once guarantee. If your endpoint returns anything other than a 2xx HTTP status code within 10 seconds, Coachful treats the delivery as failed and schedules a retry.
The retry schedule uses exponential backoff:
- Retry 1 — 30 seconds after the first failure
- Retry 2 — 5 minutes later
- Retry 3 — 30 minutes later
- Retry 4 — 2 hours later
- Retry 5 — 8 hours later
After 5 failed retries, the delivery is marked as permanently failed and will not be retried again. You can view failed deliveries and manually re-send them from Settings → Integrations → Webhooks → [Endpoint] → Delivery logs.
Because retries can cause the same event to be delivered more than once, your handler should be idempotent — use the id field to detect and skip duplicate events you've already processed.
Pro tips for production webhook integrations
Respond fast, process async
Your endpoint should return a 200 OK response immediately — ideally in under 500 ms — and then process the payload asynchronously (e.g., push it onto a queue). If your handler does database writes, external API calls, or email sends synchronously, you risk hitting the 10-second timeout and generating unnecessary retries.
Log everything at first
During initial setup, log every incoming payload to a database table or logging service before you do anything else. This gives you a complete audit trail and makes debugging far easier when an automation behaves unexpectedly.
Subscribe narrowly
It's tempting to subscribe to "All events" for convenience, but high-frequency events like message.sent or habit.checked_in can generate thousands of requests per day for an active workspace. Subscribe only to the events your integration actually needs.
Use separate endpoints per integration
Rather than routing all events to one URL and branching by event type in your handler, consider registering separate Coachful endpoints for each downstream system. This makes delivery logs cleaner and lets you disable one integration without affecting others.
Troubleshooting common webhook problems
My endpoint is receiving events but the signature check fails
The most common cause is computing the HMAC over a parsed-then-re-serialized body instead of the raw bytes. Make sure you read the raw request body before any JSON parsing middleware touches it. In Express.js, for example, use express.raw({ type: 'application/json' }) on the webhook route instead of express.json().
Events are showing as "Delivered" in Coachful but my system isn't updating
Check whether your handler is returning a 2xx status before it finishes processing (see "Respond fast, process async" above). If Coachful gets a 200, it marks the delivery as successful regardless of what your code does next. Check your async processing queue for errors.
I'm not receiving any events at all
First, confirm your endpoint URL is publicly reachable — Coachful cannot deliver to private IPs, localhost, or non-HTTPS URLs. Use the Send test event button in the webhook settings; if that fails, you'll see an error response code in the delivery log. Also verify you've subscribed to the correct event types and that the events you're expecting are actually being triggered in your workspace.
I'm getting duplicate events
This is expected behavior with at-least-once delivery. Implement idempotency in your handler: store processed webhook id values in a fast key-value store (Redis works well) and skip any payload whose id you've seen before.
My endpoint went down for a few hours — did I lose events?
Events that failed delivery will have been retried up to 5 times over approximately 10 hours. If your endpoint was down for longer, some events may have been permanently failed. Go to Settings → Integrations → Webhooks → [Endpoint] → Delivery logs, filter by "Failed", and use the Resend button to replay them manually.
Webhook deliveries are timing out intermittently
Coachful enforces a strict 10-second response timeout. Move any slow processing (database writes, third-party API calls) out of the synchronous request handler. If you're on a serverless platform like AWS Lambda or Vercel Functions, watch for cold-start latency — pre-warming strategies or keeping a persistent worker can help.
Ready to automate your coaching workflows?
Webhooks unlock a whole layer of automation that removes repetitive admin work and keeps your tools in sync — so you spend more time coaching and less time copying data between apps. Whether you're syncing enrollments to a CRM, sending welcome emails on payment success, or updating a project board when a client completes a program milestone, Coachful's webhook system gives you the real-time data you need.
Log in to your workspace and configure your first endpoint today, or explore the rest of the Integrations section for more ways to connect Coachful to your tech stack. Not on Coachful yet? Start your free trial and see how much faster your business runs when everything talks to everything. Need more help? Browse all guides in the Coachful Help Center.