Channels

Inbound webhook

Push customer messages and leads from your website forms or a custom WhatsApp gateway into PropDrop with a signed POST, and the AI agent answers them.

The inbound webhook is the way in: any system of yours can send PropDrop a customer message or a new lead. For example:

  • A "Request details" form on your website.
  • Your own WhatsApp or SMS gateway (not Meta).
  • A tool like n8n collecting leads from ads or from portal lead exports.

The message lands in the inbox like any channel, the customer is saved in your contacts, and the AI agent replies. The agent's reply goes out through the outbound webhook, so your gateway delivers it to the customer.

PropDrop doesn't pull from property portals

PropDrop doesn't connect directly to Property Finder, Bayut or Aqarmap. If you get leads there, a system of yours (like n8n) has to send them to this URL in the format below.

This page is for whoever builds the integration. Available on all plans. Who can set it up: owner and managers.

Setup

Copy the Inbound URL

In Settings → Channels & integrations, under Advanced, open Receive messages and leads (inbound webhook) and copy the URL. It looks like:

https://…/api/webhooks/inbound/<your company ID>

Generate the signing secret

Click Generate new secret and copy it (it starts with pd_in_). It's shown only once. It's a different secret from the outbound one. Generating a new one stops the old one immediately.

Sign every request

Every request must carry:

X-PropDrop-Signature: sha256=<hex HMAC-SHA256(secret, raw body)>

That's an HMAC-SHA256 of the exact raw body with your secret. Requests without a valid signature are rejected.

Request format

POST https://…/api/webhooks/inbound/<your company ID>
Content-Type: application/json
X-PropDrop-Signature: sha256=…
{
  "channel": "whatsapp",
  "source": "portal",
  "external_id": "lead-48213",
  "sent_at": "2026-10-09T12:00:00+02:00",
  "text": "I'm interested in the apartment in New Cairo, what's the price?",
  "contact": { "name": "Ahmed Ali", "phone": "+201001234567" }
}
FieldRequired?Details
contact.phone or contact.instagramOne of themPhone numbers are normalised for your company's country (e.g. 01001234567 becomes +201001234567)
contact.nameNoUp to 120 characters
contact.emailNoA valid email
textYes (or attachments)Up to 4,000 characters
channelNowhatsapp (default), sms, email, web, instagram, messenger, telegram
sourceNoWhere a new contact came from. portal records them as a Property portal lead. Also web, phone, referral, manual, import and the channel names
external_idNo (but recommended)Your ID for this message, up to 200 characters. A repeat with the same ID is ignored, so retries are safe
sent_atNoWhen it was sent, ISO 8601 with a time zone
attachmentsNoUp to 10 (below)

Attachments

"attachments": [
  { "type": "image", "url": "https://example.com/plan.jpg", "mime": "image/jpeg", "name": "plan.jpg" },
  { "type": "location", "lat": 30.0131, "lng": 31.4914, "label": "Fifth Settlement" }
]

type is image, audio, video, document or location. URLs must start with https://; we copy the file and keep it in the conversation.

Responses

StatusMeaning
202Accepted: {"ok": true, "event_id": "…"}. The message is processed next and the agent replies
400invalid_json, or invalid with issues naming the bad fields
401invalid_signature: missing or wrong signature
403agency_inactive: the company account is suspended
404not_found: wrong URL
413too_large: the body is over 256 KB

If a request was accepted (202) and processing then fails, we retry it automatically a bit later.

How the customer is matched

  • We look the customer up by phone (or Instagram handle). If they exist, the message is added to them; if not, a new contact is created with the source you sent.
  • If they already have an open conversation on the same channel, the message joins it.

If you also connected WhatsApp in PropDrop

If the same customer has an open WhatsApp conversation on your number connected in PropDrop, and your request uses "channel": "whatsapp", the message joins that conversation and the reply goes out from your connected number, not your gateway. If your gateway is a different number, use "channel": "sms" or another channel so the conversations don't mix.

Quick test

BODY='{"text":"I want an apartment in New Cairo","contact":{"name":"Test","phone":"+201001234567"},"external_id":"test-1"}'
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"
curl -X POST "$INBOUND_URL" -H "Content-Type: application/json" -H "X-PropDrop-Signature: $SIG" -d "$BODY"

If you get 202, open Conversations: you'll find the chat and the agent's reply, and the reply goes to your outbound webhook if it's set.

On this page