Partner Onboarding API Overview
The Partner Onboarding API lets you provision a property owner and maintain its property and unit roster programmatically, without manual setup by Rhino for each owner. Use it when you onboard property management companies at a volume that manual, per owner setup cannot support.
It provides four write endpoints and extends the Partner Prospect API so that a prospect may identify its building and unit by your own identifiers:
| Endpoint | Purpose |
|---|---|
POST /partners/property_owners | Create or update a property owner, and return its slug |
POST /partners/{owner_slug}/bank_accounts | Register the accounts claim payments are sent to |
POST /partners/{owner_slug}/properties | Create or update properties |
POST /partners/{owner_slug}/units | Create or update units |
POST /partners/{owner_slug}/prospects | Existing; a prospect may now reference or create its property and unit |
Base URLs, authentication, and the owner_slug path segment are identical to the rest of the Partner API. See Authentication & Environments. Owner creation is the only call not scoped to a slug, because it is the call that returns one.
Upserts and identifiers
Every resource is keyed on an identifier that you own, never a Rhino one. Resending a payload updates the existing record rather than creating a duplicate, so a batch, or a single item within it, is safe to retry.
| Resource | Upsert key |
|---|---|
| Property owner | external_org_id |
| Bank account | external_system_id, within the owner |
| Property | external_system_id, within the owner |
| Unit | external_system_id, within its property |
You never store a Rhino identifier. Wherever a payload references another resource, such as a unit referencing its property or a property referencing its payout account, it does so with your identifier for that resource.
An upsert writes only the fields it carries. Omitting a field leaves the stored value unchanged, so a scheduled full refresh that drops a field does not revert a value set earlier; sending an explicit null clears an optional field. The two array fields, embedded_frame_ancestors on the owner and authorized_members on a prospect, are the exception: when present, they replace the entire array rather than merging.
Batch requests
Every endpoint on this page, apart from owner creation, accepts a JSON array, even for a single item, and returns a result for each item. A request may carry at most 500 items; an oversized request is rejected in full before any item is processed. Send larger rosters in several batches. Because every operation is an upsert, batching is safe.
{
"status_code": 200,
"results": [
{ "external_system_id": "acme-prop-123", "action": "created" },
{ "external_system_id": "acme-prop-124", "action": "updated" },
{ "external_system_id": "acme-prop-125", "action": "failed",
"errors": { "bank_account_external_id": ["unknown account"] } }
],
"meta": { "created": 1, "updated": 1, "failed": 1 }
}
action is created, updated, or failed. A single invalid item does not fail the batch: the remaining items still apply, and the failed item carries errors keyed by field. Inspect the individual results rather than the HTTP status alone, because a 200 response may still contain failures.
Owner types
- Owners you create. An owner you created through
POST /partners/property_owners. You own all of its configuration: the coverage ceiling, the payout accounts, and the entire roster. - Owners with an existing Rhino relationship. A property management company that worked with Rhino directly before your integration. You do not create these. Rhino grants you access to named buildings and returns the slug; certain fields (
purchase_flow_enabled,max_coverage_amount_cents) remain owned by Rhino, and the owner's payout accounts typically already exist. Coordinate with your Partner Success Manager before sending data for one.
Rhino cannot automatically detect that an owner you are onboarding already works with Rhino. Where that is possible, coordinate before creating the owner; creating it regardless produces a duplicate that must later be merged manually. See Owners with an existing Rhino relationship.
Provisioning an owner
POST /partners/property_ownersreturns theowner_slug, withpurchase_flow_enabled: false.POST /partners/{owner_slug}/bank_accountsregisters payout accounts. The first account becomes the owner's default, so that claims can be paid from the outset.POST /partners/{owner_slug}/properties, thenPOST /partners/{owner_slug}/units, or both in a single pass.POST /partners/property_ownersagain withpurchase_flow_enabled: truesets the owner toactive.- Prospects resolve against the roster, and renters enroll.
Adding buildings later is limited to steps 3 and 5: new buildings are covered automatically and pay claims to the default account unless the property specifies another.
Errors
| Status | Meaning |
|---|---|
401 | Token missing, expired, or invalid |
403 | Authenticated, but not granted access to this owner |
409 | The external_org_id belongs to an owner Rhino manages directly; coordinate rather than creating it |
422 | Validation failure. Field level detail in errors |
Per item failures within a collection are returned as 200 with action: "failed" on the affected item, rather than as a request level error. Ambiguous matches and "unit name required and not derivable" are per item failures.
Next steps
- Property owners: create an owner and obtain its slug
- Bank accounts: configure claim payouts
- Properties: buildings, matching, and address handling
- Units: units, naming, and matching
- Partner Prospect API: referencing the roster from a prospect