Sites API overview
The website delivery API — everything a property website or centralized leasing site reads from Resi, scoped to one website.
The Sites API serves one job: giving a website everything it renders. A token belongs to one website, and every response is limited to that website's own properties, floor plans, units, content, forms and integrations. A property website sees its one property; a centralized leasing site sees its whole portfolio through the same endpoints.
Base URL: https://v2.getresi.com/api/sites/v1
The machine-readable contract is the OpenAPI 3 document at /openapi/sites.json. Every response object in it lists all of its keys as required and allows no others, and Resi's test suite validates real responses against it, so generated types are safe to rely on.
How it differs from V1 and V2
| Sites API | V1 | V2 | |
|---|---|---|---|
| Base path | /api/sites/v1 | /api/v1 | /api/v2 |
| Scoped to | One website | One property (by UUID) | One account |
| Auth | Bearer token, one per website | None | Bearer token, per account |
| Called from | The site's server | A browser | An integration's server |
| Addressing | Slugs | UUIDs | UUIDs |
| Built for | Next.js property and centralized leasing sites | WordPress sites and widgets | Managing data |
Server-side only. The website token reads data that is not public, such as lead routing rules, and it can create leads. Call the API from route handlers, server components or build steps. It must never be shipped to a browser.
Your first request
A site scaffolded by Resi has four environment variables written at provisioning:
| Variable | Holds |
|---|---|
RESI_DELIVERY_API_URL | https://v2.getresi.com/api/sites/v1 |
RESI_DELIVERY_TOKEN | The website's bearer token |
RESI_WEBSITE_ID | The website's id, for the X-Resi-Website header |
RESI_CACHE_WEBHOOK_SECRET | The key that verifies the cache-clear webhook |
curl "$RESI_DELIVERY_API_URL/site" \
-H "Authorization: Bearer $RESI_DELIVERY_TOKEN" \
-H "X-Resi-Website: $RESI_WEBSITE_ID" \
-H "Accept: application/json"{
"data": {
"website": { "id": "01a0b9f5-b5bc-711c-9d7b-6c67aec47953", "name": "Example Apartments", "type": "portfolio", "platform": "nextjs", "status": "live", "locale": "en_US", "environment": "production" },
"domains": [{ "hostname": "www.example-apartments.com", "is_primary": true, "managed_by": "vercel" }],
"tracking": { "gtm_id": "GTM-XXXXXXX" },
"redirects": [{ "from": "/old", "to": "/new", "status": 301 }],
"routing": {
"patterns": {
"property": "/property/{slug}",
"property_archive": "/properties",
"floor_plan": "/floor-plan/{slug}",
"floor_plan_archive": "/floor-plans",
"unit": "/unit/{slug}",
"unit_archive": "/units"
},
"uniform": true
},
"properties": [{ "id": "01000000-0000-4000-8000-000000000002", "slug": "contract-property", "name": "Contract Property", "path": "/property/contract-property", "...": "..." }],
"theme": { "tokens": null }
},
"meta": { "cache": { "tags": ["inventory:0100…0002", "property:0100…0002", "site"], "ttl": 3600 } }
}A typical build
GET /site— domains, tracking, redirects, URL patterns and a card per property.GET /paths— every path to generate statically, and the sitemap.GET /content-types— the content types the site renders and their fields.- Per page:
GET /properties/{slug}?include=…,GET /floor-plans,GET /units,GET /entries/{type}/{slug}. - Per property:
GET /integrations,GET /lead-sources,GET /forms. - At request time:
GET /resolve?path=…for paths not generated,GET /availabilityfor what moves, and the POST endpoints for leads, tours and analytics. - Hold responses by
meta.cache.tagsand drop them when the cache-clear webhook names a tag.
Guides
Last updated on
List Instagram posts GET
Synced posts from the property’s enabled Instagram connection. Returns an empty collection when none is configured. Scoped to the portfolio: `{property}` is a slug resolved against the properties attached to `{connection}`, so a slug outside this portfolio is a `404` rather than another site's property.
Authentication & website scoping
One bearer token per website, how Resi decides which website a request is for, and why everything else is a 404.