Webhooks API
Endpoints for managing webhook subscriptions.
Webhook Object​
{
"id": "webhook_123abc",
"url": "https://your-server.com/webhooks/propertybase",
"events": ["lead.created", "lead.stage_changed", "deal.closed"],
"secret": "whsec_xxxxxxxxxxxxx",
"active": true,
"created_at": "2024-01-15T10:00:00Z",
"last_triggered": "2024-01-25T14:30:00Z",
"stats": {
"deliveries_total": 150,
"deliveries_successful": 148,
"deliveries_failed": 2
}
}
Available Events​
| Event | Description |
|---|---|
lead.created | New lead created |
lead.updated | Lead details updated |
lead.stage_changed | Lead moved to new stage |
lead.assigned | Lead assigned to agent |
lead.won | Lead marked as won |
lead.lost | Lead marked as lost |
property.created | New property created |
property.updated | Property updated |
property.status_changed | Property status changed |
unit.created | New unit created |
unit.updated | Unit updated |
unit.sold | Unit marked as sold |
agent.created | New agent added |
agent.deactivated | Agent deactivated |
deal.created | New deal created |
deal.closed | Deal closed |
commission.calculated | Commission calculated |
invoice.created | Invoice generated |
List Webhooks​
GET /v1/webhooks
Example Request​
curl -X GET "https://api.propertybase.ai/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY"
Example Response​
{
"success": true,
"data": [
{
"id": "webhook_123abc",
"url": "https://your-server.com/webhooks/propertybase",
"events": ["lead.created", "lead.stage_changed"],
"active": true,
"last_triggered": "2024-01-25T14:30:00Z"
}
]
}
Get Webhook​
GET /v1/webhooks/:id
Example Request​
curl -X GET "https://api.propertybase.ai/v1/webhooks/webhook_123abc" \
-H "Authorization: Bearer YOUR_API_KEY"
Create Webhook​
POST /v1/webhooks
Request Body​
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Webhook endpoint URL |
events | array | Yes | Events to subscribe to |
secret | string | No | Signing secret (auto-generated if not provided) |
active | boolean | No | Enable immediately (default: true) |
Example Request​
curl -X POST "https://api.propertybase.ai/v1/webhooks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/propertybase",
"events": ["lead.created", "lead.stage_changed", "deal.closed"],
"active": true
}'
Example Response​
{
"success": true,
"data": {
"id": "webhook_new456",
"url": "https://your-server.com/webhooks/propertybase",
"events": ["lead.created", "lead.stage_changed", "deal.closed"],
"secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxx",
"active": true,
"created_at": "2024-01-25T15:00:00Z"
}
}
warning
The webhook secret is only returned once when creating the webhook. Store it securely!
Update Webhook​
PUT /v1/webhooks/:id
Example Request​
curl -X PUT "https://api.propertybase.ai/v1/webhooks/webhook_123abc" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": ["lead.created", "lead.stage_changed", "deal.closed", "property.status_changed"],
"active": true
}'
Delete Webhook​
DELETE /v1/webhooks/:id
Example Request​
curl -X DELETE "https://api.propertybase.ai/v1/webhooks/webhook_123abc" \
-H "Authorization: Bearer YOUR_API_KEY"
Test Webhook​
POST /v1/webhooks/:id/test
Send a test event to your webhook endpoint.
Example Request​
curl -X POST "https://api.propertybase.ai/v1/webhooks/webhook_123abc/test" \
-H "Authorization: Bearer YOUR_API_KEY"
Example Response​
{
"success": true,
"data": {
"delivery_id": "del_test123",
"status": "delivered",
"response_code": 200,
"response_time_ms": 150
}
}
Webhook Deliveries​
GET /v1/webhooks/:id/deliveries
Get delivery history for a webhook.
Example Response​
{
"success": true,
"data": [
{
"id": "del_001",
"event": "lead.created",
"status": "delivered",
"response_code": 200,
"timestamp": "2024-01-25T14:30:00Z"
},
{
"id": "del_002",
"event": "lead.stage_changed",
"status": "failed",
"response_code": 500,
"error": "Internal server error",
"timestamp": "2024-01-25T14:35:00Z",
"next_retry": "2024-01-25T14:40:00Z"
}
]
}
Webhook Payload​
All webhook deliveries follow this format:
{
"id": "evt_abc123",
"event": "lead.created",
"timestamp": "2024-01-25T14:30:00Z",
"workspace_id": "ws_123",
"data": {
"id": "lead_456",
"name": "John Smith",
"email": "john@example.com",
"source": "website",
"stage": "new",
"created_at": "2024-01-25T14:30:00Z"
}
}
Verifying Webhooks​
Verify webhook authenticity using the signature:
Headers​
| Header | Description |
|---|---|
X-Propertybase-Signature | HMAC-SHA256 signature |
X-Propertybase-Timestamp | Request timestamp |
Verification Code​
import crypto from 'crypto';
function verifyWebhook(
payload: string,
signature: string,
timestamp: string,
secret: string
): boolean {
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expectedSignature}`)
);
}
// Usage
app.post('/webhooks/propertybase', (req, res) => {
const signature = req.headers['x-propertybase-signature'];
const timestamp = req.headers['x-propertybase-timestamp'];
if (!verifyWebhook(JSON.stringify(req.body), signature, timestamp, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process webhook...
res.status(200).send('OK');
});
Retry Policy​
Failed deliveries are automatically retried:
| Attempt | Delay |
|---|---|
| 1st retry | 5 minutes |
| 2nd retry | 30 minutes |
| 3rd retry | 2 hours |
| 4th retry | 8 hours |
| 5th retry | 24 hours |
After 5 failed attempts, the webhook is disabled and you'll be notified.
Best Practices​
- Respond quickly - Return 2xx within 5 seconds
- Process async - Queue webhook processing
- Handle duplicates - Use event ID for idempotency
- Verify signatures - Always verify webhook authenticity
- Monitor failures - Set up alerting for failed deliveries