> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file 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, the partner authentication scheme, 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 `isPartner`, or minting long-lived partner keys — see [Sign in with Rhombus](/oauth-authentication), which documents the partner OAuth path and key minting. This guide picks up once you have a partner key in hand.
</Note>

## 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](/oauth-authentication#working-with-partner-accounts) for how partner keys are minted.
  * 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](/api-reference/overview#authentication) (`x-auth-scheme` + `x-auth-apikey`) used everywhere else in the API.
</Info>

The base URLs are the same as for any other Rhombus API call — there is no separate partner host:

| 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) |

## 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**         | `partner-api-token`                                                                         | `partner-api-token`                                                              |
| **`x-auth-org` header** | Not used (ignored)                                                                          | **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 calls use the same two headers as standard calls, with one difference — the **scheme** value:

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

```bash theme={null}
-H "x-auth-scheme: partner-api-token" \
-H "x-auth-apikey: YOUR_PARTNER_API_KEY" \
-H "Content-Type: application/json"
```

<Note>
  **Token vs. certificate auth.** Partners using mutual-TLS (certificate-based) credentials instead of a token use `x-auth-scheme: partner-api` with their client certificate. The `partner-api-token` scheme shown throughout this guide is the simpler, token-based option and is recommended for most integrations. Certificate auth is **not** supported on WebSocket connections.
</Note>

<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.
</Warning>

## 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 verifies that your partner account actually manages the target org before honoring the call — if it doesn't, the request is rejected.

<Warning>
  **`x-auth-org` is not listed in the OpenAPI spec.** The auto-generated [API Reference](/api-reference/overview) documents each endpoint's body and the `x-auth-scheme` parameter, but it does not yet describe `x-auth-org`. The header is fully supported regardless — it's the standard mechanism the [Rhombus CLI](/rhombus-cli) uses for its `--partner-org` flag and the one the [WebSocket API](/websocket/authentication) uses for partner connections. Add it yourself on client-level calls; don't expect the "Try it" panel to surface it.
</Warning>

Omit `x-auth-org` on `/api/partner/...` endpoints — partner endpoints already operate at the partner level and ignore it.

## 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` returns lightweight client records (name + UUID + device counts), ideal for quickly resolving a client UUID before acting on it.

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

  ```python Python theme={null}
  import requests

  BASE_URL = "https://api2.rhombussystems.com"
  headers = {
      "x-auth-scheme": "partner-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 theme={null}
  const BASE_URL = "https://api2.rhombussystems.com";
  const headers = {
    "x-auth-scheme": "partner-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 theme={null}
  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", "partner-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)
  	}
  }
  ```
</CodeGroup>

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

```json theme={null}
{
  "clients": [
    {
      "clientOrgName": "Acme Corporation",
      "clientOrgUuid": "aB_cD1eF2gH3iJ4kL5mN",
      "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`. Note this is **not** a partner endpoint; it's the same camera endpoint any organization uses, scoped to your client by the header.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/camera/getMinimalCameraStateList \
    -H "x-auth-scheme: partner-api-token" \
    -H "x-auth-apikey: YOUR_PARTNER_API_KEY" \
    -H "x-auth-org: aB_cD1eF2gH3iJ4kL5mN" \
    -H "Content-Type: application/json" \
    -d '{}'
  ```

  ```python Python theme={null}
  import requests

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

  headers = {
      "x-auth-scheme": "partner-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 theme={null}
  const BASE_URL = "https://api2.rhombussystems.com";
  const CLIENT_ORG_UUID = "aB_cD1eF2gH3iJ4kL5mN";

  const headers = {
    "x-auth-scheme": "partner-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 theme={null}
  package main

  import (
  	"bytes"
  	"net/http"
  )

  func main() {
  	clientOrgUUID := "aB_cD1eF2gH3iJ4kL5mN"

  	req, _ := http.NewRequest("POST",
  		"https://api2.rhombussystems.com/api/camera/getMinimalCameraStateList",
  		bytes.NewBufferString("{}"))
  	req.Header.Set("x-auth-scheme", "partner-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...
  }
  ```
</CodeGroup>

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. The header is what redirects the call into the managed client.

### The CLI does this for you

The [Rhombus CLI](/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 theme={null}
# By UUID
rhombus --partner-org aB_cD1eF2gH3iJ4kL5mN 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 scheme and target org, but pass them as **query parameters** rather than headers. See [WebSocket Authentication](/websocket/authentication) for the full pattern:

```text theme={null}
wss://ws.rhombussystems.com:8443/websocket?x-auth-scheme=partner-api-token&x-auth-org=aB_cD1eF2gH3iJ4kL5mN
```

## Partner endpoint reference

These `/api/partner/...` endpoints operate at the partner level and require a partner key. All are `POST`. Browse full request/response schemas in the [API Reference](/api-reference/overview).

| 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                                    |

<Note>
  Partner API keys are minted with `POST /api/partner/submitApiTokenApplication`. That minting endpoint is not part of the public OpenAPI spec, so it won't appear in the API Reference — see [Sign in with Rhombus → Working with partner accounts](/oauth-authentication#working-with-partner-accounts) for how to obtain partner keys.
</Note>

## Troubleshooting

<AccordionGroup>
  <Accordion title="401 Unauthorized on a client-level endpoint">
    Confirm your scheme is `partner-api-token` (not `api-token`) and that `x-auth-apikey` is your partner key. A standard org key cannot reach other organizations no matter what `x-auth-org` you send.
  </Accordion>

  <Accordion title="403 Forbidden, or the call targets the wrong org">
    The `x-auth-org` value must be a client your partner account actually manages. Re-fetch the list with `getClientsV2` and copy the exact `clientOrgUuid` — these are base64 url-safe UUIDs (\~22 chars), so a truncated or re-encoded value will be rejected or resolve to the wrong org.
  </Accordion>

  <Accordion title="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. Add the header to scope the call into the client.
  </Accordion>

  <Accordion title="x-auth-org seems to be ignored on a /api/partner/ endpoint">
    That's expected. Partner endpoints operate at the partner level and ignore `x-auth-org`. Use the endpoint's own request body (for example, the `orgUuid` field on `registerCameraToClient`) to specify which client an action applies to.
  </Accordion>

  <Accordion title="Partner auth fails over WebSocket">
    WebSocket connections don't support certificate (`partner-api`) auth — generate a token-based key and use `partner-api-token`. Also remember that for WebSocket, `x-auth-scheme` and `x-auth-org` are **query parameters**, not headers. See [WebSocket Authentication](/websocket/authentication).
  </Accordion>
</AccordionGroup>

## Next steps

<Columns cols={2}>
  <Card title="Sign in with Rhombus" icon="key" href="/oauth-authentication">
    Obtain partner credentials and mint long-lived partner keys
  </Card>

  <Card title="WebSocket Authentication" icon="bolt" href="/websocket/authentication">
    Open real-time partner connections scoped to a client org
  </Card>

  <Card title="Rhombus CLI" icon="terminal" href="/rhombus-cli">
    Use --partner-org to run any command against a managed client
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/overview">
    Browse every partner and client-level endpoint
  </Card>
</Columns>
