Skip to main content
This guide takes you from an unprotected API to one where every request is checked for a valid MudraID token and the right scope — before it reaches your handlers. The integration is two lines plus a config file. By the end your routes will reject unauthenticated or under-scoped agents automatically, with no auth code in your handlers.

Before you start

  • A MudraID account, with your platform registered (step 1 below).
  • A FastAPI or Starlette application.
  • Python 3.10 or newer.

1. Register your platform

Sign in to the MudraID portal, create a platform, and verify you own its domain (a DNS TXT record). Then define the scopes your routes will require — the permissions you’ll hand out to agents, like items:read and items:write. You’ll get a platform_id, which identifies your platform in the scopes file, and a canonical resource URI. Agents request access tokens for that resource URI, and it becomes the tokens’ audience.

2. Get your scopes file

The portal generates a mudraid_scopes.yaml for your platform. It maps each route to one of three outcomes: a required scope, an open public route, or a hidden skip route.
Drop it in your project root, next to where your app starts.

3. Install the middleware

4. Configure verification and add the middleware

Three values tell the middleware which tokens to accept:
  • MUDRAID_JWKS_URL — required, no default. The /.well-known/jwks.json path on the MudraID environment your platform is registered with; the portal prints it on the credential screen.
  • MUDRAID_EXPECTED_ISSUERS — the issuer your environment’s authorization server advertises at /.well-known/oauth-authorization-server. Agents’ access tokens carry it as iss.
  • expected_audience — your platform’s canonical resource URI. Agents’ access tokens carry it as aud.
With neither MUDRAID_JWKS_URL nor jwks_url= set, the middleware raises ValueError when the ASGI stack is built. It will not boot unconfigured.
Without expected_audience, the middleware expects aud to equal the platform_id in your YAML, and without an issuer setting it expects the legacy issuer mudraid-identity. Those were the claims of native agent tokens, which are retired. Agents’ OAuth access tokens carry the authorization server’s issuer and your resource URI, so set both values above or every agent call fails with WRONG_ISSUER or WRONG_AUDIENCE.
That’s the whole change. Your existing route handlers stay exactly as they are — no decorators, no auth parameters, no per-route checks.

5. Verify the integration before trusting it

Do this before you conclude anything is protected. curl a scope-gated route with no Authorization header:
If your own handler runs instead — a 200, a 201, your own JSON — the middleware is not in the ASGI stack. Installing the package and downloading mudraid_scopes.yaml does not put it there; add_middleware does.No other state produces your handler’s response. Wired with no token is 401, wired with the wrong scope is 403, wired with a path your YAML does not cover is 404, and wired with unreadable YAML is 500. Reaching the handler means nothing was enforced.The portal cannot detect this for you. Verified means your domain was proven by a DNS TXT record, and Active means the surface may use the API. Both are set the moment DNS verification succeeds. Neither means MudraID has observed a single enforced request.
Once that check passes, the public route should still be open:
A registered agent calling the scoped route with a valid, in-scope token gets through to your handler. That’s the loop working.

What just happened

For every incoming request, the middleware now:
  1. Matches the method and path against your YAML.
  2. Lets public routes through untouched.
  3. Reads the Authorization: Bearer token.
  4. Verifies its signature, issuer, audience, and timing against MudraID’s published keys — local verification, no per-request callback.
  5. Checks the route’s required scope is present in the token.
  6. Forwards to your handler, or returns a structured {"error_code", "message"} error.
Your code only ever runs for requests that are authenticated and in scope.

Troubleshooting

Full table: Interpret verification error codes.

Going further: live enforcement

Offline verification checks the token and the route’s scope. To have MudraID decide each sensitive action against current authority, containment and policy, register an enforcement adapter and use the middleware’s V2 mode (MCP Streamable HTTP servers) — see V2 mode.

Next steps

Define scopes

Design the permissions your API exposes.

Manage the scopes lifecycle

How changes roll out safely.

Error responses

The stable error_code contract.

Survive key rotation

Why rotation needs no action from you.