Outbound Webhooks
Outbound webhooks allow your agency to receive real-time notifications whenever key events occur inside your DashboardFox account — such as a new workspace being created, a trial expiring, or a subscription payment failing. Instead of polling the platform for changes, your external systems (Pabbly, Zapier, Make, or your own application) are notified automatically the moment something happens.
Each webhook sends an HTTP POST request containing a JSON payload to a URL you configure. You can set up as many endpoints as you need, each with its own URL, event subscriptions, and optional security signature.
How It Works
You configure an endpoint URL and choose which events to subscribe to.
When a subscribed event occurs, DashboardFox sends an HTTP POST to your URL within seconds.
Your receiving application processes the payload and takes action — creating a record, sending an email, triggering a workflow, etc.
DashboardFox logs every delivery attempt. If your endpoint returns an error, it will retry automatically (see Retry Behaviour below).
Finding the Webhooks Settings
Webhooks are managed from your Agency settings panel:
Log in as an Agency Owner.
Click your agency name in the top navigation to open Agency Settings.
Select the Webhooks tab.
Note: Only Agency Owners can create, edit, or delete webhook endpoints. Billing Admins and Members cannot access this tab.
Creating a Webhook Endpoint
Click Add in the top-right corner of the endpoint list.
Fill in the Name field — this is just a label for your reference (e.g. "Pabbly — New Workspace").
Enter your Endpoint URL. This must be an HTTPS address. HTTP endpoints are not accepted.
Optionally enter a Signing Secret (see Signature Verification below). If provided, you will only be shown this value once — copy it immediately.
Under Events to Subscribe, check each event type you want this endpoint to receive.
Click Create. Your new endpoint will appear in the list on the left.
Tip: You can create multiple endpoints — for example, one pointed at Pabbly for workspace events and another pointed at your own API for billing events.
Editing an Endpoint
Click any endpoint in the left panel to open its settings on the right. You can update the name, URL, and event subscriptions at any time, then click Save.
Changing the signing secret: The secret cannot be edited directly after creation. Click Regenerate to generate a new one. The new secret is shown once — update your receiving application before navigating away.
Enabling and Disabling an Endpoint
Each endpoint has a toggle switch in the endpoint list. Flipping it off pauses all deliveries to that endpoint without deleting it. Toggle it back on at any time to resume.
Deleting an Endpoint
Select the endpoint, then click Delete in the top-right of the editor panel. You will be asked to confirm. Deletion is permanent and will remove all delivery history for that endpoint.
Testing an Endpoint
With an endpoint selected, click the Test button. DashboardFox will send a sample payload for each of the endpoint's subscribed events, with the "test": true flag set in the envelope. The results are shown immediately and are also visible in the Delivery Log below the editor.
Tip: Use the Test button to verify your receiving application is reachable and parsing the payload correctly before going live.
Delivery Log
The delivery log shows the last 10 attempts for the selected endpoint. Each row displays:
Event type — which event triggered the delivery
HTTP status code — the response returned by your endpoint
Duration — how long your endpoint took to respond
Timestamp — when the attempt was made
Attempt number — 1 for the initial delivery, 2–4 for retries
Click any row to expand it and see the full payload that was sent and the response body your endpoint returned.
Retry Behaviour
If your endpoint returns a non-2xx status code or times out, DashboardFox will retry the delivery automatically:
Attempt | Delay After Previous Attempt |
|---|---|
1 (initial) | Immediate |
2 | 30 seconds |
3 | 5 minutes |
4 | 1 hour |
After 4 attempts with no success, the delivery is marked as failed. No further retries will occur. Each attempt is logged individually in the Delivery Log.
Note: Your endpoint must respond within 10 seconds. Responses that take longer are treated as a timeout and counted as a failed attempt.
Signature Verification (Optional but Recommended)
If you configure a signing secret, every delivery will include two additional HTTP headers:
Header | Description |
|---|---|
| HMAC-SHA256 signature of the request body, prefixed with |
| Unix timestamp (milliseconds) when the request was sent |
How to verify the signature
To confirm a delivery is genuinely from DashboardFox and has not been tampered with:
Read the raw request body as a string (before any JSON parsing).
Compute HMAC-SHA256 of the body string using your signing secret.
Compare the result (prefixed with
sha256=) against the value inX-Webhook-Signature.Optionally, check that
X-Webhook-Timestampis within an acceptable window (e.g. 5 minutes) to protect against replay attacks.
Example — Node.js
const crypto = require('crypto'); function verifyWebhook(rawBody, signature, secret) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) // raw string, not parsed JSON .digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) );}
Example — PHP
function verifyWebhook(string $rawBody, string $signature, string $secret): bool { $expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret); return hash_equals($expected, $signature);}
Payload Envelope
Every event — regardless of type — uses the same outer envelope:
{ "event": "workspace.created", "fired_at": "2026-02-24T17:00:00Z", "test": false, "agency_id": "agency-abc123", "data": { ...event-specific fields... }}
Field | Type | Description |
|---|---|---|
| string | The event slug that triggered this delivery |
| string | ISO 8601 UTC timestamp of when the event fired |
| boolean |
|
| string | Your agency identifier |
| object | Event-specific payload — see reference below |
Event Reference
workspace.created
Fired when a new workspace is created under your agency.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "tier_name": "professional", "agency_id": "agency-abc123"}
workspace.deleted
Fired when a workspace is permanently deleted.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "tier_name": "professional", "agency_id": "agency-abc123"}
workspace.suspended
Fired when a workspace is suspended — typically due to a payment issue.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "tier_name": "professional", "agency_id": "agency-abc123"}
workspace.reactivated
Fired when a suspended workspace is reactivated.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "tier_name": "professional", "agency_id": "agency-abc123"}
workspace.transfer_completed
Fired when an ownership transfer of a workspace is accepted and completed.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "from_email": "old-owner@acme.com", "to_email": "new-owner@acme.com", "agency_id": "agency-abc123"}
workspace.trial_started
Fired when a new workspace enters its trial period.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "trial_ends_at": "2026-03-17T00:00:00Z", "agency_id": "agency-abc123"}
workspace.trial_expiring
Fired when a trial is 3 days away from expiring. Useful for sending reminder emails or prompting upgrade flows. This event fires once per workspace per day while the 3-day window applies.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "trial_ends_at": "2026-03-17T00:00:00Z", "agency_id": "agency-abc123"}
workspace.trial_expired
Fired when a trial period ends and the workspace has not been converted to a paid subscription.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "trial_ends_at": "2026-03-17T00:00:00Z", "agency_id": "agency-abc123"}
subscription.upgraded
Fired when a workspace moves to a higher subscription tier.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "old_tier": "Starter", "new_tier": "Professional", "billing_cycle": "monthly", "agency_id": "agency-abc123"}
subscription.downgraded
Fired when a workspace moves to a lower subscription tier.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "old_tier": "Professional", "new_tier": "Starter", "billing_cycle": "monthly", "agency_id": "agency-abc123"}
subscription.cancelled
Fired when a subscription is cancelled. The workspace will continue to function until the end of the current billing period.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "tier_name": "professional", "agency_id": "agency-abc123"}
subscription.reactivated
Fired when a previously cancelled subscription is reactivated before it fully lapses.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "tier_name": "professional", "agency_id": "agency-abc123"}
subscription.payment_failed
Fired when a subscription payment attempt fails. The retry_count field indicates how many times payment has been attempted for this billing cycle.
"data": { "workspace_id": 1042, "workspace_name": "Acme Corp", "owner_email": "jane@acme.com", "amount": 49.00, "currency": "USD", "invoice_id": "INV-00892", "retry_count": 1, "agency_id": "agency-abc123"}
user.registered
Fired when a new user completes registration under your agency.
"data": { "user_id": 204, "user_email": "jane@acme.com", "user_name": "Jane Smith", "agency_id": "agency-abc123"}
user.deleted
Fired when a user exercises their right to deletion and their account is removed.
"data": { "user_id": 204, "user_email": "jane@acme.com", "user_name": "Jane Smith", "agency_id": "agency-abc123"}
team.member_invited
Fired when an agency owner invites someone to join the agency team, or directly adds an existing user.
"data": { "agency_id": "agency-abc123", "agency_name": "My Agency", "invitee_email": "colleague@acme.com", "role": "member", "invited_by_email": "owner@agency.com"}
team.member_joined
Fired when an invited user accepts their invitation and joins the agency team.
"data": { "agency_id": "agency-abc123", "agency_name": "My Agency", "invitee_email": "colleague@acme.com", "role": "member", "invited_by_email": "owner@agency.com"}
team.member_removed
Fired when a team member is removed from the agency.
"data": { "agency_id": "agency-abc123", "agency_name": "My Agency", "invitee_email": "colleague@acme.com", "role": "member", "invited_by_email": "owner@agency.com"}
Event Quick Reference
Event | When it fires |
|---|---|
| A new workspace is created |
| A workspace is permanently deleted |
| A workspace is suspended |
| A suspended workspace is reactivated |
| A workspace ownership transfer completes |
| A new workspace enters its trial period |
| A trial is 3 days from expiring (fires daily) |
| A trial period ends without conversion |
| A workspace moves to a higher tier |
| A workspace moves to a lower tier |
| A subscription is cancelled |
| A cancelled subscription is reactivated |
| A payment attempt fails |
| A new user registers |
| A user account is deleted |
| A team member is invited or directly added |
| An invited team member accepts their invite |
| A team member is removed from the agency |
Common Use Cases
Goal | Events to subscribe |
|---|---|
Sync new customers to your CRM |
|
Automate trial nurture emails |
|
Trigger dunning workflows |
|
Update billing records on plan changes |
|
Audit team access in your own system |
|
Deprovision accounts on deletion |
|
Tips & Best Practices
Always respond quickly. Return a 200 status as soon as you receive the request, then process the payload asynchronously. If your handler takes longer than 10 seconds, DashboardFox will treat it as a timeout and retry.
Check the test flag. Deliveries sent via the Test button have "test": true set. Filter these out in your production logic if needed.
Use signature verification. Always configure a signing secret and verify the X-Webhook-Signature header to confirm deliveries are genuinely from DashboardFox.
Make your handler idempotent. Due to retries, your endpoint may occasionally receive the same event more than once. Design your logic to handle duplicate deliveries gracefully.
Use the delivery log for debugging. If your automation isn't triggering as expected, open the endpoint in the Webhooks tab and check the delivery log. The full request payload and your endpoint's response body are both visible there.