Webhook integration

IN THIS ARTICLE
The Webhooks integration allows automations to send event data to custom endpoints using the Send Webhook action.
What are webhooks?
Webhooks are a way for Estii to send real-time data to external systems when events occur. Unlike traditional integrations that require platform-specific setup, webhooks allow you to send event data to any HTTPS endpoint you control.
This makes webhooks ideal for:
- Building custom integrations with internal tools
- Connecting to automation platforms like n8n, Make.com, or Zapier
- Triggering workflows in systems that support webhook receivers
- Integrating with platforms not yet directly supported by Estii
Setting up webhook automations
Webhooks don't require any connection setup in the Integrations tab. You can start using them immediately by creating an automation with a Send Webhook action.
Creating a webhook automation
- Go to Settings > Workflow > Automations
- Click "Create Automation" or use a template
- Select an event to trigger the automation (e.g., "Deal Updated")
- Add conditions if needed to filter when the webhook fires
- Add a "Send Webhook" action
- Configure the webhook URL, secret, and optional message


Webhook configuration
When you add a Send Webhook action, you'll need to configure the following fields:
Webhook URL (required)
The HTTPS endpoint where Estii will send the webhook payload. This must be a valid HTTPS URL (except for localhost/127.0.0.1 which is allowed for development).
Example: https://hooks.example.com/estii-events or http://localhost:3000/webhook
Message (optional)
An optional custom message that will be included in the webhook payload. This field supports dynamic values from the triggering event using the $field syntax.
Example: Deal $name status changed to $status
Webhook payload
All webhooks send a JSON payload with the following structure:
{
"event": "estii_deal_updated",
"space_id": "abc123",
"timestamp": "2026-01-27T14:30:00.000Z",
"deal": {
"id": "xyz789",
"url": "https://app.estii.com/abc123/deals/xyz789",
"name": "Acme Project",
"status": "approved",
"price": 55000,
"cost": 40000,
"currency": "usd",
"margin": 0.27,
"start": "2026-02-01T00:00:00.000Z",
"end": "2026-03-15T00:00:00.000Z",
"due": "2026-01-31T00:00:00.000Z",
"owner": {
"id": "member_456",
"name": "Dom"
}
},
"changes": {
"status": "draft"
},
"message": "Deal Acme Project approved"
}
Payload fields
| Field | Type | Description |
|---|---|---|
event | string | The type of event that triggered the webhook (e.g., "estii_deal_updated") |
space_id | string | The ID of the space where the event occurred |
timestamp | string | ISO 8601 timestamp of when the event occurred |
deal | object | Current state of the deal (see Deal fields below) |
changes | object | Previous values of fields that changed (empty if no tracked fields changed) |
message | string | Your custom message (if configured) |
Deal fields
The deal object contains the current state of all tracked deal fields:
| Field | Type | Description |
|---|---|---|
id | string | The ID of the deal |
url | string | Direct link to the deal in Estii |
name | string | Deal name |
status | string | Deal status (draft/approved/won/lost/abandoned) |
price | number | Deal price in space currency (rounded to 2 decimal places) |
cost | number | Deal cost in space currency (rounded to 2 decimal places) |
currency | string | Deal currency code (e.g., "usd", "gbp") |
margin | number | Deal margin (0-1, rounded to 4 decimal places) |
target_price | number | Target price (rounded to 2 decimal places) |
probability | number | Win probability (0-1, rounded to 4 decimal places) |
start | string | Estimated start date (ISO 8601 timestamp) |
end | string | Estimated end date (ISO 8601 timestamp) |
due | string | Due date (ISO 8601 timestamp) |
description | string | Deal description |
owner | object (optional) | Deal owner information (only present if deal has an owner) |
owner.id | string | The member ID of the deal owner |
owner.name | string | The display name of the deal owner |
Changes object
The changes object contains the previous values of fields that changed. This allows you to:
- See what changed by checking which keys are present
- Know the previous value for each changed field
- Detect the nature of the change by comparing with current values in
deal
Example when status changed from "draft" to "approved":
"changes": {
"status": "draft"
}
If no tracked fields changed, changes will be an empty object: {}
Verifying webhook requests
Every webhook request includes an X-Estii-Webhook header containing the secret you configured. Your receiving endpoint should verify this header matches your stored secret before processing the payload.
Example verification (Node.js):
app.post('/estii-webhook', (req, res) => {
const receivedSecret = req.headers['x-estii-webhook'];
const expectedSecret = process.env.ESTII_WEBHOOK_SECRET;
if (receivedSecret !== expectedSecret) {
return res.status(401).json({ error: 'Invalid secret' });
}
// Process the webhook payload
const { event, space_id, deal, changes } = req.body;
console.log(`Received ${event} for deal ${deal.id}`);
// Check what changed
if (changes.status) {
console.log(`Status changed from ${changes.status} to ${deal.status}`);
}
res.status(200).json({ success: true });
});
Testing webhooks
Use the "Send Test" button in the webhook action configuration to send a sample payload to your endpoint. This helps verify your endpoint is correctly configured before the automation goes live.
The test payload uses realistic dummy data:
{
"event": "deal_updated",
"space_id": "test_space",
"timestamp": "2026-01-27T12:00:00.000Z",
"deal": {
"id": "test_deal",
"url": "https://app.estii.com/test_space/deals/test_deal",
"name": "Sample Deal",
"status": "approved",
"price": 10000,
"owner": { "id": "test_user", "name": "Test User" }
},
"changes": {},
"message": "Test message from Estii"
}
Delivery and retries
Estii attempts to deliver webhooks with the following retry logic:
- Initial attempt: Immediate delivery
- First retry: After 1 second (if initial attempt fails)
- Second retry: After 5 seconds (if first retry fails)
- Final retry: After 30 seconds (if second retry fails)
A delivery is considered successful if your endpoint returns a 2xx HTTP status code.
Important notes:
- 4xx responses (client errors) are not retried, as they typically indicate a configuration issue
- 5xx responses (server errors) and network failures trigger retries
- Failed deliveries don't block the automation from completing
Example integrations
n8n
- In n8n, create a new workflow with a Webhook trigger node
- Set the webhook to accept POST requests
- Copy the webhook URL from n8n
- In Estii, create a webhook automation and paste the URL
- Copy the secret from Estii and add header verification in n8n
Make.com
- In Make.com, create a new scenario with a Webhooks module
- Choose "Custom webhook" and create a new webhook
- Copy the webhook URL
- In Estii, create a webhook automation and paste the URL
- Use the secret in Make.com to verify incoming requests
Custom endpoint
Any HTTPS endpoint that can receive POST requests with JSON payloads can receive Estii webhooks. Ensure your endpoint:
- Accepts POST requests with
Content-Type: application/json - Verifies the
X-Estii-Webhookheader matches your stored secret - Returns a 2xx status code for successful processing
- Responds within a reasonable timeout (under 30 seconds)
Need help?
Don't hesitate to get in touch with our support team if you require further assistance on using webhook automations.