Skip to content

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.

sequenceDiagram participant PMS as Property Management System participant P as Propexo participant G as MeterBase PMS->>P: Data change detected P->>P: Normalize event payload P->>G: POST /api/webhooks/propexo G->>G: Verify signature G->>G: Process event G-->>P: 200 OK

Setting Up Webhook Endpoints

Step 1: Configure the Webhook URL in Propexo

In the Propexo dashboard:

  1. Navigate to Settings > Webhooks
  2. Click Add Endpoint
  3. Enter the MeterBase webhook URL: https://your-meterbase-domain.com/api/webhooks/propexo
  4. Select the events you want to receive (or select all)
  5. Copy the Signing Secret provided by Propexo

Step 2: Configure MeterBase

Add the signing secret to your .env file:

PROPEXO_WEBHOOK_SECRET=whsec_your_signing_secret_here

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

flowchart TD A["Receive POST /api/webhooks/propexo"] --> B{"Verify\nSignature"} B -->|Invalid| C["Return 401 Unauthorized"] B -->|Valid| D{"Parse Event\nType"} D -->|data.new| E["Create or flag\nnew record"] D -->|data.update| F["Update local\nrecord"] D -->|sync.complete| G["Trigger full\ndata refresh"] D -->|Unknown| H["Log and ignore"] E --> I["Return 200 OK"] F --> I G --> I H --> I

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

  1. Propexo computes an HMAC-SHA256 signature of the raw request body using the shared webhook secret.
  2. The signature is included in the X-Propexo-Signature header.
  3. MeterBase recomputes the HMAC-SHA256 of the received body using its copy of the secret.
  4. 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

X-Propexo-Signature: sha256=5d3b...a1f2

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:

Navigate to Integrations > Propexo > Webhook Logs to view:

  • Timestamp of each received event
  • Event type and resource type
  • Processing status (success, failed, ignored)
  • Full payload (click to expand)
curl "https://api.meterbase.io/api/webhooks/logs?limit=50" \
  -H "Authorization: Bearer $TOKEN"

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_SECRET in .env matches 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_id in 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