Skip to main content

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​

EventDescription
lead.createdNew lead created
lead.updatedLead details updated
lead.stage_changedLead moved to new stage
lead.assignedLead assigned to agent
lead.wonLead marked as won
lead.lostLead marked as lost
property.createdNew property created
property.updatedProperty updated
property.status_changedProperty status changed
unit.createdNew unit created
unit.updatedUnit updated
unit.soldUnit marked as sold
agent.createdNew agent added
agent.deactivatedAgent deactivated
deal.createdNew deal created
deal.closedDeal closed
commission.calculatedCommission calculated
invoice.createdInvoice 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​

FieldTypeRequiredDescription
urlstringYesWebhook endpoint URL
eventsarrayYesEvents to subscribe to
secretstringNoSigning secret (auto-generated if not provided)
activebooleanNoEnable 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​

HeaderDescription
X-Propertybase-SignatureHMAC-SHA256 signature
X-Propertybase-TimestampRequest 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:

AttemptDelay
1st retry5 minutes
2nd retry30 minutes
3rd retry2 hours
4th retry8 hours
5th retry24 hours

After 5 failed attempts, the webhook is disabled and you'll be notified.

Best Practices​

  1. Respond quickly - Return 2xx within 5 seconds
  2. Process async - Queue webhook processing
  3. Handle duplicates - Use event ID for idempotency
  4. Verify signatures - Always verify webhook authenticity
  5. Monitor failures - Set up alerting for failed deliveries