# Client scope

> How an API call selects a client in agency mode: the client_id and all_clients query parameters, client_id in request bodies, keys limited to clients, and what happens when agency mode is off.

Source: https://upfour.io/docs/api/client-scope

In agency mode, monitors and other resources can belong to a client. The API has no “current client”: each request says which clients it means, and the key decides which ones it may see.

## Agency mode must be on

Clients are available when agency mode is switched on for the Company. While it is off:

- Every client endpoint, such as `GET /clients`, answers `404 Not found`.
- List endpoints ignore `client_id` and `all_clients` and return company-level resources only.

## Choose clients when you read

Resources that can belong to a client carry an optional `client_id`: monitors, scheduled jobs, status pages, incidents, escalation policies, on-call schedules and playbooks. A resource without one is company-level. List endpoints take two query parameters:

| You send | You get |
| --- | --- |
| nothing | Company-level resources only. |
| `client_id=<uuid>` | The resources of that one client. |
| `all_clients=true` | Everything the key may see: all clients and company-level resources. It wins over `client_id`. |

```bash
export CLIENT_ID="…"   # from GET /clients

curl -s -G https://app.upfour.io/v1/monitors \
  -H "Authorization: Bearer $UP4_API_KEY" \
  --data-urlencode "client_id=$CLIENT_ID"

curl -s -G https://app.upfour.io/v1/monitors \
  -H "Authorization: Bearer $UP4_API_KEY" \
  --data-urlencode "all_clients=true"
```

- `all_clients` counts only when it is exactly `true`.
- A `client_id` that is not a UUID does not fail. The call falls back to company-level resources.
- There is no header for this. The choice belongs to each request, not to the key.

## Choose a client when you write

Create and update calls take `client_id` in the JSON body. Leave it out and the resource is company-level.

```bash
curl -s -X POST https://app.upfour.io/v1/monitors \
  -H "Authorization: Bearer $UP4_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Lakeside Bakery site",
    "url": "https://example.com",
    "monitor_type": "http",
    "client_id": "'"$CLIENT_ID"'"
  }'
```

- Creating a monitor with a `client_id` that is not a client of your Company, or that belongs to an archived client, is `400 bad_request`.
- A key that may not write to that client gets `403` with the message “You do not have write access to this client”.

## Keys limited to clients

A key can be limited to chosen clients when it is created in the app. What a key may see is its client set: for a personal key, what its owner may see, narrowed to the chosen clients; for a team key, the clients of its team plus company-level resources. `GET /me` shows it:

```
"client_set": { "All": false, "CompanyLevel": true, "IDs": ["…", "…"] }
```

| Field | Meaning |
| --- | --- |
| `All` | The key may see every client. |
| `CompanyLevel` | The key may see company-level resources. |
| `IDs` | The clients the key may see when it is limited, otherwise `null`. |

- Lists never contain clients outside the set, whatever you pass in `client_id`.
- A single resource outside the set, such as a monitor, answers `404` and not `403`, so ids of other clients cannot be probed.
- Company-level routes such as `/organization` answer `404` to team keys and to keys that cannot read company-level resources.

## Common mistakes

- **Creating a monitor without `client_id` and then listing with `client_id`.** The monitor is company-level and does not appear.
- **Passing `all_clients=True` or `all_clients=1`.** Only `true` works; the rest means company-level.
- **Expecting an error when agency mode is off.** The parameters are ignored without a message.
- **Sending `client_id` as a header.** No header exists.
- **Changing the client between pages.** The [cursor check](https://upfour.io/docs/api/pagination.md) does not cover it; keep it the same for every page.
