The strategy is replacement, not integration. We are moving clients away from ILS / PMS lead-management intake. The client's website posts leads straight into PropFlow, and Clara owns the lead from the first second — reply in seconds, guest card created, follow-up cadence armed. The PMS stays the system of record; PropFlow becomes the system of work, starting at the front door.
One endpoint, multi-tenant by construction. Server-to-server only — the visitor's browser never talks to PropFlow; the client site's own server (or their website vendor's platform) is the caller.
POST https://propflowai.co/api/leads/website
Header x-propflow-lead-key: <per-client key>
{
"propertyId": "1773625953462", // required, must be on the key's allowlist
"name": "Raul Perez Foster", // required
"email": "prospect@example.com", // required, validated
"phone": "(951) 404-9086", // optional
"bedrooms": "studio", // optional: studio | 1br | 2br | free text
"movein": "2026-09-01", // optional, YYYY-MM-DD
"message": "Studio or 1bd Thanks!", // optional
"locale": "en" // optional: en | es
}
| Response | Meaning | Caller's move |
|---|---|---|
202 | Accepted — the regular lead flow is running | Show the visitor success |
400 / 401 / 403 | Bad payload / unknown key / property not on this key | Fix the integration; do not retry blindly |
429 | Per-property rate limit | Back off |
5xx | PropFlow-side failure | Fall back to the email path so no lead is ever lost |
source: website_api).Decision (Fede/Gera, Aug 25): only the short-term fix is built now; the API switch stays on paper. The short-term fix, both halves live in production as of Aug 25:
website@propflowai.co instead of Clara's own address — the "our mail vs a real lead" ambiguity is removed at its source. Subject, prospect reply-to, and body format unchanged (lead parsing keys on the body shape, verified).The API switch for Camellia is specced and parked: camellia-site PR #18 ([HOLD], unmerged) holds the form-side change — inert by design until the endpoint exists and a key is configured. Do not merge it before both.
What we hand a client (or their website vendor) is deliberately small:
Who makes the change depends on who owns the form:
| Site type | Example | The change |
|---|---|---|
| Custom / agency-built | Camellia | Their developer swaps the email send for the POST — an hour of work |
| Vendor template | Yale 25 Station (Apartments247 → RentCafe feed) | The vendor points the form's lead destination at our endpoint instead of the ILS/PMS feed — one vendor integration covers every property on that platform |
| PMS-native site | RentCafe-hosted sites | Replace the site or intercept its lead notifications into the connected mailbox during transition; these convert last |
Transition note: listing-site (ILS) leads keep arriving by email into the connected mailbox until the client turns those subscriptions down — nothing breaks mid-migration; the mailbox lane and the API lane run side by side, and both end in the same flow.
| # | Repo | Item | Status |
|---|---|---|---|
| 0 | both | Short-term fix: provenance stamp (#6251) + neutral form sender (camellia-site #19) | Shipped Aug 25 |
| 1 | propflowai | POST /api/leads/website: key auth → validation → synthesize inbound payload → existing queue → ingestion-log row (website_api) + rate limit + failure alert | Spec only |
| 2 | propflowai | Tests: key rejection, property allowlist, payload validation, same-pipeline-outcome regression (reuse the Raul-shape fixture), publish-failure alert | Spec only |
| 3 | camellia-site | Form handler: PropFlow POST primary, SendGrid email fallback on error, honeypot/validation kept | Parked — PR #18 [HOLD], inert until 1 exists |
| 4 | both | Prod verification: real form submission with a test identity → prospect + conversation + Clara reply + website_api log row; honeypot submission → dropped, Sentry event, nothing in PropFlow | With the build |
| 5 | ops | Key issuance + env config on both Vercel projects (explicit go required for prod env writes) | With the build |
| 6 | propflowai | After a quiet month with the fallback unused: retire the email-relay special cases for the form's shape | Later |
npm run build) before pushing; use a PR for the record.Context: Aug 25 incident doc (the lead blackout + reasoning leak) · PR #6251 (provenance stamp, merged) · PR #6253 (tour-confirmation copy, merged) · current form handler: camellia-site src/app/api/contact/route.ts.