> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nxos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Cross-org access: brokers acting on customer accounts

> How Letters of Authorization let one organization operate the API on behalf of another.

This guide explains how a broker organization operates the API on behalf of customer organizations through a single API key, and how to revoke that access when the relationship ends.

## When you'd use this

The everyday case is a broker (a regulated counterparty that owns the client relationship) serving multiple customer organizations through a single platform integration. Each customer has their own org, accounts, balances, and funding methods. The broker holds an API key and operates on each customer's behalf one request at a time.

Examples:

* A private-broker program where each high-net-worth client has their own org but is operated by the broker's desk.
* A platform that white-labels nxos for partner firms, each managing their own clients.
* A treasury operations team that consolidates several legal entities under one operating team.

If your integration only ever acts on its own org, skip this guide.

## The model

With an LOA, one organization is authorized to act on behalf of another via the platform API. The granting organization (the customer) signs the LOA; the authorized organization (the broker) holds it. Once active, the broker sends requests with the `Nxos-On-Behalf-Of` header set to the customer's org id, and the platform scopes the request to the customer's data.

Signing happens as part of the customer's [verification flow](/guides/verification). Revoking ends access; re-establishing it requires a new grant.

### Lifecycle

```
                signed                       revoke
   PENDING ──────────────► ACTIVE ──────────────► REVOKED
      │                                              ▲
      └─────────────────── revoke ───────────────────┘
```

| Status    | Meaning                                    | Effective for `Nxos-On-Behalf-Of`? |
| --------- | ------------------------------------------ | ---------------------------------- |
| `PENDING` | Granter has not yet signed.                | No                                 |
| `ACTIVE`  | Granter has signed.                        | Yes                                |
| `REVOKED` | Previously active or pending, now revoked. | No                                 |

### KYB gating

An `ACTIVE` LOA is necessary but not sufficient. The granting organization must also currently be in good standing on KYB (verification status `APPROVED`, no past-due expiry). If the granter's verification moves to `PENDING`, `ON_HOLD`, `REJECTED`, or `RESUBMISSION_REQUIRED`, the LOA is suspended for that period and the broker's requests return `403 authorization_required`. Access resumes automatically when the granter returns to `APPROVED`.

From the broker's perspective, this is indistinguishable from a missing LOA: the response is the same `403 authorization_required`. The granter's compliance status is not leaked to a third party.

## Using `Nxos-On-Behalf-Of`

Once an LOA between customer `org_cust...` and broker `org_brkr...` is `ACTIVE` and the customer's KYB is `APPROVED`, the broker calls any delegation-enabled endpoint by setting the header:

```bash theme={null}
curl https://api.sandbox.nxos.io/v1/accounts \
  -H "Authorization: Bearer nxos_sk_test_brkr..." \
  -H "Nxos-On-Behalf-Of: org_cust1234567890abcdef1234567890abcd"
```

The response is the customer's accounts, not the broker's. The request was scoped to the customer for that single call.

### Which routes accept the header

Each route opts in to delegation individually. Self-only routes (creating a child org, signing) omit it: a broker cannot sign an LOA on a customer's behalf, nor create a customer's children. Routes that read or operate on accounts, balances, beneficiaries, quotes, payouts, and NXOS-to-NXOS transfers all accept the header.

If you send `Nxos-On-Behalf-Of` to a route that doesn't accept delegation, the header is silently ignored and the request stays scoped to your own org. The default posture is default-deny: a route only sees data the caller has direct authority over unless it explicitly opts in.

### Possible 403 responses

| Code                     | Meaning                                                                                                                                                                                     | Fix                                                                                   |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `acting_org_not_found`   | The header points to an org that doesn't exist.                                                                                                                                             | Check the org id.                                                                     |
| `authorization_required` | The org exists, but you don't hold a currently effective LOA on it. Possible reasons: the customer hasn't signed, the grant was revoked, or the customer's KYB is not currently `APPROVED`. | Check the LOA state in the dashboard, and confirm the customer's verification status. |

## Revoking an authorization

Either side of the grant can call [`POST /v1/authorizations/revoke`](/api-reference/authorizations/revoke): the granting customer or the authorized broker. The caller's organization (from the API key) must be one of the two parties. Otherwise the call returns `403 forbidden`.

```bash theme={null}
curl -X POST https://api.sandbox.nxos.io/v1/authorizations/revoke \
  -H "Authorization: Bearer nxos_sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "grantingOrganizationId": "org_cust1234567890abcdef1234567890abcd",
    "authorizedOrganizationId": "org_brkr1234567890abcdef1234567890abcd",
    "type": "LOA",
    "reason": "Client off-boarded"
  }'
```

```json theme={null}
{
  "object": "authorization",
  "grantingOrganizationId": "org_cust1234567890abcdef1234567890abcd",
  "authorizedOrganizationId": "org_brkr1234567890abcdef1234567890abcd",
  "type": "LOA",
  "status": "REVOKED",
  "signedAt": "2025-12-01T10:30:00.000Z",
  "revokedAt": "2026-05-15T14:30:00.000Z",
  "revokedReason": "Client off-boarded",
  "createdAt": "2025-12-01T10:30:00.000Z",
  "updatedAt": "2026-05-15T14:30:00.000Z"
}
```

<Warning>
  Revocation is immediate and permanent. The next request the broker makes with `Nxos-On-Behalf-Of` pointing at this customer returns `403 authorization_required`. To re-establish access, the customer must sign a new LOA. There is no restore endpoint.
</Warning>

### Idempotency

A second revoke of the same `(granter, authorized, type)` tuple returns `404 authorization_not_found`. The row is already `REVOKED` and excluded from the active set. There is no separate `already_revoked` error code. "Already revoked" and "never existed" surface identically by design.

You can also supply an `Idempotency-Key` header for client-side dedup of network retries. See [Idempotency](/concepts/idempotency-and-rate-limits).

### Possible errors

| Status | Code                      | When                                                                           |
| ------ | ------------------------- | ------------------------------------------------------------------------------ |
| `400`  | `invalid_request`         | `grantingOrganizationId == authorizedOrganizationId`.                          |
| `400`  | `validation_error`        | Malformed org id (must be `org_<32 hex>`), or `reason` exceeds 500 characters. |
| `403`  | `forbidden`               | Your API key's organization is neither the granter nor the authorized.         |
| `404`  | `organization_not_found`  | One of the two organizations doesn't exist.                                    |
| `404`  | `authorization_not_found` | No non-revoked grant matches the tuple. Already revoked, or never existed.     |

## Summary

| Operation                                            | Where it happens                                                                                                                                                                                                                                                                                      |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Sign LOA                                             | As part of the customer's [verification flow](/guides/verification)                                                                                                                                                                                                                                   |
| Use the LOA                                          | Set `Nxos-On-Behalf-Of: <granter-org-id>` on each request                                                                                                                                                                                                                                             |
| List LOAs                                            | [`GET /v1/authorizations`](/api-reference/authorizations/list), either side. `?role=authorized` for "orgs I can act on", `?role=granter` for "orgs that authorized me"                                                                                                                                |
| Revoke LOA                                           | [`POST /v1/authorizations/revoke`](/api-reference/authorizations/revoke), by either party                                                                                                                                                                                                             |
| Import a customer's verification (`INDIVIDUAL` only) | [`POST /v1/organizations/verification/import`](/api-reference/organizations/import-verification) — pass a Sumsub Reusable KYC share token instead of running the customer through the hosted flow. See [Import from a partner tenant](/guides/verification#importing-from-a-partner-tenant-advanced). |

## Related

* [Authentication](/concepts/authentication): how API keys work
* [Verification](/guides/verification): bringing a customer org through KYB
* [Accounts](/concepts/accounts): what scopes by organization
