Webhooks¶
MeterBase receives webhook events from Propexo to stay in sync with your property management system in real time. This guide covers webhook setup, event types, payload format, and signature verification.
Overview¶
Webhooks allow Propexo to push data change notifications to MeterBase as they happen, rather than requiring MeterBase to poll for updates. When a property is updated, a lease is signed, or a sync completes in your PMS, Propexo sends an HTTP POST request to MeterBase's webhook endpoint.
Setting Up Webhook Endpoints¶
Step 1: Configure the Webhook URL in Propexo¶
In the Propexo dashboard:
- Navigate to Settings > Webhooks
- Click Add Endpoint
- Enter the MeterBase webhook URL:
https://your-meterbase-domain.com/api/webhooks/propexo - Select the events you want to receive (or select all)
- Copy the Signing Secret provided by Propexo
Step 2: Configure MeterBase¶
Add the signing secret to your .env file:
Step 3: Verify Connectivity¶
Propexo provides a Test button in the webhook configuration. Click it to send a test event and verify that MeterBase receives and acknowledges it.
# You can also test manually with curl
curl -X POST https://your-meterbase-domain.com/api/webhooks/propexo \
-H "Content-Type: application/json" \
-H "X-Propexo-Signature: test_signature" \
-d '{
"event": "test.ping",
"timestamp": "2026-03-25T10:00:00Z",
"data": {}
}'
HTTPS Required
Propexo requires webhook endpoints to use HTTPS. For local development, use a tunneling service like ngrok to expose your local endpoint with an HTTPS URL.
Propexo Webhook Events¶
data.new¶
Sent when a new record is created in the PMS.
Triggers:
- New property added to the PMS
- New unit created
- New lease signed
- New resident record created
MeterBase Action: If the property is linked to MeterBase, new units and leases are automatically imported. New properties are flagged for review in the Propexo integration dashboard.
Payload:
{
"event": "data.new",
"timestamp": "2026-03-25T14:30:00Z",
"connection_id": "conn_abc123",
"resource_type": "unit",
"data": {
"id": "unit_xyz789",
"property_id": "prop_001",
"unit_number": "305",
"sqft": 950,
"bedrooms": 2,
"bathrooms": 1,
"status": "vacant"
}
}
data.update¶
Sent when an existing record is modified in the PMS.
Triggers:
- Property details changed (name, address, etc.)
- Unit details changed (sqft, bedroom count, etc.)
- Lease updated (occupant count changed, lease renewed, etc.)
- Resident moved out (unit status changed to vacant)
MeterBase Action: The corresponding local record is updated. If the change affects RUBS calculations (e.g., occupancy status change), a notification is generated.
Payload:
{
"event": "data.update",
"timestamp": "2026-03-25T15:00:00Z",
"connection_id": "conn_abc123",
"resource_type": "unit",
"data": {
"id": "unit_xyz789",
"property_id": "prop_001",
"unit_number": "305",
"sqft": 950,
"bedrooms": 2,
"bathrooms": 1,
"status": "occupied",
"current_lease": {
"resident_name": "John Smith",
"occupant_count": 2,
"start_date": "2026-04-01",
"end_date": "2027-03-31"
}
},
"changes": {
"status": {"old": "vacant", "new": "occupied"},
"current_lease": {"old": null, "new": "lease_abc"}
}
}
sync.complete¶
Sent when a full data sync between Propexo and the PMS finishes.
Triggers:
- Scheduled sync completes
- Manual sync initiated from Propexo dashboard
- MeterBase-triggered sync completes
MeterBase Action: MeterBase refreshes all unit data for properties associated with this connection. This ensures the local data is fully consistent with the PMS.
Payload:
{
"event": "sync.complete",
"timestamp": "2026-03-25T16:00:00Z",
"connection_id": "conn_abc123",
"sync_id": "sync_def456",
"stats": {
"properties_synced": 25,
"units_synced": 1200,
"leases_synced": 980,
"duration_seconds": 145,
"errors": 0
}
}
How MeterBase Processes Webhooks¶
Processing Guarantees¶
| Property | Behavior |
|---|---|
| Idempotency | MeterBase handles duplicate webhook deliveries gracefully. Processing the same event twice produces the same result. |
| Ordering | Events are processed in the order received. If ordering matters (e.g., create before update), Propexo guarantees delivery order within a connection. |
| Retry on failure | If MeterBase returns a non-2xx status code, Propexo retries with exponential backoff (1 min, 5 min, 30 min, 2 hours, 24 hours). |
| Response time | MeterBase acknowledges webhooks within 5 seconds. Long-running processing is handled asynchronously after acknowledgment. |
Payload Format¶
All webhook payloads share a common envelope:
{
"event": "event.type",
"timestamp": "ISO 8601 timestamp",
"connection_id": "Propexo connection identifier",
"resource_type": "property | unit | lease | resident",
"data": {
"...resource-specific fields..."
}
}
Common Fields¶
| Field | Type | Description |
|---|---|---|
event |
string | Event type identifier |
timestamp |
string | ISO 8601 timestamp of when the event occurred |
connection_id |
string | Propexo connection ID (maps to a MeterBase Propexo connection) |
resource_type |
string | Type of resource affected: property, unit, lease, resident |
data |
object | Resource-specific payload (varies by resource type and event) |
changes |
object | For data.update events: old and new values for changed fields |
Signature Verification¶
Every webhook request from Propexo includes a signature header that MeterBase uses to verify the request is authentic.
How It Works¶
- Propexo computes an HMAC-SHA256 signature of the raw request body using the shared webhook secret.
- The signature is included in the
X-Propexo-Signatureheader. - MeterBase recomputes the HMAC-SHA256 of the received body using its copy of the secret.
- If the signatures match, the request is authentic. If not, it is rejected with a 401 status.
Verification Example (Python)¶
import hmac
import hashlib
def verify_webhook_signature(payload_body: bytes, signature: str, secret: str) -> bool:
"""Verify that the webhook payload was sent by Propexo."""
expected = hmac.new(
secret.encode("utf-8"),
payload_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
Header Format¶
The signature value is a hex-encoded HMAC-SHA256 digest prefixed with sha256=.
Always Verify Signatures
Never process webhook payloads without verifying the signature. Without verification, an attacker could send fake events to your webhook endpoint and corrupt your data.
Webhook Logs¶
MeterBase logs all received webhook events for debugging and auditing:
Troubleshooting¶
Webhooks not arriving¶
- Verify the webhook URL in Propexo is correct and accessible from the internet
- Check that your server's firewall allows inbound HTTPS traffic
- Use the Propexo dashboard's test feature to send a test event
- For local development, verify your ngrok or tunnel is running
Signature verification failing¶
- Ensure
PROPEXO_WEBHOOK_SECRETin.envmatches the signing secret shown in the Propexo dashboard - Verify the raw request body is being used for verification (not a parsed/re-serialized version)
- Check for middleware that modifies the request body before it reaches the webhook handler
Events processed but data not updating¶
- Check the webhook logs for processing errors
- Verify the
connection_idin the event matches a registered connection in MeterBase - Ensure the affected property has been imported into MeterBase (webhooks for unlinked properties are logged but not processed)
Duplicate events¶
- Propexo may retry delivery if it does not receive a 200 response within 5 seconds
- MeterBase's idempotent processing handles this gracefully, but check if your webhook handler is timing out
- Review server logs for slow response times on the webhook endpoint