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

# Authenticated APIs

> Use the deterministic session model for APIs that publish protected request surfaces.

<Warning>
  **Closed beta.** Authenticated APIs are not yet generally available. The surface described here is live in production, but access is gated to a small group of design partners while the build pipeline matures. If you want to try it, reach out at [kaan@peel.sh](mailto:kaan@peel.sh). Do not build production integrations against it until it exits beta.
</Warning>

Authenticated runtime support is intentionally narrow. Peel exposes it only when build time found a concrete protected request surface and published it as explicit endpoints.

This page assumes you already know the difference between **host auth** (how you call Peel) and **target-site auth** (`session_required`). If not, start with [Authentication](/getting-started/authentication).

<Warning>
  This is not generic login automation. Peel does not support arbitrary browser login flows, page-by-page navigation, or open-ended authenticated browsing at runtime.
</Warning>

## The published contract

API detail responses expose the boundary directly:

* `api.auth_mode`
* `api.auth`
* `api.requires_session`
* `api.user_input_prompt`
* Per endpoint: `endpoint_type` and `auth_requirement`

```json theme={null}
{
  "auth_mode": "managed_session_only",
  "auth": {
    "capability_summary": "managed_session_only",
    "families": [
      {
        "session_tag": "orders_session",
        "login_endpoints": ["login"],
        "protected_endpoints": ["get_orders"],
        "verification_status": "structurally_verified",
        "user_input_required": false
      }
    ],
    "requires_managed_session": true,
    "user_input_required": false
  },
  "requires_session": true,
  "endpoints": [
    {
      "endpoint_name": "login",
      "endpoint_type": "login",
      "auth_requirement": "public"
    },
    {
      "endpoint_name": "get_orders",
      "endpoint_type": "data",
      "auth_requirement": "session_required"
    }
  ]
}
```

`endpoint_type: "login"` creates the session. `auth_requirement: "session_required"` marks protected calls that need that session.

`auth_mode` is a derived capability summary with three values:

* `public` — no session required.
* `mixed_public_and_managed_session` — some endpoints are public, others need a session.
* `managed_session_only` — every endpoint on the API is session-gated.

Use `api.auth` when you need the compiled family view: which login endpoint pairs with which protected endpoints, whether user input is still required, and how much verification the compiled flow has.

`verification_status` on each family has three possible values:

* **`unverified`** — Peel compiled the login flow structurally but has not exercised it. Runtime calls may fail for reasons the build did not catch.
* **`structurally_verified`** — the compiled login and protected endpoints line up correctly by shape, including selectors, request bodies, and expected cookies, but no real credentials have been replayed against the target. Treat this as worth testing against a real account.
* **`credential_verified`** — the build replayed the full flow with real credentials at build time, and the compiled endpoints returned the expected shape. This is the highest-confidence tier.

If a protected build pauses for missing credentials or disambiguation, resume it through `/v1/apis/{api_id}/respond` over REST or `respond_to_api_input` over MCP before retrying runtime calls.

## REST flow

```bash theme={null}
curl -X POST "$PEEL_API_BASE/v1/apis/$API_ID/endpoints/login:call" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "you@example.com", "password": "your-password" }'
```

```json theme={null}
{
  "status": "success",
  "status_code": 200,
  "data": {},
  "initiates_session": true,
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "encryption_key": "gAAAAABk..."
}
```

For protected REST endpoints, send session credentials with headers:

```bash theme={null}
curl -X POST "$PEEL_API_BASE/v1/apis/$API_ID/endpoints/get_orders:call" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-Session-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -H "X-Encryption-Key: gAAAAABk..." \
  -H "Content-Type: application/json" \
  -d '{ "status": "shipped", "limit": 5 }'
```

Headers are the canonical transport for session credentials. Body fields work as a fallback. See [Authentication](/getting-started/authentication#rest-session-credentials) for precedence rules.

If either credential is missing, the call fails before target transport execution.

## MCP shape

`call_endpoint` is invoked over JSON-RPC at `POST https://api.peel.sh/mcp`. Session credentials live at the top of `arguments` alongside `api_id` and `endpoint_name`. The endpoint's own params go under a nested `params` object:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "call_endpoint",
    "arguments": {
      "api_id": "550e8400-e29b-41d4-a716-446655440000",
      "endpoint_name": "get_orders",
      "session_id": "550e8400-...",
      "encryption_key": "gAAAAABk...",
      "params": {
        "status": "shipped",
        "limit": 5
      }
    }
  }
}
```

## What this means operationally

* Host auth gets you into Peel. It does not create a target-site session.
* The login endpoint creates the target-site session.
* Protected behavior must already be compiled into explicit endpoints.
* Not every site can be expressed this way.

For the broader runtime boundary, see [Deterministic Runtime](/concepts/deterministic-runtime). For host-side auth, see [Authentication](/getting-started/authentication).
