Skip to main content

Move-outs API

A move-out is the record Rhino opens when a resident vacates a unit. You open one through this API when a resident moves out, and Rhino tracks refund/consent/statement steps against it as they ship.

This is an early release. Today the API covers opening a move-out and reading it back; consent, statement submission, and payout are not live yet and are not documented here until they are. See move_out.initiated for the corresponding webhook.

See Authentication & Environments for base URLs and request signing.

Open a move-out

POST /partners/{owner_slug}/move_outs
Content-Type: application/json

Unlike the prospect and property endpoints, the body is not wrapped in a named key — send the move-out's own fields at the top level:

{
"external_id": "your-move-out-123",
"move_out_date": "2026-09-30",
"property": {
"external_id": "your-property-1",
"address_line_one": "123 Main St",
"address_city": "Chicago",
"address_state": "IL",
"address_zip": "60601"
},
"unit": {
"external_id": "your-unit-1",
"name": "4B"
},
"residents": [
{
"role": "primary",
"name": "Jordan Rivera",
"email": "renter@example.com",
"external_id": "your-resident-1"
}
]
}

external_id is the idempotency key, unique per property owner. Re-POSTing the same external_id returns the existing move-out unchanged — it does not update it and does not create a duplicate. refund_amount_cents is omitted here deliberately: send it only once the refund amount is final, since its presence is what tells Rhino the statement is done.

Both a create and a re-post return 200-shaped bodies with a status_code field: 201 when the move-out was created, 200 when an existing one was returned. Read status_code rather than the HTTP status if you need to tell them apart — the HTTP status matches it in both cases.

Fetch a move-out

GET /partners/{owner_slug}/move_outs/{id}

Returns the same move-out object. Webhooks are the primary channel for status changes; use this to reconcile if you are not subscribed, or to poll after creation.

{id} is the numeric move_out_id from the create response — see the note on IDs below.

Request fields

FieldNotes
external_idYour identifier for the move-out. Required, unique per property owner.
move_out_dateYYYY-MM-DD. Required.
propertyObject with address_line_one, address_city, address_state, address_zip (all required) and an optional external_id. Stored as sent — see the note below.
unitOptional object with external_id and name.
residentsRequired, at least one. Each entry needs role (primary or co_resident) and name; email and external_id are optional.
refund_amount_centsOptional. Integer cents. Send only when the refund amount is final.

The property address is stored exactly as sent, not derived from any Rhino property record. Most departing residents predate any integration Rhino has with your system, so a move-out stands on its own — nothing here requires the property, unit, or residents to already exist in Rhino.

Response

{
"status_code": 201,
"move_out": {
"move_out_id": 1042,
"external_id": "your-move-out-123",
"status": "initiated",
"move_out_date": "2026-09-30",
"refund_amount_cents": null,
"property": {
"external_id": "your-property-1",
"address_line_one": "123 Main St",
"address_city": "Chicago",
"address_state": "IL",
"address_zip": "60601"
},
"unit": {
"external_id": "your-unit-1",
"name": "4B"
},
"residents": [
{
"role": "primary",
"name": "Jordan Rivera",
"email": "renter@example.com",
"external_id": "your-resident-1"
}
]
}
}

Response fields

FieldDescription
move_out_idRhino's numeric ID for the move-out
statusinitiated today. More values arrive as later milestones (consent, statement, payout) ship.
refund_amount_centsnull until the statement is final

Note on IDs: unlike prospects (tpp_…) and policies (policy_…), a move-out's ID is a plain integer, not a prefixed string. The same move_out_id appears in the create/fetch response and in the move_out.initiated webhook payload.

Errors

{
"status_code": 422,
"error": "Move-out invalid.",
"move_out": {
"external_id": "can't be blank",
"residents": "must include at least one resident"
}
}
StatusMeaning
401Request signature missing, malformed, or older than five minutes
403Caller not granted access to this property owner
404Unknown owner_slug, or the move-out does not exist — including one that exists under a different owner
422Validation failure — see the move_out object for field-level detail

Next steps