---
title: "Endpoints a tenant can reach"
description: "Every broker route, classified into the seven classes the gateway enforces: produce, consume, queue admin, read, gated, operator, blocked."
---

> Queen MQ documentation, for AI agents
> Complete self-contained summary of Queen MQ: https://queenmq.com/llms-brief.txt
> Fetch that first when the question is about the product rather than about this page.
> Index of all pages: https://queenmq.com/llms.txt

# Endpoints a tenant can reach

The gateway does not forward a request it cannot name. Every broker-bound path is
matched against one classifier, which returns exactly one class, and the class decides
three things at once: which credential may use the route, which limits apply to it, and
which usage class it meters as.

The classifier is the enforcement spec. It runs on the URL path only, never the query
string, and it is written to fail closed.

## How a path is classified

1. **The operator subset is checked first**, because the prefix blocks below would
   otherwise swallow two of its entries. It is a closed list of eight paths. Matching
   it opens nothing on its own: reaching one still needs a live operator principal, and
   on a cell with `QUEEN_PROXY_OPERATOR_ENABLED` off the route answers `404` before
   authentication runs at all.

2. **Hard blocks.** Everything under `/api/v1/migration`, `/api/v1/system`, and
   `/internal`, plus `/api/v1/stats/refresh`, bare `/metrics`, the broker's own
   `/status`, and the queue-less discovery pop `GET /api/v1/pop`. Blocked for every
   principal on every cell.

3. **Data plane, then queue admin, then gated features, then reads**, by exact path or
   prefix, and for some routes by method: a `DELETE` under `/api/v1/resources/queues/`
   is queue admin, while a `GET` on the same prefix is a read. The gated families
   (streams, traces, kv, timers, ephemeral) are method-exact: a verb the broker does not
   register for a path fails closed here rather than travelling upstream to a `405`.

4. **Anything else under `/api/` is blocked.** An unrecognised API-shaped path is never
   forwarded, so a broker route added upstream does not become reachable by accident.
   It has to be classified here first.

5. **Everything else is a read.** That is the dashboard and static-asset fallback.

A blocked or unauthorized-operator route answers `404 {"code":"route_blocked"}`, not
`403`. A tenant learns that a path does not exist for them rather than that it exists
and is forbidden.

## Classes with extra behaviour

**`produce`** is buffered and parsed: items are counted, per-item payload sizes checked,
each `(queue, partition)` admitted against the plan caps, and message tokens taken.
Whatever is buffered is forwarded byte for byte: the proxy never rewrites a body.

Produce is no longer the only class read on the way in. `POST /api/v1/configure` is
buffered as the explicit creation path, so the created queue passes the same registry
admission plus the plan's retention ceiling. The streams cycle is always buffered,
because its sink `push_items` are messages: they answer the produce caps, and a blocked
cluster refuses whole any cycle that grows while an ack-only or state-only one passes. A
kv or timers batch is buffered only while its cluster is push-blocked, to refuse whole a
batch that grows stored state while letting cancels and deletes through. And
`POST /api/v1/ephemeral/push` is buffered so its items debit the message bucket, the one
limit that applies to the RAM class ([quotas](/reference/multi-tenant/quotas/)).

**`consume`** with `wait=true` holds a parked-consumer slot for the duration of the
upstream call, and the long-poll timeout is recomputed as the client's requested wait,
clamped to `QUEEN_PROXY_LONGPOLL_MAX_MS`, plus `QUEEN_PROXY_LONGPOLL_MARGIN_MS`. The
ephemeral `wait=true` pop parks on the same slot.

## The table

The proxy classifies every broker-bound request into exactly one class, and anything API-shaped that matches no rule is blocked. The table below applies that classifier to the broker's own route list.

| Class | What it means |
| --- | --- |
| produce | Counted against the message quota. May create queues and partitions implicitly. |
| consume | Pop, ack and lease extension. A `wait=true` pop also holds a parked-consumer slot. |
| queue admin | Configuration, deletions, seeks and subscription changes. |
| read | Listings, status, analytics, DLQ and message reads, all tenant-scoped. |
| gated (streams) | Available when the plan enables the streams feature. Registration and the state read are never quota-blocked. The cycle is the produce half of the family: a cycle whose body carries sink `push_items` answers the storage and monthly blocks (refused whole, with the same code the equivalent push would get), its sink queues and partitions pass registry admission, its items answer the per-item payload cap, and its accepted sink messages are billed as push. An ack-only or state-only cycle always passes, so a blocked tenant can keep draining its source. |
| gated (traces) | Writing a trace is available when the plan enables the traces feature. |
| gated (kv) | Available when the plan enables the KV feature, which a plan that has never heard of it does not. A `PUT` is the half a storage quota blocks; a `GET` is read level; a `DELETE` is how a tenant at its cap gets back under it and is never quota-blocked. The batch `POST` carries both halves in one array, so a quota refuses the whole call with a named reason rather than dropping part of it. |
| gated (timers) | Available when the plan enables the timers feature. Scheduling is quota-blockable; cancelling is not, and has its own route for that reason, since a tenant blocked from cancelling would keep producing messages it can no longer stop. |
| gated (ephemeral) | Available when the plan enables the ephemeral feature, which a plan that has never heard of it does not. A `push` is the half a storage quota blocks and its messages are counted like any other; a pop is metered as a delivery and holds a parked-consumer slot while it waits; ack, configure, reset and the queue `DELETE` are write level and never quota-blocked, since dropping a queue is how a tenant gets its memory back. The two status reads are read level. |
| operator | Cell-wide surfaces. Not tenant-scopable, so a tenant credential gets the same 404 a blocked route returns. |
| blocked | Never exposed to a tenant, whatever the credential. Returns 404. |

### produce

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/push` |
| `POST` | `/api/v1/transaction` |

### consume

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/ack` |
| `POST` | `/api/v1/ack/batch` |
| `POST` | `/api/v1/lease/:leaseId/extend` |
| `GET` | `/api/v1/pop/queue/:queue` |
| `GET` | `/api/v1/pop/queue/:queue/partition/:partition` |

### queue admin

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/configure` |
| `DELETE` | `/api/v1/consumer-groups/:group` |
| `DELETE` | `/api/v1/consumer-groups/:group/queues/:queue` |
| `POST` | `/api/v1/consumer-groups/:group/queues/:queue/partitions/:partition/seek` |
| `POST` | `/api/v1/consumer-groups/:group/queues/:queue/seek` |
| `POST` | `/api/v1/consumer-groups/:group/subscription` |
| `DELETE` | `/api/v1/messages/:partitionId/:transactionId` |
| `DELETE` | `/api/v1/resources/queues/:queue` |

### read

| Method | Path |
| --- | --- |
| `GET` | `/api/v1/analytics/queue-lag` |
| `GET` | `/api/v1/analytics/queue-ops` |
| `GET` | `/api/v1/analytics/queue-parked-replicas` |
| `GET` | `/api/v1/analytics/retention` |
| `GET` | `/api/v1/consumer-groups` |
| `GET` | `/api/v1/consumer-groups/:group` |
| `GET` | `/api/v1/consumer-groups/lagging` |
| `GET` | `/api/v1/dlq` |
| `GET` | `/api/v1/messages` |
| `GET` | `/api/v1/messages/:partitionId/:transactionId` |
| `POST` | `/api/v1/messages/:partitionId/:transactionId/retry` |
| `GET` | `/api/v1/resources/namespaces` |
| `GET` | `/api/v1/resources/overview` |
| `GET` | `/api/v1/resources/queues` |
| `GET` | `/api/v1/resources/queues/:queue` |
| `GET` | `/api/v1/resources/queues/:queue/depth` |
| `GET` | `/api/v1/resources/tasks` |
| `GET` | `/api/v1/status/analytics` |
| `GET` | `/api/v1/status/queues` |
| `GET` | `/api/v1/status/queues/:queue` |
| `GET` | `/api/v1/traces/:partitionId/:transactionId` |
| `GET` | `/api/v1/traces/by-name/:traceName` |
| `GET` | `/api/v1/traces/names` |
| `GET` | `/auth/login` |
| `POST` | `/auth/logout` |
| `GET` | `/auth/me` |
| `GET` | `/health` |

### gated (streams)

| Method | Path |
| --- | --- |
| `POST` | `/streams/v1/cycle` |
| `POST` | `/streams/v1/queries` |
| `POST` | `/streams/v1/state/get` |

### gated (traces)

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/traces` |

### gated (kv)

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/kv` |
| `DELETE` | `/api/v1/kv/:ns/*key` |
| `GET` | `/api/v1/kv/:ns/*key` |
| `PUT` | `/api/v1/kv/:ns/*key` |

### gated (timers)

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/timers` |
| `GET` | `/api/v1/timers/:queue` |
| `DELETE` | `/api/v1/timers/:queue/*timerKey` |
| `GET` | `/api/v1/timers/:queue/*timerKey` |

### gated (ephemeral)

| Method | Path |
| --- | --- |
| `POST` | `/api/v1/ephemeral/ack` |
| `POST` | `/api/v1/ephemeral/configure` |
| `GET` | `/api/v1/ephemeral/pop` |
| `POST` | `/api/v1/ephemeral/push` |
| `DELETE` | `/api/v1/ephemeral/queue/:queue` |
| `GET` | `/api/v1/ephemeral/queues` |
| `GET` | `/api/v1/ephemeral/queues/:queue/depth` |
| `POST` | `/api/v1/ephemeral/reset` |

### operator

| Method | Path |
| --- | --- |
| `GET` | `/api/v1/analytics/postgres-stats` |
| `GET` | `/api/v1/analytics/system-metrics` |
| `GET` | `/api/v1/analytics/worker-metrics` |
| `GET` | `/api/v1/status` |
| `GET` | `/api/v1/status/buffers` |
| `GET` | `/api/v1/system/maintenance` |
| `POST` | `/api/v1/system/maintenance` |
| `GET` | `/api/v1/system/maintenance/pop` |
| `POST` | `/api/v1/system/maintenance/pop` |
| `GET` | `/metrics/prometheus` |

### blocked

| Method | Path |
| --- | --- |
| `GET` | `/api/v1/pop` |
| `POST` | `/api/v1/stats/refresh` |
| `GET` | `/api/v1/system/ephemeral` |
| `POST` | `/api/v1/system/ephemeral` |
| `GET` | `/api/v1/system/kv-timers` |
| `POST` | `/api/v1/system/kv-timers` |
| `GET` | `/api/v1/system/shared-state` |
| `GET` | `/internal/api/inter-instance/stats` |
| `POST` | `/internal/api/notify` |
| `GET` | `/internal/api/shared-state/stats` |
| `GET` | `/metrics` |
| `GET` | `/status` |

62 of the broker's 84 method + path pairs are reachable with a tenant credential; the rest are operator or blocked surfaces.

## Reading it in practice

- A tenant's normal working set is `produce`, `consume`, `queue admin` and `read`.
  Those four cover the whole documented HTTP API for building on Queen.
- `gated` routes exist on the broker for every tenant and are opened by the plan's
  `features` object, not by the credential's scopes. The kv, ephemeral and streams
  families are double-gated: the broker holds a per-tenant grant of its own behind the
  plan flag ([isolation](/reference/multi-tenant/isolation/)).
- `operator` and `blocked` are the two classes a tenant can never reach. They are
  cell-wide surfaces that the broker does not tenant-scope, which is precisely why the
  proxy exists. [Isolation](/reference/multi-tenant/isolation/) explains what each of
  them would leak.

## Related

- [Credentials and authorization](/reference/multi-tenant/auth/): the matrix of class
  against principal.
- [Quotas and rate limits](/reference/multi-tenant/quotas/): which limits attach to
  which class.
- The broker's own [route table](/reference/http/routes/), with the access level each
  route requires.

Source: https://queenmq.com/reference/multi-tenant/endpoints/index.mdx
