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

# Define scopes and protect routes

> Design the permissions your API exposes, and map each route to one.

The middleware enforces exactly what's in your `mudraid_scopes.yaml`. Designing that file well is the main work of integrating as a platform — and it's a design task, not just config. This guide walks through it.

## Start from the permissions, not the routes

Before mapping routes, decide what an agent should be *able to do* on your API. Those are your scopes. Keep them coarse enough to be meaningful and fine enough to be useful:

* `items:read`, `items:write`
* `orders:read`, `orders:write`, `orders:cancel`

Use `resource:action`. The names are visible to agent owners when they request access, so make them self-explanatory.

## Map each route to one of three choices

For every route, pick exactly one:

| Choice          | Meaning                           | Use for                                    |
| --------------- | --------------------------------- | ------------------------------------------ |
| `scope: <name>` | Token must carry this scope       | Anything that touches data or actions      |
| `public: true`  | No token required                 | Health checks, status, open metadata       |
| `skip: true`    | Returns 404 — invisible to agents | Internal/admin routes agents shouldn't see |

```yaml theme={null}
platform_id: 4f8e9c1d-2b4f-5e6a-7b8c-9d0e1f2a3b4c
version: 1
routes:
  - method: GET
    path: /health
    public: true
  - method: GET
    path: /api/v1/items
    scope: items:read
  - method: GET
    path: /api/v1/items/{item_id}
    scope: items:read
  - method: POST
    path: /api/v1/items
    scope: items:write
```

## Path parameters

Use brace syntax for variable segments. The middleware matches the shape, not the value:

```yaml theme={null}
  - method: GET
    path: /api/v1/items/{item_id}
    scope: items:read
```

So `/api/v1/items/42` and `/api/v1/items/abc` both match this one rule.

## Routes with no rule return 404

A route you don't list behaves exactly like `skip: true` — it returns 404. A hidden route and a non-existent route are indistinguishable to a caller, on purpose, so agents can't probe your surface. The flip side: if you forget to list a real route, agents will get 404s on it. Listing routes is mandatory, not optional.

## Scopes are flat — no implicit hierarchy

`items:write` does **not** grant `items:read`. If a route needs both, require both and grant both. There's no "higher" scope that quietly unlocks "lower" ones. It's slightly more verbose, and it eliminates a whole class of accidental over-permissioning.

## Common mistakes to avoid

* **Forgetting a route** — it 404s. List every route an agent should reach.
* **Assuming hierarchy** — grant each scope explicitly.
* **One mega-scope** — `api:all` defeats the point. Scope by resource and action.
* **Hand-editing in production** — the portal is the source of truth; see the lifecycle guide.

## Related

* [Platforms and scopes](/guides/concepts/platforms-scopes)
* [Manage the scopes lifecycle](/guides/platform-operator/scopes-lifecycle)
