The partner API
The REST API is for a system that wants to do more than announce checkouts: register the hosts it manages, raise a cleaning on demand, subscribe a host to a package and read back what happened.
It sits alongside the webhook, it does not replace it. For automatic turnovers the webhook is the right tool; the API is what you call when your own software is deciding.
Base URL: https://suitiee.com/api/v1
The full reference, with every field and a request builder, is at Integrations → API documentation in your operator panel.

What you need
- An operator (
/partner) account. - An API key: Settings → API keys → create. It is shown once. Name it after the system that will use it, so you can revoke one without breaking the others.

Step 1 — Authenticate
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
60 requests a minute per key. Above that you get 429; back off and retry.
Step 2 — Know the envelope
One shape for everything, so a client can be written once.
{ "data": { }, "message": "Optional" }
A list adds paging:
{ "data": [ ], "meta": { "current_page": 1, "last_page": 5, "per_page": 15, "total": 73 } }
An error is never a bare string:
{ "error": { "code": "INSUFFICIENT_BALANCE", "message": "…", "details": { } } }
Codes you should handle by name rather than by message: UNAUTHENTICATED, FORBIDDEN,
NOT_FOUND, VALIDATION_ERROR, INSUFFICIENT_BALANCE, PACKAGE_EXHAUSTED,
PACKAGE_EXPIRED, SLOT_UNAVAILABLE.
Amounts are SAR with two decimals; dates are ISO 8601 UTC; public resources are identified
by UUID, and your hosts by your own external_id.
Step 3 — Register the hosts
POST /partner/clients
{ "external_id": "OWNER-118", "client_phone": "+9665…", "client_name_en": "…" }
external_id is yours. Every later call names the host by it, so use whatever your own
system already calls them and never change it.
GET /partner/clients, GET /partner/clients/{external_id} and
PUT /partner/clients/{external_id} do the rest.
Step 4 — The PMS flow: announce, then check out
This is the pair that makes turnovers automatic without a webhook.
POST /partner/reservations
{
"external_reservation_id": "BK-99120",
"client_external_id": "OWNER-118",
"external_unit_id": "APT-204",
"checkin_datetime": "2026-09-06T15:00:00Z",
"expected_checkout_datetime": "2026-09-09T11:00:00Z",
"next_checkin_datetime": "2026-09-09T16:00:00Z"
}
The booking is anticipated: nothing is billed and nobody is dispatched. Send
next_checkin_datetime as soon as you know it and the cleaning window will end before that
arrival rather than defaulting to five hours.
POST /partner/reservations/{external_reservation_id}/checkout
That is the moment it is billed, a cleaning is created and a cleaner is dispatched.
GET /partner/reservations and GET /partner/reservations/{id} read them back.
Step 5 — The compound flow: raise the work yourself
A building or compound that is not selling nights has no checkouts to react to. It books the work directly:
POST /partner/requests
Idempotency-Key: 3f1c-…
{
"client_external_id": "OWNER-118",
"service_id": "…",
"requested_window_start": "2026-09-06T08:00:00Z",
"requested_window_end": "2026-09-06T12:00:00Z"
}
The price is captured at creation. The host's package visits are used first, then their wallet.
GET /partner/requests lists them, GET /partner/requests/{uuid} reads one, and
POST /partner/requests/{uuid}/cancel cancels one under your own cancellation rules.
Step 6 — Always send an Idempotency-Key
POST /partner/requests accepts an Idempotency-Key header. Send a fresh one per intent and
repeat it on every retry of that same intent.
Without it, a request that times out on your side and is retried bills the host twice, and neither of you finds out until the invoice.
The rest of the surface
| Call | What it is for |
|---|---|
GET /partner/packages |
The packages you can subscribe a host to |
POST /partner/clients/{external_id}/subscribe |
Subscribe one, funded by your credit. See Partner credit |
GET /partner/credits |
Your credit balance and its ledger |
GET /partner/webhooks/events |
Every event you have sent us and what became of it |
What the API does not do yet
Named because guessing costs a day: there is no services catalogue endpoint, no maintenance by API, no proof-photo endpoint, no invoices endpoint, and no way to change a booking's dates after announcing it. Those are planned. Everything above is what exists today.
When it goes wrong
| What you see | What it means | What to do |
|---|---|---|
401 UNAUTHENTICATED |
The key is wrong, revoked, or not sent as Bearer |
Mint a new key under Settings → API keys |
422 VALIDATION_ERROR |
details.errors names the field |
Read details, not the message |
422 INSUFFICIENT_BALANCE |
The host cannot pay for this visit | Top up the wallet, or subscribe them to a package |
404 on a host you just created |
You are addressing them by our id rather than your external_id |
Use your own id everywhere |
| Two cleanings for one intent | A retry without an Idempotency-Key |
Send one and repeat it on retries |
429 |
60 a minute per key | Back off; use one key per system so one client cannot starve another |
| Everything succeeds and nothing happens in the real world | The account is in test mode | See Test mode |