Managing Guests
A guest in Minut represents a stay at one of your homes: a name, contact details, and a check-in / check-out window. Guests are how Minut knows when a property is occupied, who to send pre-arrival messages to, and which stay any noise or occupancy event belongs to.
If you already have a native PMS integration (Guesty, Hostaway, Bookingsync, etc.), guests are created automatically for you and you don't need this API. The endpoints below are for the case where you want to push reservations into Minut yourself — for example, from a PMS we don't yet have a connector for, or from a custom internal system.
Guests created through this API end up in the same place as guests created via a PMS integration or a CSV import. The only thing that changes is how Minut got the data.
This page is an orientation, not a field-level reference. Request and response schemas, query parameters and exhaustive error codes live in the OpenAPI specification — the prose here covers how the pieces fit together and the behaviour that isn't obvious from the spec.
Prerequisites
You'll need an OAuth client and an access token — see Authentication for Users. The token response includes an expires_in field — schedule a refresh against it rather than waiting for 401s. Every request below assumes a valid Authorization: Bearer ACCESS_TOKEN header.
Find your home IDs
Every guest belongs to a home, so you need the Minut home_id before you can create a guest. List the homes your token has access to:
- Curl
- Typescript
curl --request GET 'https://api.minut.com/v8/homes?limit=30' \
--header 'Authorization: Bearer ACCESS_TOKEN'
import axios from 'axios';
const response = await axios.get(
'https://api.minut.com/v8/homes',
{
params: { limit: 30 },
headers: { Authorization: `Bearer ${accessToken}` },
},
)
const homes = response.data.homes
In practice, do this lookup once per home and store the mapping your_property_id → minut_home_id on your side, rather than calling /homes on every reservation push.
Create a guest
To register a reservation in Minut, POST to /homes/{home_id}/guests:
- Curl
- Typescript
curl --request POST 'https://api.minut.com/v8/homes/HOME_ID/guests' \
--header 'Authorization: Bearer ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"name": "Jane Doe",
"phone_number": "+14155234567",
"email": "jane@example.com",
"checkin_time": "2026-06-01T15:00:00Z",
"checkout_time": "2026-06-05T11:00:00Z"
}'
import axios from 'axios';
const response = await axios.post(
`https://api.minut.com/v8/homes/${homeId}/guests`,
{
name: 'Jane Doe',
phone_number: '+14155234567',
email: 'jane@example.com',
checkin_time: '2026-06-01T15:00:00Z',
checkout_time: '2026-06-05T11:00:00Z',
},
{
headers: { Authorization: `Bearer ${accessToken}` },
},
)
const guest = response.data
A few behaviours that aren't obvious from the schema:
- Contact details are not strictly required. If both
phone_numberandemailare omitted, the request still succeeds — the resulting guest carries avalidation_errorsentry (e.g.missing_phone_number_and_email). Phone numbers that fail validation come back withinvalid_phone_numberorunreachable_country. Treatvalidation_errorsas informational and inspect it on every guest you create. - The response contains more fields than you'll send. Expect read-only fields like
source,readonly,validation_errors,access_code,guest_page, and (once messaging starts) aconversationobject. Ignore anything you don't need — new fields may be added over time. - Hold on to the returned
guest_id— you'll need it to update or delete the guest later, and there is no server-side deduplication (see Idempotency below).
List and fetch guests
GET /homes/{home_id}/guests returns the guests for a home with pagination and filtering. GET /homes/{home_id}/guests/{guest_id} returns one.
- Curl
- Typescript
curl --request GET 'https://api.minut.com/v8/homes/HOME_ID/guests?limit=50&offset=0' \
--header 'Authorization: Bearer ACCESS_TOKEN'
import axios from 'axios';
const response = await axios.get(
`https://api.minut.com/v8/homes/${homeId}/guests`,
{
params: { limit: 50, offset: 0 },
headers: { Authorization: `Bearer ${accessToken}` },
},
)
const { guests, paging } = response.data
Update a guest
Two ways to change an existing guest:
PATCH— partial update. Send only the fields you want to change. This is what you almost always want.PUT— full replace. You must send the complete representation; any field you omit is treated as cleared.
- Curl
- Typescript
curl --request PATCH 'https://api.minut.com/v8/homes/HOME_ID/guests/GUEST_ID' \
--header 'Authorization: Bearer ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"checkout_time": "2026-06-06T11:00:00Z"
}'
import axios from 'axios';
const response = await axios.patch(
`https://api.minut.com/v8/homes/${homeId}/guests/${guestId}`,
{
checkout_time: '2026-06-06T11:00:00Z',
},
{
headers: { Authorization: `Bearer ${accessToken}` },
},
)
const guest = response.data
Guests that originated from a native PMS integration are marked read-only. On those, only conversation.status can be changed via PATCH; PUT, DELETE, and other field updates return 400 Bad Request with error_key: readonly_guest. Guests you create via this API are not read-only.
Delete a guest
For cancellations, DELETE /homes/{home_id}/guests/{guest_id}.
Idempotency and deduplication
The create endpoint does not deduplicate. If you POST the same reservation twice you will get two guests in Minut. Plan for this on your side:
- When you push a new reservation, store the returned
guest_idagainst your own reservation ID. - When the reservation changes, look up the stored
guest_idand callPATCH(orPUT) — don'tPOSTagain. - If you lose your local mapping, list guests for the home and match on check-in time rather than re-creating.
Rate limits and errors
See API Information → Rate Limits for the global limits and 429 handling.
Branch on the HTTP status code first — it's present on every response, so it's the signal you can always rely on. Most errors also include a more specific error_key (for example invalid_guest, readonly_guest, or insufficient_access) which is more stable than the human-readable message and worth branching on where you need finer detail. Not every response carries one — 401 and 404s don't — so use error_key to refine the status code, not replace it. The OpenAPI spec enumerates the keys each endpoint can return.