Reference
Home setup
Set a home's checklist, Matterport tour and baseline photos.
Setting up a home
Once a property is in the roster you can prepare it for inspections: give it the checklist the cleaner works through, a Matterport tour, and baseline photos of the home in good condition. All three are optional, and an inspection works without any of them; each one makes the report sharper.
Every call here addresses a home by your property_id, the one you sent in
the roster, and takes workspace_id as a query parameter. Any roster state may
be set up, inactive and unconfirmed included, so you can prepare a home
before it goes live. An id that is not in that workspace's roster answers
404 property_not_found, and so does an id that belongs to a different
workspace. The id is matched literally and must survive as one path segment, so
percent-encode anything reserved.
Request bodies on these endpoints are limited to 376,224 bytes; a larger body
answers 413 payload_too_large before it is read. That is a guard against a
mistaken bulk upload, separate from the field limits below. It sits well above
any realistic body at those limits, and both rules apply.
Progress for every home shows in the setup block on
GET /v1/properties:
"setup": {
"checklist": { "items": 12 },
"matterport": { "state": "imported", "url": "https://my.matterport.com/show/?m=SxQL3iGyoDo" },
"baseline_photos": { "count": 18, "state": "imported" }
}
| Field | Meaning |
|---|---|
checklist.items |
How many items the home's own housekeeping checklist has (the list a cleaner is served on a turnover). 0 means it has none of its own. The inspection and maintenance lists are not counted here; read them with GET .../checklist?type=. |
matterport.state |
none, importing, imported or failed, for the tour the home currently names. url is omitted when no tour is set. |
baseline_photos.count |
Every photo in the home's baseline, whatever added it: your imports, and photos the home's managers or we added (uploads, a Google Drive folder, their Airbnb listing, Breezeway listing photos). |
baseline_photos.state |
importing while a photo import is running, yours or one the home's managers started. Otherwise imported when the home has any baseline photos, failed when it has none and its most recent import in the last 30 days failed, and none otherwise. Read the import itself for which photos were refused. |
PUT/v1/properties/{property_id}/checklist?workspace_id=...#
Replace the home's checklist with the list you send. The cleaner sees the items in your order. It is a full replace, not a merge, and it is idempotent: sending the same list twice leaves the same checklist. It is safe after the home has been recorded; items a cleaner already checked off stay on the reports that recorded them.
| Field | Required | Notes |
|---|---|---|
items |
yes | Array of 1 to 50 items. To remove the checklist, use DELETE; an empty array is refused. |
items[].name |
yes | The step as the cleaner reads it on their phone, one step at a time. 1 to 120 characters; under 55 reads best. Name the area, then the visible results: Kitchen: counters clear, sink empty, floor swept. A dash used as punctuation (an em dash, or an en dash with a space beside it) is refused; use a colon. |
items[].notes |
no | A short label shown under the step on one truncated line, such as the floor or room. Not a place for instructions. Up to 500 characters. |
Unknown fields, at the top level or on an item, are rejected with
400 invalid_request, and detail names the field and the item index.
A home has three checklists, and ?type= picks which one you are writing.
The values are housekeeping (the default when you omit it), inspection and
maintenance. Each is a separate list: writing one never disturbs the other
two, and clearing one leaves the others alone. Anything outside those three is
400 invalid_request with detail.parameter set to type.
Housekeeping is the list a cleaner is served during a turnover, so it is the
one to use unless you have a reason not to. The response echoes type back
even when you left it out, so a stored response always says which list it
describes.
Every item comes back with an id, which is ours and is how per-item
results are reported (see What we send back to you). One thing to know about
it: a replace retires the old items and creates new ones, so an id is stable
between writes and not across them. That is deliberate, because a result should
point at the version of the item that was actually checked. Read the ids back
after each PUT rather than caching them across an edit.
curl -sS -X PUT "https://api.rapideyeinspections.com/v1/properties/unit_42/checklist?workspace_id=ws_123" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "name": "Bedrooms: beds made, linens fresh, floors clear", "notes": "Upstairs" },
{ "name": "Hot tub: cover on and latched" }
]
}'
{
"workspace_id": "ws_123",
"property_id": "unit_42",
"type": "housekeeping",
"items": [
{ "id": "c1f0a2e4-...", "name": "Bedrooms: beds made, linens fresh, floors clear", "notes": "Upstairs" },
{ "id": "9b73d5a1-...", "name": "Hot tub: cover on and latched" }
],
"updated_at": "2026-09-19T14:02:11Z"
}
GET/v1/properties/{property_id}/checklist?workspace_id=...#
The home's own checklist, in order. items is an empty array when the home
has none of its own, and updated_at is then omitted; a company-wide checklist
set up with us may still apply to that home.
?type= reads one of the three lists, same values and same default as the
PUT. Read the item ids back from here after any edit: they are what
per-item results are keyed on, and a replace issues new ones.
curl -sS "https://api.rapideyeinspections.com/v1/properties/unit_42/checklist?workspace_id=ws_123&type=maintenance" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME"
{
"workspace_id": "ws_123",
"property_id": "unit_42",
"type": "maintenance",
"items": [
{ "id": "c1f0a2e4-...", "name": "Bedrooms: beds made, linens fresh, floors clear", "notes": "Upstairs" }
],
"updated_at": "2026-09-19T14:02:11Z"
}
DELETE/v1/properties/{property_id}/checklist?workspace_id=...#
Remove one of the home's own checklists. Idempotent: removing a checklist that
is not there is a 200. If the customer has a company-wide checklist of that
type on our side, the home goes back to using it. ?type= picks which list to
clear and leaves the other two alone.
curl -sS -X DELETE "https://api.rapideyeinspections.com/v1/properties/unit_42/checklist?workspace_id=ws_123" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME"
{ "workspace_id": "ws_123", "property_id": "unit_42", "type": "housekeeping", "items": [] }
PUT/v1/properties/{property_id}/matterport?workspace_id=...#
Set the home's Matterport tour and import it as baseline imagery. Answers 202
with state: "importing"; watch setup.matterport.state on
GET /v1/properties for imported or failed.
| Field | Required | Notes |
|---|---|---|
url |
yes | A https://my.matterport.com/show/?m=<model id> share link (other query parameters are fine) or a https://discover.matterport.com/space/<model id> link. We store it as https://my.matterport.com/show/?m=<model id>. |
Sending a tour again is safe. The same tour that is already imported answers
200 with state: "imported" and imports nothing; the same tour that is still
importing answers 202 with the import already running. A different tour while
one is importing is 409 matterport_import_in_progress, and detail.importing names
the tour that is running; wait for the first to
finish. A tour whose import failed is imported again. A different tour while one
is already imported replaces it: the home keeps using the imported tour until
the new one finishes importing, and if the new import fails the old tour stays
in use and state reads failed for the tour you sent.
curl -sS -X PUT "https://api.rapideyeinspections.com/v1/properties/unit_42/matterport?workspace_id=ws_123" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME" \
-H "Content-Type: application/json" \
-d '{ "url": "https://my.matterport.com/show/?m=SxQL3iGyoDo&play=1" }'
{
"workspace_id": "ws_123",
"property_id": "unit_42",
"matterport": { "url": "https://my.matterport.com/show/?m=SxQL3iGyoDo", "state": "importing" }
}
DELETE/v1/properties/{property_id}/matterport?workspace_id=...#
Remove the home's tour. Idempotent. Its imported imagery is deleted and stops being used from the next inspection, and an import that is running is stopped. Nothing else in the home's baseline (photos, the baseline video) is affected.
curl -sS -X DELETE "https://api.rapideyeinspections.com/v1/properties/unit_42/matterport?workspace_id=ws_123" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME"
{ "workspace_id": "ws_123", "property_id": "unit_42", "matterport": { "state": "none" } }
POST/v1/properties/{property_id}/baseline-photos?workspace_id=...#
Import baseline photos of the home, in good condition, from URLs. Answers 202
with an import_id; the photos are fetched in the background. Photos add to the
home's baseline, they never replace it, and sending a photo we already hold
adds nothing, whatever URL it arrives from. One import runs per home at a
time: a second batch while one is importing is
409 baseline_import_in_progress. Baseline imports (photos and tours, from
every workspace) also queue behind each other on our side, so at a busy moment
an import can stay importing for some minutes before its first photo is
fetched. Poll the import; do not time it out and send it again.
| Field | Required | Notes |
|---|---|---|
photos |
yes | Array of 1 to 25 objects. A repeated photo counts toward the 25 and is fetched, is stored once, and is reported in the import's duplicates count. |
photos[].url |
yes | An https URL on the default port, up to 2,048 characters, with no credentials in it. |
What we fetch, and what we refuse per photo rather than for the whole batch:
- Public hosts only. A host that resolves to a private, loopback, link-local or otherwise non-public address is refused, and so is a redirect to one. We follow at most three redirects, each checked the same way.
- JPEG, PNG or WebP, up to 15 MB. The
Content-Typemust say so and the bytes must match it. - 20 seconds per photo. A slower server fails that photo.
- Nothing of yours or ours is sent. No cookies and no authorization header, so the URL has to be fetchable on its own; a signed URL that lives for a few minutes is fine.
curl -sS -X POST "https://api.rapideyeinspections.com/v1/properties/unit_42/baseline-photos?workspace_id=ws_123" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME" \
-H "Content-Type: application/json" \
-d '{
"photos": [
{ "url": "https://photos.example.com/unit_42/living-room.jpg" },
{ "url": "https://photos.example.com/unit_42/kitchen.jpg" }
]
}'
{
"workspace_id": "ws_123",
"property_id": "unit_42",
"import_id": "5d0c7a4e-3b1f-4f7e-9c2a-8e6b1d4f0a37",
"state": "importing",
"accepted": 2
}
GET/v1/properties/{property_id}/baseline-photos/imports/{import_id}?workspace_id=...#
One photo import: its state (importing, imported or failed), how many
photos were stored, how many were duplicates (a photo the home already
holds, from this request or from anywhere else, or one removed from the home
while the import ran), and every photo we refused, with its position in your
request, its URL and a reason. stored, duplicates and the refused photos
add up to the number you sent. The import is failed when every photo was
refused, or when it failed before it could report on any photo. The first
carries no error: every refused photo is already in failed with its own
reason. The second carries a short error, and sending the same photos again
is safe.
reason |
Meaning |
|---|---|
invalid_url |
The URL, or a redirect it sent us to, is not one we fetch. |
dns_failed |
The host did not resolve. |
private_address |
The host resolves to a non-public address. |
connect_failed |
We could not connect or the connection broke. |
too_many_redirects |
More than three redirects. |
http_status |
The server answered something other than 200. |
unsupported_content_type |
Not JPEG, PNG or WebP. |
content_mismatch |
The bytes are not a usable image of the type the server declared: another type, truncated or corrupt, or over 100 megapixels. |
too_large |
Over 15 MB. |
timeout |
The photo took longer than 20 seconds. |
upload_failed |
We fetched it and could not store it. Sending it again is safe. |
fetch_failed |
Something unexpected went wrong on our side with this photo. Sending it again is safe. |
An import_id from another home or workspace answers 404 not_found,
identical to one that does not exist.
curl -sS "https://api.rapideyeinspections.com/v1/properties/unit_42/baseline-photos/imports/5d0c7a4e-3b1f-4f7e-9c2a-8e6b1d4f0a37?workspace_id=ws_123" \
-H "Authorization: Bearer rapideye_pk_REPLACE_ME"
{
"workspace_id": "ws_123",
"property_id": "unit_42",
"import_id": "5d0c7a4e-3b1f-4f7e-9c2a-8e6b1d4f0a37",
"state": "imported",
"stored": 1,
"duplicates": 0,
"failed": [
{ "index": 1, "url": "https://photos.example.com/unit_42/kitchen.jpg", "reason": "http_status" }
]
}