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

# Let your agent call your app

> Call your own app's routes with your floo API key or the floo MCP, as yourself, with no app API key.

Send your floo API key as a bearer token to your app's URL. floo's gateway checks that you are a member of the app, removes the key, and passes your identity to the app as it does for your browser. Anyone with access to the app can call all of its routes this way, including its app API key routes.

```bash theme={null}
curl -H "Authorization: Bearer $FLOO_KEY" https://my-app-dev.getfloo.app/api/notes
```

Your agent uses the key it already signed in with, so it can check its own deploy, read data, and call your app's endpoints without an [app API key](https://getfloo.com/docs/guides/app-api-keys.md). App API keys stay the way to give access to a program that is not you.

## What the app receives

The app gets the same identity headers as a signed-in browser request, so it needs no change:

```text theme={null}
X-Floo-Auth-Method: session
X-Floo-User-Email:  jane@acme.com
X-Floo-User-Id:     01HQK4...
X-Floo-User-Name:   Jane Doe
X-Floo-User-Role:   member
```

`X-Floo-User-Role` is your app role. The `Authorization` header never reaches the app.

## Who can call which route

| Route `access` | With your floo API key |
| - | - |
| `accounts` | Admitted when you are a member of the app, the same rule as [App sign-in](https://getfloo.com/docs/guides/app-auth.md). |
| `api_key` | Admitted when you are a member of the app, as if the key held every scope. The app sees user headers with your app role, not app API key headers, so it can decide what you may do. |
| `public` | The key is removed and the request arrives anonymous, as from any browser. |

floo checks your membership and the key on every request, so removing a member or revoking a key stops the next call. A read-scoped floo API key can send `GET`, `HEAD`, and `OPTIONS`; other methods need write scope. An org that requires SSO accepts browser sign-in only, and refuses floo API keys with `SSO_REQUIRED`. WebSocket upgrades still need browser sign-in.

A refusal comes back as JSON naming the fix:

```json theme={null}
{
  "error": "access denied",
  "code": "ACCESS_DENIED",
  "message": "jane@acme.com is not a member of app my-app. An app admin can run `floo apps invite jane@acme.com --app my-app`."
}
```

Send the key only in the `Authorization` header. floo removes it there; a key in a query string or a body reaches the app.

## From the floo MCP

With the [floo MCP server](https://getfloo.com/docs/guides/mcp.md) connected (`https://api.getfloo.com/mcp`), your agent gets three tools that make the same calls:

| Tool | Does |
| - | - |
| `search_app_api` | Reads the app's OpenAPI spec and returns the operations matching a keyword |
| `read_app_api` | Sends `GET` or `HEAD` |
| `write_app_api` | Sends `POST`, `PUT`, `PATCH`, or `DELETE` |

Each takes `app_id` (from `list_apps`) and `environment`: `dev` to build and test, `prod` for live data, or a preview's slug. The environment is required, so a call never reaches prod by accident, and every result names the environment it called. An environment that is not deployed returns `ENVIRONMENT_NOT_LIVE` with the app's live environments. `path` is an app path such as `/api/notes`; full URLs, `..` segments, and `/__floo/*` paths are refused. floo drops any `Authorization`, `Cookie`, `Accept-Encoding`, or `X-Floo-*` header the agent passes, so the call always runs as you.

Responses return the app's status, content type, and body, cut at 256 KB. A call with no answer in 25 seconds fails with `APP_TIMEOUT`. floo keeps request and response bodies out of its logs and error reports.

`read_app_api` is marked read-only and `write_app_api` destructive, so your MCP client can approve reads on its own and ask you before writes.

## Expose an OpenAPI spec

`search_app_api` reads `/openapi.json`, then `/api/openapi.json`, or the `spec_path` the agent passes. Each match lists its method, path, `operationId`, summary, parameters, and request body, with the spec's local `$ref`s filled in, so the agent can build the call without reading your code. The spec must be JSON and at most 5 MB. A result holds about 256 KB at most; when a big spec doesn't fit, the agent is told to narrow its query. With no spec, it says why for each path (its HTTP status, too large, or not an OpenAPI document) and tells the agent to pass `spec_path` or call the paths it already knows.

> [accordion] FastAPI
>
> Built in: FastAPI serves `/openapi.json` unless you set `openapi_url=None`.

> [accordion] Next.js (floo starter)
>
> Apps from `floo projects create` already serve `/api/openapi.json`, generated from their Zod validators. Describe each new endpoint in `app/api/<name>/openapi.ts`; the starter's tests fail when a handler is undocumented.

> [accordion] Express
>
> ```js theme={null}
> import swaggerJsdoc from "swagger-jsdoc";
>
> const spec = swaggerJsdoc({
>   definition: { openapi: "3.1.0", info: { title: "my-app", version: "1" } },
>   apis: ["./routes/*.js"],
> });
> app.get("/openapi.json", (req, res) => res.json(spec));
> ```
>
> `swagger-jsdoc` builds the spec from `@openapi` comments on your route handlers.

> [accordion] Django REST framework
>
> ```python theme={null}
> # settings.py
> INSTALLED_APPS += ["drf_spectacular"]
> REST_FRAMEWORK = {"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema"}
>
> # urls.py
> from drf_spectacular.views import SpectacularAPIView
>
> urlpatterns += [path("openapi.json", SpectacularAPIView.as_view())]
> ```

> [accordion] Rails and other stacks
>
> Commit an OpenAPI 3 document and serve it as JSON at `/openapi.json`, or tell your agent its path. In Rails:
>
> ```ruby theme={null}
> # config/routes.rb
> get "/openapi.json", to: proc {
>   [200, { "content-type" => "application/json" }, [Rails.root.join("openapi.json").read]]
> }
> ```

A spec route behind `accounts` or `api_key` access is read as you, like any other call.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.