Docs
Sites API

Sites API reference

Every Sites endpoint, generated from the OpenAPI document at /openapi/sites.json.

The website delivery API. Everything a Next.js property website or centralized leasing website reads from Resi, scoped to one website. It is separate from the property-centric /api/v1, which is unchanged.

Authentication. Every request needs Authorization: Bearer <token>. A token is scoped to exactly one website (website:{id}:deliver, or website:{id}:preview for draft content) and must belong to the website's account; an account API token, whose ability is the wildcard *, is refused. Call it from the site's server; the token must never reach a browser.

Which website. Resolved from the Host header, or from X-Resi-Website when Host is meaningless (CI builds). The website never appears in the URL. The resolved website and the token's website must agree, otherwise 403.

Addressing. Properties, floor plans and units are addressed by slug and found only among the website's own enabled properties. Anything else is a 404 identical to a record that does not exist. UUIDs are not accepted in paths.

Envelope. Every success is {data, meta}. Keys are snake_case. Lists add meta.pagination. Errors are {message} and, for validation, {message, errors}.

Caching. Every GET sends an ETag and honours If-None-Match with 304. Cache-Control is private, no-cache. meta.cache.tags names what the payload was built from and meta.cache.ttl suggests how long to hold it. Resi sends a signed cache-clear webhook naming the tags that changed.

Cache-clear webhook. When data a website rendered changes, Resi POSTs to the site (default https://{primary domain}/api/resi/cache, or the URL in the website's cache_webhook_url setting; https to a public host only, and a redirect is never followed) with X-Resi-Event: cache.invalidate and a JSON body: {"event": "cache.invalidate", "website_id": "...", "tags": ["inventory:..."], "paths": [], "timestamp": 1789760000}. Only a site built to receive it is sent one: a site whose provisioning wrote it RESI_CACHE_WEBHOOK_SECRET (every site scaffolded from the current template), or one whose cache_webhook_url setting names a receiver. Sites on earlier templates are never sent it. Verify it before acting: X-Resi-Signature is sha256= followed by the HMAC-SHA256 of the raw request body, keyed with the site's RESI_CACHE_WEBHOOK_SECRET (written to the site's environment at provisioning; unique per website). Reject a body whose timestamp is more than a few minutes old, since the timestamp is inside the signed bytes precisely so a replay cannot refresh it. Then revalidate every cached response carrying one of tags. Answer 2xx; anything else is retried up to five times with backoff. Changes within about fifteen seconds are sent as one webhook. A change Resi does not detect is picked up when meta.cache.ttl runs out.

Tags. site, paths, property:{id}, inventory:{property_id}, entries:{type}, integrations:{property_id}, lead-sources:{property_id}, forms:{property_id}.

Filtering. List endpoints accept documented filters, sort (- prefix for descending, comma-separated) and page / per_page. A value that cannot be applied is a 422, never an ignored filter.

Compatibility. Additive changes ship continuously: new endpoints, new optional parameters, new keys. Removing or retyping a key is a breaking change and needs an ADR.

Endpoints

Bootstrap

What a build reads first.

EndpointSummary
GET /api/sites/v1/siteSite manifest
GET /api/sites/v1/pathsRenderable paths
GET /api/sites/v1/resolveResolve a path
GET /api/sites/v1/groupsGroup sets

Content

Content entries.

EndpointSummary
GET /api/sites/v1/content-typesContent types
GET /api/sites/v1/entries/{type}List entries of a content type
GET /api/sites/v1/entries/{type}/{slug}One entry

Properties

The website's properties.

EndpointSummary
GET /api/sites/v1/propertiesList properties
GET /api/sites/v1/properties/{property}One property
GET /api/sites/v1/properties/{property}/neighborhoodNeighborhood
GET /api/sites/v1/properties/{property}/reviewsReviews
GET /api/sites/v1/properties/{property}/instagramInstagram feed

Inventory

Floor plans, units and availability across the website's properties.

EndpointSummary
GET /api/sites/v1/floor-plansList floor plans
GET /api/sites/v1/floor-plans/{floorPlan}One floor plan
GET /api/sites/v1/unitsList units
GET /api/sites/v1/units/{unit}One unit
GET /api/sites/v1/units/{unit}/price-matrixUnit price matrix
GET /api/sites/v1/availabilityAvailability feed
GET /api/sites/v1/unit-typesUnit types
GET /api/sites/v1/facetsSearch facets

Attribution

Lead sources and the rules that pick one for a visit.

EndpointSummary
GET /api/sites/v1/lead-sourcesLead sources for every property
GET /api/sites/v1/properties/{property}/lead-sourcesLead sources for one property

Integrations

The third-party tools a property's pages embed.

EndpointSummary
GET /api/sites/v1/integrationsIntegrations for every property
GET /api/sites/v1/properties/{property}/integrationsIntegrations for one property

Conversion

Forms, leads, tours and analytics events.

EndpointSummary
GET /api/sites/v1/formsList forms
GET /api/sites/v1/forms/{form}One form
POST /api/sites/v1/forms/{form}/submissionsSubmit a form
POST /api/sites/v1/tours/availabilityTour availability
POST /api/sites/v1/tours/reservationsReserve a tour
POST /api/sites/v1/eventsRecord an analytics event
POST /api/sites/v1/source-observationsRecord a source observation

Last updated on