> ## Documentation index
> Fetch the complete documentation index at: https://developer.rhombus.com/llms.txt
> Use it to discover all available pages before exploring further.

# Partner API Calls

> Make Rhombus API calls as a partner — authenticate with a partner API key, manage your client organizations with partner endpoints, and scope client-level calls to a managed org using the x-auth-org header.

## Overview

If you're a Rhombus **partner** — a managed service provider (MSP) or reseller that operates many customer organizations under one partner account — your API key works differently from a standard organization key. A single partner key lets you:

- Manage your fleet of client organizations with **partner endpoints** (`/api/partner/...`) — list clients, register hardware, check licenses, and issue API tokens.
- Reach into any one of those clients and call **client-level endpoints** (cameras, access control, sensors, users — the rest of the API) _as that client_, by naming the target org in a single request header.

This guide explains the two kinds of calls, how partner credentials authenticate, and the `x-auth-org` header that ties them together so one set of credentials can operate across every organization you manage.

> **Note**: **What this guide isn't.** This covers making REST API calls with an existing partner API key. If you need to _obtain_ partner credentials — the OAuth browser-login flow, detecting partner accounts, or minting long-lived partner keys — see [Sign in with Rhombus](https://developer.rhombus.com/oauth-authentication), which documents the partner OAuth path and key minting. This guide picks up once you have a partner key in hand.

## Before you begin

> **Info**: To follow this guide you need:
>
> - A **partner API key** (`x-auth-apikey`) issued for your partner account. See [Sign in with Rhombus → Working with partner accounts](https://developer.rhombus.com/oauth-authentication#working-with-partner-accounts) for how partner keys are minted. A partner user's OAuth access token works the same way, sent as `Authorization: Bearer <token>`.
> - The **client organization UUID** of any client you want to act on. You don't have to know it up front — the first call below returns it.
> - Familiarity with the [standard authentication headers](https://developer.rhombus.com/api-reference/overview#authentication) (`x-auth-scheme` + `x-auth-apikey`) used everywhere else in the API.

The base URLs are the same as for any other Rhombus API call — there is no separate partner host. Use your [region's](https://developer.rhombus.com/api-regions) base URLs (US shown here; EU organizations use the `.eu.` variants):

| Base URL                           | Purpose                                               |
| ---------------------------------- | ----------------------------------------------------- |
| `https://api2.rhombussystems.com`  | All API endpoints, partner and client-level           |
| `https://media.rhombussystems.com` | Media and streaming (clips, live streams, thumbnails) |

> **Note**: Partner keys are region-bound like any other API key, and a partner account and its client organizations live in the same region.

## Two kinds of calls

Every request you make as a partner is one of two kinds. The difference is the endpoint path — and whether you scope the call to a specific client.

|                         | Partner endpoints                                                                           | Client-level endpoints                                                           |
| ----------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| **Path prefix**         | `/api/partner/...`                                                                          | Everything else (`/api/camera/...`, `/api/accesscontrol/...`, `/api/org/...`, …) |
| **What they do**        | Manage your portfolio of clients: list orgs, register devices, check licenses, issue tokens | Operate _inside_ one org: cameras, doors, sensors, users, events                 |
| **Who can call them**   | Partner accounts only                                                                       | Any account; a partner targets a specific client                                 |
| **Auth scheme**         | `api-token` (`partner-api-token` also accepted)                                             | `api-token` (`partner-api-token` also accepted)                                  |
| **`x-auth-org` header** | **Don't send it** — it moves the call into that client org                                  | **Required** — names the client org to act as                                    |

The key idea: **partner endpoints operate at the partner level, client-level endpoints operate inside one organization.** A partner reaches into a client by adding the `x-auth-org` header — covered below. There are no "partner versions" of client endpoints; you call the same `/api/camera/...` endpoint a customer would, just with partner credentials and the `x-auth-org` header.

## Authenticating as a partner

Partner credentials use the same schemes and headers as any other credential. `api-token`, `api` and `api-oauth-token` accept partner credentials, and `partner-api-token`, `partner-api` and `partner-api-oauth-token` are accepted as aliases for them. With a partner API key:

| Header          | Value                                          |
| --------------- | ---------------------------------------------- |
| `x-auth-scheme` | `api-token` (or its alias `partner-api-token`) |
| `x-auth-apikey` | Your partner API key                           |
| `Content-Type`  | `application/json`                             |

```bash
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_PARTNER_API_KEY" \
-H "Content-Type: application/json"
```

Create a partner API key in the Rhombus Console under **Settings → API Management → Add API Key**.

> **Note**: **Other partner credentials.** Partners using mutual-TLS (certificate-based) keys use `x-auth-scheme: api` (or `partner-api`) with their client certificate; certificate keys aren't accepted on the event WebSocket. A partner user's OAuth access token goes in `Authorization: Bearer <token>`. The token-based key shown throughout this guide is the simplest option and is recommended for most integrations.

> **Warning**: **Treat a partner API key like a master key.** It can reach every organization you manage. Store it encrypted at rest, never commit it to source control, and rotate or revoke unused keys. A leaked partner key exposes all of your clients, not just one.

## Scoping a call to a client organization

To make a client-level call on behalf of a managed client, add the **`x-auth-org`** header set to that client's organization UUID:

| Header       | Value                                                                                              |
| ------------ | -------------------------------------------------------------------------------------------------- |
| `x-auth-org` | The target client organization's UUID (base64 url-safe, \~22 chars, e.g. `AAAAAAAAAAAAAAAAAAAAAA`) |

With this header present, Rhombus treats the request as though it came from inside that client organization. The server checks that the client has granted your partner account access (login access, or management by your MSP) and that the grant hasn't expired; if not, the request is rejected with 403 `PARTNER_CLIENT_ACCESS_DENIED`. A value that isn't a valid organization UUID is rejected with 400 `INVALID_AUTH_ORG`. Inside the client org, the call can do what the role the client granted your partner account allows.

- **`x-auth-org` is a header only.** It's never read from a query parameter.
- **It means the same for every partner credential:** partner API keys, partner certificate keys and partner OAuth access tokens.
- **A blank value counts as absent.**
- **The [API Reference](https://developer.rhombus.com/api-reference/overview) lists it on every operation**, and the [Rhombus CLI](https://developer.rhombus.com/rhombus-cli) sets it for its `--partner-org` flag.

Omit `x-auth-org` on `/api/partner/...` endpoints. Partner endpoints operate at the partner level; sending `x-auth-org` there moves the call into the client org, so it fails or acts on the wrong org.

### Calls without `x-auth-org`

A partner credential that calls a client-level endpoint without `x-auth-org` still works, and acts in your partner organization, but the response carries two headers:

```http
Deprecation: true
Sunset: Tue, 05 Jan 2027 00:00:00 GMT
```

After January 5, 2027, those calls return an error. Send `x-auth-org` on every client-level call; the `/api/partner/...` endpoints don't need it. The event WebSocket already refuses a partner handshake without `x-auth-org`, with 403 `PERMISSION_REQUIRED`.

## Examples

### Step 1 — List your client organizations

Start with a partner endpoint to discover the orgs you manage and their UUIDs. [`POST /api/partner/getClientsV2`](https://developer.rhombus.com/api-reference/partner-webservice/get-partner-clients-v2) returns lightweight client records (name + UUID + device counts), ideal for quickly resolving a client UUID before acting on it.

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/partner/getClientsV2 \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```python Python
import requests

BASE_URL = "https://api2.rhombussystems.com"
headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_PARTNER_API_KEY",
    "Content-Type": "application/json",
}

resp = requests.post(f"{BASE_URL}/api/partner/getClientsV2", headers=headers, json={})
resp.raise_for_status()

for client in resp.json().get("clients", []):
    print(client["clientOrgName"], "->", client["clientOrgUuid"])
```

```javascript JavaScript
const BASE_URL = "https://api2.rhombussystems.com";
const headers = {
  "x-auth-scheme": "api-token",
  "x-auth-apikey": "YOUR_PARTNER_API_KEY",
  "Content-Type": "application/json",
};

const resp = await fetch(`${BASE_URL}/api/partner/getClientsV2`, {
  method: "POST",
  headers,
  body: JSON.stringify({}),
});
const data = await resp.json();
for (const client of data.clients ?? []) {
  console.log(`${client.clientOrgName} -> ${client.clientOrgUuid}`);
}
```

```go Go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST",
		"https://api2.rhombussystems.com/api/partner/getClientsV2",
		bytes.NewBufferString("{}"))
	req.Header.Set("x-auth-scheme", "api-token")
	req.Header.Set("x-auth-apikey", "YOUR_PARTNER_API_KEY")
	req.Header.Set("Content-Type", "application/json")

	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()

	var out struct {
		Clients []struct {
			ClientOrgName string `json:"clientOrgName"`
			ClientOrgUUID string `json:"clientOrgUuid"`
		} `json:"clients"`
	}
	json.NewDecoder(resp.Body).Decode(&out)
	for _, c := range out.Clients {
		fmt.Printf("%s -> %s\n", c.ClientOrgName, c.ClientOrgUUID)
	}
}
```

A response lists each managed client, including the `clientOrgUuid` you'll pass as `x-auth-org`:

```json
{
  "clients": [
    {
      "clientOrgName": "Acme Corporation",
      "clientOrgUuid": "aB_cD1eF2gH3iJ4kL5mN6o",
      "totalCameras": 25,
      "totalLocations": 3
    },
    {
      "clientOrgName": "Beta Industries",
      "clientOrgUuid": "nO_pQ6rS7tU8vW9xY0zZ",
      "totalCameras": 12,
      "totalLocations": 1
    }
  ]
}
```

### Step 2 — Call a client-level endpoint as a managed client

Now use a client UUID from Step 1 in the `x-auth-org` header to call a regular client-level endpoint — here, listing a client's cameras with [`POST /api/camera/getMinimalCameraStateList`](https://developer.rhombus.com/api-reference/camera-webservice/get-minimal-camera-state-list). Note this is **not** a partner endpoint; it's the same camera endpoint any organization uses, scoped to your client by the header.

```bash cURL
curl -X POST https://api2.rhombussystems.com/api/camera/getMinimalCameraStateList \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_PARTNER_API_KEY" \
  -H "x-auth-org: aB_cD1eF2gH3iJ4kL5mN6o" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```python Python
import requests

BASE_URL = "https://api2.rhombussystems.com"
CLIENT_ORG_UUID = "aB_cD1eF2gH3iJ4kL5mN6o"

headers = {
    "x-auth-scheme": "api-token",
    "x-auth-apikey": "YOUR_PARTNER_API_KEY",
    "x-auth-org": CLIENT_ORG_UUID,   # act as this managed client
    "Content-Type": "application/json",
}

resp = requests.post(
    f"{BASE_URL}/api/camera/getMinimalCameraStateList",
    headers=headers,
    json={},
)
resp.raise_for_status()
print(resp.json().get("cameraStates", []))
```

```javascript JavaScript
const BASE_URL = "https://api2.rhombussystems.com";
const CLIENT_ORG_UUID = "aB_cD1eF2gH3iJ4kL5mN6o";

const headers = {
  "x-auth-scheme": "api-token",
  "x-auth-apikey": "YOUR_PARTNER_API_KEY",
  "x-auth-org": CLIENT_ORG_UUID, // act as this managed client
  "Content-Type": "application/json",
};

const resp = await fetch(`${BASE_URL}/api/camera/getMinimalCameraStateList`, {
  method: "POST",
  headers,
  body: JSON.stringify({}),
});
console.log((await resp.json()).cameraStates);
```

```go Go
package main

import (
	"bytes"
	"net/http"
)

func main() {
	clientOrgUUID := "aB_cD1eF2gH3iJ4kL5mN6o"

	req, _ := http.NewRequest("POST",
		"https://api2.rhombussystems.com/api/camera/getMinimalCameraStateList",
		bytes.NewBufferString("{}"))
	req.Header.Set("x-auth-scheme", "api-token")
	req.Header.Set("x-auth-apikey", "YOUR_PARTNER_API_KEY")
	req.Header.Set("x-auth-org", clientOrgUUID) // act as this managed client
	req.Header.Set("Content-Type", "application/json")

	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
	// decode resp.Body...
}
```

Drop the `x-auth-org` header and the same call would target _your_ partner organization instead of the client — which usually has no cameras of its own — and the response would carry the `Deprecation` and `Sunset` headers described in [Calls without `x-auth-org`](https://developer.rhombus.com/partner-api-calls#calls-without-x-auth-org). The header is what redirects the call into the managed client.

### The CLI does this for you

The [Rhombus CLI](https://developer.rhombus.com/rhombus-cli) wraps the same mechanism behind a `--partner-org` flag, accepting either a client UUID or name and setting `x-auth-org` for you:

```bash
# By UUID
rhombus --partner-org aB_cD1eF2gH3iJ4kL5mN6o camera get-minimal-camera-state-list

# By client name (the CLI resolves it to a UUID via getClientsV2)
rhombus --partner-org "Acme Corporation" camera get-minimal-camera-state-list
```

### WebSocket connections

Real-time partner connections use the same credentials. On the WebSocket handshake, send `x-auth-apikey` and `x-auth-org` as **HTTP headers**. `x-auth-scheme` can go in the query string or a header. `x-auth-org` is not read from the query string, and it's required: a partner handshake without it is refused with 403 `PERMISSION_REQUIRED`. Browsers can't set custom headers on a WebSocket handshake, so connect from a server-side client. See [WebSocket Authentication](https://developer.rhombus.com/websocket/authentication) for the full pattern.

```text
URL:     wss://ws.rhombussystems.com:8443/websocket?x-auth-scheme=api-token
Headers: x-auth-apikey: YOUR_PARTNER_API_KEY
         x-auth-org: aB_cD1eF2gH3iJ4kL5mN6o
```

## Partner endpoint reference

These `/api/partner/...` endpoints operate at the partner level and require a partner credential. All are `POST`. Browse full request/response schemas in the [API Reference](https://developer.rhombus.com/api-reference/partner-webservice/get-partner-clients-v2).

| Purpose        | Endpoint                           | What it does                                                       |
| -------------- | ---------------------------------- | ------------------------------------------------------------------ |
| **Clients**    | `getClients`                       | List all client organizations (full info)                          |
|                | `getClientsV2`                     | List clients with basic info — fastest way to resolve client UUIDs |
|                | `getClientSummaryInfo`             | Summary for a single client                                        |
|                | `getClientStatusMap`               | Aggregated device and location status across clients               |
|                | `createPartnerClient`              | Create a new client organization                                   |
|                | `customizeClient`                  | Customize a client account                                         |
|                | `deleteClient`                     | Delete a client organization                                       |
| **Devices**    | `getClientDevices`                 | Devices for a specific client                                      |
|                | `getListOfAllClientDevices`        | Devices across every managed client                                |
|                | `getListOfAvailableHardware`       | Hardware available for registration                                |
|                | `getClaimKeysForPartnerOrg`        | Claim keys for the partner org                                     |
|                | `registerCameraToClient`           | Register a camera to a client org                                  |
|                | `reassignDeviceOrg`                | Move a device from one client org to another                       |
|                | `customizeClientDevice`            | Customize a client device                                          |
| **Licensing**  | `getLicensesForOrg`                | Licenses available to a client org                                 |
|                | `getDeviceLicensesForOrg`          | Device-specific licenses for a client org                          |
|                | `updateSendLicenseExpirationEmail` | Toggle license-expiration email alerts                             |
| **API tokens** | `getApiTokens`                     | List the partner's active API tokens                               |
|                | `getApiTokenApplications`          | List pending token applications                                    |
|                | `revokeApiToken`                   | Revoke a partner API token                                         |
| **Sales**      | `registerDeal`                     | Register a deal/opportunity                                        |
|                | `getShipments`                     | Shipments for a specific client                                    |

## Partner API keys

Create partner keys in the console under **Settings → API Management**, or with the API. These endpoints run at the partner level, so call them without `x-auth-org`. All are `POST`:

| Action              | Endpoint                                                                                                                                | Body                                                                                                                      | Response                                                                                |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Create              | [`/api/partner/submitApiTokenApplication`](https://developer.rhombus.com/api-reference/partner-webservice/submit-api-token-application) | `displayName`, `permissionGroupUuid` (a partner role), `authType` (`API_TOKEN` or `CERT` with a `csr`), `expiresAtMs`     | `apiKey`, `tokenUuid`, `expiresAtMs`; for certificate keys, `cert` and `certNotAfterMs` |
| Rotate              | [`/api/partner/rotateApiToken`](https://developer.rhombus.com/api-reference/partner-webservice/rotate-api-token)                        | `tokenUuid`, optional `overlapSec` (default 86400, at most 2592000), `csr` (required for certificate keys), `expiresAtMs` | The create fields plus `previousKeyExpiresAtMs`                                         |
| Renew a certificate | [`/api/partner/renewApiTokenCert`](https://developer.rhombus.com/api-reference/partner-webservice/renew-api-token-certificate)          | `csr`, and `tokenUuid` unless a certificate key renews its own certificate                                                | `cert`, `certNotAfterMs`                                                                |

- **Who can call them:** a partner console or mobile app session, a partner user's OAuth access token (with all three [scopes](https://developer.rhombus.com/oauth-authentication#scopes)), or a partner API key, whose partner role includes API administration. Federated tokens can't.
- **When the caller is a partner API key,** `expiresAtMs` is required: at most 365 days from now, and no later than the calling key's own expiry. The new key is deleted when the calling key is deleted. A key creates and rotates keys only in its own organization, so a partner key that sends `x-auth-org` to these endpoints gets 403.
- **Rotation** issues a key with the same role and keeps the old key working for `overlapSec` seconds; `previousKeyExpiresAtMs` says when it stops.
- **Renewal** keeps the same key and issues a new certificate, with no overlap. Partner certificates last 365 days, and a CSR whose signature doesn't verify is rejected.
- **Expired keys** get 401 `CREDENTIAL_EXPIRED` and still appear in `getApiTokens` until you revoke them.

```bash cURL
# Rotate a partner key; the old key keeps working for one day.
EXPIRES_AT_MS=$(( ($(date +%s) + 90 * 86400) * 1000 ))
curl -X POST "https://api2.rhombussystems.com/api/partner/rotateApiToken" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_PARTNER_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"tokenUuid\": \"OLD_TOKEN_UUID\", \"overlapSec\": 86400, \"expiresAtMs\": $EXPIRES_AT_MS}"
```

[Manage keys with the API](https://developer.rhombus.com/authentication/api-keys#manage-keys-with-the-api) documents the same fields for organization keys. To mint a partner key from a partner user's sign-in, see [Sign in with Rhombus → Working with partner accounts](https://developer.rhombus.com/oauth-authentication#working-with-partner-accounts).

## Troubleshooting

**401 Unauthorized**

A 401 means the credential is missing, malformed, unknown, expired or revoked. The body's `errorCode` says which: `UNAUTHENTICATED` (no credential sent), `INVALID_CREDENTIAL` (a malformed value, or a key that was deleted or belongs to the other [region](https://developer.rhombus.com/api-regions)), `CREDENTIAL_EXPIRED`, `CREDENTIAL_REVOKED`, or `CERTIFICATE_MISMATCH` (a certificate issued for a different key). Check `x-auth-scheme` and that the key is in `x-auth-apikey`.

**400 INVALID_AUTH_ORG**

The `x-auth-org` value isn't a valid organization UUID. Copy the exact `clientOrgUuid` from `getClientsV2`: these are base64 url-safe UUIDs (\~22 chars), so a truncated or re-encoded value is rejected.

**403 Forbidden, or the call targets the wrong org**

`PARTNER_CLIENT_ACCESS_DENIED` means your partner account doesn't have access to the `x-auth-org` organization: it isn't a client you manage, or its grant to you has expired. Re-fetch the list with `getClientsV2` and copy the exact `clientOrgUuid`. `PERMISSION_REQUIRED` means the credential is valid but the role (or, for an OAuth token, its scopes) doesn't allow the call. A standard organization key can't reach other organizations, whatever `x-auth-org` you send.

**An empty or unexpected response on a client endpoint**

If you forgot `x-auth-org`, the call ran against your partner organization (which typically owns no cameras, doors, or sensors) and returned an empty list; the response also carries `Deprecation` and `Sunset` headers. Add the header to scope the call into the client.

**A /api/partner/ endpoint fails or acts on the wrong org**

Don't send `x-auth-org` to partner endpoints: it moves the call into the client org. Use the endpoint's own request body (for example, the `orgUuid` field on `registerCameraToClient`) to say which client an action applies to.

**Partner auth fails over WebSocket**

The event WebSocket doesn't accept certificate keys. Generate a token-based key and use `api-token`. On the handshake, `x-auth-scheme` may be a query parameter, but `x-auth-apikey` and `x-auth-org` must be HTTP headers. A partner handshake without `x-auth-org` is refused with 403 `PERMISSION_REQUIRED`. See [WebSocket Authentication](https://developer.rhombus.com/websocket/authentication).

## Next steps

- **[Sign in with Rhombus](https://developer.rhombus.com/oauth-authentication)**: Obtain partner credentials and mint long-lived partner keys
- **[WebSocket Authentication](https://developer.rhombus.com/websocket/authentication)**: Open real-time partner connections scoped to a client org
- **[Rhombus CLI](https://developer.rhombus.com/rhombus-cli)**: Use --partner-org to run any command against a managed client
- **[API Reference](https://developer.rhombus.com/api-reference/overview)**: Browse every partner and client-level endpoint
