V1 API overview
The public delivery API. Render-ready payloads for one property, and the public writes a website or widget needs.
The delivery API: pre-composed, render-ready payloads for a single property, plus the public write endpoints a property website or widget needs.
Reach for V1 when you are rendering one property's public presence. Reach for the V2 management API when you are managing data across an account.
Authentication
None. Every V1 endpoint is public — these endpoints are called from property websites and public forms, where no secret can be held.
Two consequences worth being deliberate about:
- Anything on a property record is effectively public. Internal notes, staging URLs, or unpublished content that lands in a V1 payload is readable by anyone holding the property id — and property ids appear in the page source of every Resi-built site.
- Only lead submission, tour booking, demand events, source observations, and cache purge accept writes. Everything else is read-only; there is no way to modify a property through V1.
Addressing a property
Records are addressed by UUID. Every /property/{property} route takes a property UUID, and /property/{property}/unit/{unit} takes a unit UUID:
GET /api/v1/property/019dbc38-d49e-7310-95d4-711a5b7a4b40
A value that is not in UUID form is a 404, the same as an unknown id.
Slug addressing lives on the portfolio routes. Because these endpoints are unauthenticated, a slug in an unscoped path would let anyone walk every account's properties from a name read off a public website. So a portfolio site addresses its pages by slug under its own connection instead:
GET /api/v1/connection/{connection}/property/1520-gough-street
GET /api/v1/connection/{connection}/property/1520-gough-street/floor-plans
Those routes resolve the slug against the properties attached to that connection, so a slug belonging to another portfolio is a 404 rather than someone else's property rendered on your domain. They accept slugs only — pass a UUID and you get a 404.
Note that a slug is editable and an id is not: if you cache by the path segment, a renamed property serves stale content until its cache entry expires or is purged. Cache by id when that matters.
Conventions
- V1 payload casing is mixed for legacy compatibility. Follow each endpoint schema exactly; V2 payloads consistently use snake_case. Normalize at your boundary.
- Most resource responses are wrapped in a
dataenvelope. Legacy media, neighborhood, content-conditionals, website, widget, and lead-source configuration endpoints return an unwrapped object. There is no pagination. - Money is returned as a JSON number.
- Timestamps are UTC ISO-8601.
- Errors use
{"error": "..."}on V1, where V2 uses{"message": "..."}. Validation failures use{"message", "errors"}. Parse defensively. - Responses may gain fields without a version bump. Deserialize permissively — an unrecognized key must never throw.
Rate limits
| Endpoint | Limit | Keyed by |
| --- | --- | --- |
| POST /demand-events | 120/min | IP |
| POST /source-observations | 240/min | IP |
| POST /cache/clear | 30/min | Target property or portfolio id |
| POST /leads, POST /tour/* | none | — |
| All GET endpoints | none | — |
Lead and tour writes are unthrottled: set your own abuse controls in front of them.
Caching
| Endpoints | Suggested TTL |
| --- | --- |
| /units, /unit-types, /floor-plans | 5–15 minutes |
| /property, /amenities, /fees, /buildings | 1 hour |
| /galleries, /faqs, /reviews, /neighborhood, /content-groups, /panels | 6–24 hours |
| /unit/{unit}/price-matrix | 24 hours, per unit |
| /forms, /integrations | 1 hour — but re-fetch /forms after a lead submission returns 404 |
Guides
- Pricing and fees: base rent, total monthly leasing price, fee breakdowns and display settings
- Leads and tours: submitting leads and booking tours from a public form
- Instagram feeds
The V1 API reference lists every endpoint. The OpenAPI document is at /openapi/v1.json.
Last updated on