> For the complete documentation index, see [llms.txt](https://build.restless.ai/llms.txt).

These are machine-readable instructions for using the Restless API.

Every endpoint, every parameter, every auth requirement - written for an agent that will copy-paste commands, not a human skimming for nouns.

# MCP Server

There's an MCP server at `https://build.restless.ai/mcp` exposing tools like `search_endpoints`, `get_endpoint`, and operation lookup. When you need specifics about an endpoint - parameters, status codes, examples - query the MCP server first; do not guess.

If the user has not yet connected the MCP server in their client, they can install it from the docs at `https://build.restless.ai`.

# Getting Started

**Restless** is a toolkit you install on your API to get it ready for agents. It watches every call in production and turns your spec into docs and an MCP server, so agents can find what they need — and when one fails, Restless has the data to tell it why.

```
npx restless init
```

# Installation

## Use with Claude

Connect Restless to Claude Code, Claude Desktop, or Claude.ai over MCP, then let Claude search endpoints and make calls for you.

### Claude Code (CLI)

Run this from your terminal - Claude Code picks it up immediately.

```bash
claude mcp add --transport http restless-docs https://build.restless.ai/mcp
```

### Claude Desktop

Add this entry under `mcpServers` in `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows), then restart Claude Desktop.

```json
{
  "mcpServers": {
    "restless-docs": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://build.restless.ai/mcp"
      ]
    }
  }
}
```

### Claude.ai (Web)

In Claude.ai, open Settings → Connectors → Add custom connector, then paste this URL. Available on paid plans.

```
https://build.restless.ai/mcp
```

Open Claude.ai: https://claude.ai/customize/connectors?modal=add-custom-connector

### Or paste this prompt

I want to use the Restless API.

If you support MCP (Model Context Protocol), connect to this server so you can search endpoints and make calls directly:
https://build.restless.ai/mcp

The full machine-readable documentation index is at https://build.restless.ai/llms.txt.
The complete OpenAPI spec is at https://build.restless.ai/openapi.yaml.
Read those, then help me make requests against the API.

## Use with ChatGPT

Use Restless from ChatGPT and the Codex CLI over MCP, so it can browse the API and write calls without you pasting docs.

### Codex (CLI)

Run this from your terminal - Codex (OpenAI's CLI) registers the MCP server immediately.

```bash
codex mcp add restless-docs --url https://build.restless.ai/mcp
```

### ChatGPT (Web)

In ChatGPT, open Settings → Connectors → Add, then paste this URL. Requires a paid plan with developer/connector access enabled.

```
https://build.restless.ai/mcp
```

Open ChatGPT: https://chatgpt.com/

### Or paste this prompt

I want to use the Restless API.

If you support MCP (Model Context Protocol), connect to this server so you can search endpoints and make calls directly:
https://build.restless.ai/mcp

The full machine-readable documentation index is at https://build.restless.ai/llms.txt.
The complete OpenAPI spec is at https://build.restless.ai/openapi.yaml.
Read those, then help me make requests against the API.

## CLI

### Install

npx restless init

### Authentication

Authorizing a machine opens a browser once (`npx restless login`), after which the session is reused for 24 hours. `npx restless key` writes your project's `RESTLESS_KEY` straight to `.env`. Name your agent non-interactively with `RESTLESS_AGENT=cursor` (or `--agent cursor`) so it gets recorded on the project.

### Machine-readable output

Pass `--json` to `update` commands (e.g. `npx restless update --status --json`) for parseable output.

### Common commands

A few common commands. Run `npx restless --help` to list every command.

- `npx restless init` - Scan the repo for supported APIs and set up spec + SDK wiring; inside a coding agent it prints instructions for the agent to follow.
- `npx restless key` - Register the project and write RESTLESS_KEY to .env (safe to re-run; re-adopts an existing project).
- `npx restless register --oas <file>` - Record an OpenAPI spec in .restless/settings.json (rejects localhost servers).
- `npx restless verify --url <url>` - Send one request and confirm the SDK saw it, the log landed, and no owner-id placeholder remains.
- `npx restless update --status --json` - Read-only check: reports specChanged and whether the dashboard is behind; writes nothing.
- `npx restless update --refresh --json` - Re-run the spec's source, then push spec and settings.

### Agent setup prompt

Run `npx restless init` to set up API success tracking. Inside a coding agent it prints setup instructions for you to carry out (reading routes, writing the OpenAPI spec, wiring middleware) rather than driving your repo itself. Use `npx restless guide oas` and `npx restless guide sdk` to get the spec-writing and SDK-wiring instructions. If init misjudges the stack, re-run with `RESTLESS_SKIP_STACK_CHECK=1 npx restless init`. Run `npx restless --help` and `npx restless <cmd> --help` to discover commands and flags. For changes after setup use `npx restless update` (not init): `--status --json` to check without writing, `--refresh --json` to re-run the spec source and push, `--oas <file|url>` to point at a different spec, `--sync` to push settings, and `--project <id>` to pick one API in a multi-API repo. Identify yourself with `RESTLESS_AGENT=<tool>` or `--agent <tool>`.

See the full README for details: https://build.restless.ai/installs/cli/full.md

### Package details

- Package: `restless` (v0.7.0)
- Last published: 2026-08-17
- README: https://build.restless.ai/installs/cli/full.md

## Node.js

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official Node.js SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for Node.js is fetch.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## Python

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official Python SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for Python is requests.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## Ruby

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official Ruby SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for Ruby is Net::HTTP.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## PHP

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official PHP SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for PHP is cURL.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## Go

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official Go SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for Go is net/http.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## React

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official React SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for React is fetch.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## Java

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official Java SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for Java is java.net.http.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## C#

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official C# SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for C# is HttpClient.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## Rust

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no official Rust SDK, so use whatever HTTP client and conventions this codebase already uses for API calls. If there isn't an established pattern, a common choice for Rust is reqwest.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

## Any other language

### Agent setup prompt

We want to integrate Restless into this codebase via API.

There's no SDK, so use whatever HTTP client and conventions this codebase already uses for API calls.

Authentication: send a bearer token in the `Authorization` header (`Authorization: Bearer <token>`).

The base URL is `https://app.restless.ai`.

You can see the available endpoints at https://build.restless.ai/llms.txt, or read the full OpenAPI spec at https://build.restless.ai/openapi.yaml. Adapt the auth and endpoints to your use case as needed.

# Endpoints

Base URL: `https://app.restless.ai`

- Identity behind the API key - `GET https://app.restless.ai/api/v1/me`
- List accessible projects - `GET https://app.restless.ai/api/v1/projects`
- Get one project - `GET https://app.restless.ai/api/v1/projects/{slug}`
- Search request logs - `GET https://app.restless.ai/api/v1/projects/{slug}/logs`
- Get one log (audited) - `GET https://app.restless.ai/api/v1/projects/{slug}/logs/{logId}`
- List end-users (or at-risk users) - `GET https://app.restless.ai/api/v1/projects/{slug}/users`
- Top endpoints (optionally with error rates) - `GET https://app.restless.ai/api/v1/projects/{slug}/endpoints`
- Time-series aggregation (or filter values) - `GET https://app.restless.ai/api/v1/projects/{slug}/metrics`
- Get docs portal settings - `GET https://app.restless.ai/api/v1/projects/{slug}/docs`
- Update docs portal settings - `PATCH https://app.restless.ai/api/v1/projects/{slug}/docs`
- Get docs content - `GET https://app.restless.ai/api/v1/projects/{slug}/content`
- Update docs content - `PATCH https://app.restless.ai/api/v1/projects/{slug}/content`
- List members + invites - `GET https://app.restless.ai/api/v1/projects/{slug}/members`
- Invite a member - `POST https://app.restless.ai/api/v1/projects/{slug}/members`
- Remove a member or revoke an invite - `DELETE https://app.restless.ai/api/v1/projects/{slug}/members`
- List use cases - `GET https://app.restless.ai/api/v1/projects/{slug}/usecases`
- Create a use case - `POST https://app.restless.ai/api/v1/projects/{slug}/usecases`
- Update a use case - `PATCH https://app.restless.ai/api/v1/projects/{slug}/usecases/{usecaseSlug}`
- Delete a use case - `DELETE https://app.restless.ai/api/v1/projects/{slug}/usecases/{usecaseSlug}`
- List context items - `GET https://app.restless.ai/api/v1/projects/{slug}/context`
- Create a context item - `POST https://app.restless.ai/api/v1/projects/{slug}/context`
- Update a context item - `PATCH https://app.restless.ai/api/v1/projects/{slug}/context/{contextSlug}`
- Delete a context item - `DELETE https://app.restless.ai/api/v1/projects/{slug}/context/{contextSlug}`
- List recovery messages - `GET https://app.restless.ai/api/v1/projects/{slug}/recovery`
- Create/update a recovery message - `POST https://app.restless.ai/api/v1/projects/{slug}/recovery`
- Delete a recovery message - `DELETE https://app.restless.ai/api/v1/projects/{slug}/recovery`
- List data sources - `GET https://app.restless.ai/api/v1/projects/{slug}/data-sources`
- Connect a GitHub repo - `POST https://app.restless.ai/api/v1/projects/{slug}/data-sources`
- Update a data source - `PATCH https://app.restless.ai/api/v1/projects/{slug}/data-sources`
- Disconnect a data source - `DELETE https://app.restless.ai/api/v1/projects/{slug}/data-sources`
- Re-ingest a documentation source - `POST https://app.restless.ai/api/v1/projects/{slug}/data-sources/{sourceId}/sync`
- Get MCP tool catalog + config - `GET https://app.restless.ai/api/v1/projects/{slug}/mcp-tools`
- Update MCP tool catalog config - `PATCH https://app.restless.ai/api/v1/projects/{slug}/mcp-tools`
- List API feedback from agents - `GET https://app.restless.ai/api/v1/projects/{slug}/feedback`
- Triage one piece of API feedback - `PATCH https://app.restless.ai/api/v1/projects/{slug}/feedback/{feedbackId}`

## Full OpenAPI specification

Complete spec for every endpoint above (internal operations removed):

```yaml
openapi: 3.1.0
info:
  title: Restless Public API
  version: 1.0.0
  description: >-
    Personal-API-key authenticated access to everything your Restless user can reach. Pass your key
    as `Authorization: Bearer rk_live_...`. Read-only keys are refused on writes.
servers:
  - url: https://app.restless.ai
security:
  - apiKey: []
tags:
  - name: Account
    description: The identity and access behind the API key.
  - name: Projects
    description: The projects this key can reach.
  - name: Logs
    description: Search captured API requests, or fetch one in full.
  - name: Users
    description: The end-users calling the API, including at-risk ones.
  - name: Metrics
    description: Time-series and top-endpoint aggregations over captured traffic.
  - name: Docs
    description: 'The public docs portal: its settings and its written content.'
  - name: Use cases
    description: Owner-curated task walkthroughs shown on the docs portal.
  - name: Context
    description: Extra knowledge the docs AI and MCP server answer from.
  - name: Recovery
    description: Next-step hints the SDK returns to agents that hit a known error.
  - name: Data sources
    description: Connected repos that feed docs and SDK content.
  - name: MCP
    description: The tool catalog the project's MCP server exposes.
  - name: Feedback
    description: Notes agents left about what confused or blocked them.
  - name: Members
    description: Who can reach the project, plus pending invites.
components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: A personal API key (starts with rk_live_).
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
  responses:
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: No such project/resource you can access.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
paths:
  /api/v1/me:
    get:
      tags:
        - Account
      summary: Identity behind the API key
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/projects:
    get:
      tags:
        - Projects
      summary: List accessible projects
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/projects/{slug}:
    get:
      tags:
        - Projects
      summary: Get one project
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/projects/{slug}/logs:
    get:
      tags:
        - Logs
      summary: Search request logs
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: status
          in: query
          schema:
            type: integer
        - name: method
          in: query
          schema:
            type: string
        - name: urlContains
          in: query
          schema:
            type: string
        - name: groupEmail
          in: query
          schema:
            type: string
        - name: since
          in: query
          schema:
            type: string
            format: date-time
        - name: until
          in: query
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/logs/{logId}:
    get:
      tags:
        - Logs
      summary: Get one log (audited)
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: logId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/projects/{slug}/users:
    get:
      tags:
        - Users
      summary: List end-users (or at-risk users)
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: limit
          in: query
          schema:
            type: integer
        - name: atRisk
          in: query
          schema:
            type: boolean
        - name: threshold
          in: query
          schema:
            type: number
        - name: minRequests
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/endpoints:
    get:
      tags:
        - Metrics
      summary: Top endpoints (optionally with error rates)
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: since
          in: query
          schema:
            type: string
            format: date-time
        - name: until
          in: query
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          schema:
            type: integer
        - name: withErrors
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/metrics:
    get:
      tags:
        - Metrics
      summary: Time-series aggregation (or filter values)
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: groupBy
          in: query
          schema:
            type: string
            enum:
              - period
              - status
              - user
        - name: since
          in: query
          schema:
            type: string
            format: date-time
        - name: until
          in: query
          schema:
            type: string
            format: date-time
        - name: filters
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/docs:
    get:
      tags:
        - Docs
      summary: Get docs portal settings
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    patch:
      tags:
        - Docs
      summary: Update docs portal settings
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: OK
        '403':
          description: Read-only key.
  /api/v1/projects/{slug}/content:
    get:
      tags:
        - Docs
      summary: Get docs content
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    patch:
      tags:
        - Docs
      summary: Update docs content
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/members:
    get:
      tags:
        - Members
      summary: List members + invites
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    post:
      tags:
        - Members
      summary: Invite a member
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
              required:
                - email
      responses:
        '200':
          description: OK
    delete:
      tags:
        - Members
      summary: Remove a member or revoke an invite
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: memberId
          in: query
          schema:
            type: string
        - name: inviteId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/usecases:
    get:
      tags:
        - Use cases
      summary: List use cases
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    post:
      tags:
        - Use cases
      summary: Create a use case
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                  maxLength: 120
                  description: Max 120 characters.
                description:
                  type: string
                icon:
                  type: string
                content:
                  type: string
                  maxLength: 16000
                  description: Max 16000 characters.
                docsBody:
                  type: string
                  maxLength: 16000
                  description: Max 16000 characters.
                public:
                  type: boolean
                asTool:
                  type: boolean
              required:
                - title
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/usecases/{usecaseSlug}:
    patch:
      tags:
        - Use cases
      summary: Update a use case
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: usecaseSlug
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                description:
                  type: string
                icon:
                  type: string
                content:
                  type: string
                  maxLength: 16000
                  description: Max 16000 characters.
                docsBody:
                  type: string
                  maxLength: 16000
                  description: Max 16000 characters.
                public:
                  type: boolean
                asTool:
                  type: boolean
      responses:
        '200':
          description: OK
    delete:
      tags:
        - Use cases
      summary: Delete a use case
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: usecaseSlug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/context:
    get:
      tags:
        - Context
      summary: List context items
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    post:
      tags:
        - Context
      summary: Create a context item
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                  maxLength: 120
                  description: Max 120 characters.
                content:
                  type: string
                  maxLength: 8000
                  description: >-
                    Max 8000 characters, so the item embeds as a single retrieval chunk. Longer
                    material goes in several context items.
                public:
                  type: boolean
              required:
                - title
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/context/{contextSlug}:
    patch:
      tags:
        - Context
      summary: Update a context item
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: contextSlug
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                content:
                  type: string
                  maxLength: 8000
                  description: >-
                    Max 8000 characters, so the item embeds as a single retrieval chunk. Longer
                    material goes in several context items.
                public:
                  type: boolean
                showInAgent:
                  type: boolean
      responses:
        '200':
          description: OK
    delete:
      tags:
        - Context
      summary: Delete a context item
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: contextSlug
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/recovery:
    get:
      tags:
        - Recovery
      summary: List recovery messages
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    post:
      tags:
        - Recovery
      summary: Create/update a recovery message
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fingerprintKey:
                  type: string
                message:
                  type: string
                strategy:
                  type: string
              required:
                - fingerprintKey
                - message
      responses:
        '200':
          description: OK
    delete:
      tags:
        - Recovery
      summary: Delete a recovery message
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: fingerprintKey
          in: query
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/data-sources:
    get:
      tags:
        - Data sources
      summary: List data sources
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    post:
      tags:
        - Data sources
      summary: Connect a GitHub repo
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                installationId:
                  type: integer
                owner:
                  type: string
                repo:
                  type: string
                branch:
                  type: string
                category:
                  type: string
                  enum:
                    - documentation
                    - sdk
                provider:
                  type: string
                siteUrl:
                  type: string
                  description: >-
                    Public URL of the live docs site this repo publishes to. Shown as a
                    Documentation link in the public portal header.
              required:
                - installationId
                - owner
                - repo
                - branch
                - category
      responses:
        '200':
          description: OK
    patch:
      tags:
        - Data sources
      summary: Update a data source
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: sourceId
          in: query
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                siteUrl:
                  type: string
                  description: >-
                    Public URL of the live docs site. Empty clears it and removes the portal header
                    link.
              required:
                - siteUrl
      responses:
        '200':
          description: OK
    delete:
      tags:
        - Data sources
      summary: Disconnect a data source
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: sourceId
          in: query
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/data-sources/{sourceId}/sync:
    post:
      tags:
        - Data sources
      summary: Re-ingest a documentation source
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: sourceId
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/mcp-tools:
    get:
      tags:
        - MCP
      summary: Get MCP tool catalog + config
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      responses:
        '200':
          description: OK
    patch:
      tags:
        - MCP
      summary: Update MCP tool catalog config
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: OK
  /api/v1/projects/{slug}/feedback:
    get:
      tags:
        - Feedback
      summary: List API feedback from agents
      description: >-
        Notes captured by the docs MCP server's `send_feedback` tool: where the API or its MCP
        surface confused, blocked, or misled a machine consumer. Newest first. `counts` covers the
        whole project, not the filtered slice.
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: status
          in: query
          schema:
            type: string
            enum:
              - active
              - archived
          description: Omit to return both active and archived.
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 500
      responses:
        '200':
          description: OK
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/projects/{slug}/feedback/{feedbackId}:
    patch:
      tags:
        - Feedback
      summary: Triage one piece of API feedback
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Project slug.
        - name: feedbackId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                  enum:
                    - active
                    - archived
              required:
                - status
      responses:
        '200':
          description: OK
        '403':
          description: Read-only key.
        '404':
          $ref: '#/components/responses/NotFound'
```

# Use cases

This is a curated list of things people can do with this API.

## Update project use cases

Review existing use cases for a project and update them, or create new ones.

Manage the use cases published for a project. Start by listing what already exists, then edit any entry in place or add a fresh one when a capability is missing.

Reach for this when a project's documented use cases have drifted from the current API, or when you want to seed a project with example content and refine it over time.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. List the current use cases for the project with `GET /api/v1/projects/{slug}/usecases`. Note the `usecaseSlug` of each entry.
4. To update an existing use case in place, send the revised fields to `PATCH /api/v1/projects/{slug}/usecases/{usecaseSlug}`. It accepts `title`, `description`, `icon`, `content`, `docsBody`, `public`, and `asTool`, and leaves anything you omit untouched.
5. To add a new use case, create it with `POST /api/v1/projects/{slug}/usecases`. It accepts the same fields as the update, so a complete use case can be created in one call. Only `title` is required, and `public` and `asTool` both default to true unless you pass `false`.
6. Note what each body field is for, since three of them read like descriptions and are not interchangeable. `description` is the one-line excerpt on the card. `docsBody` is the prose write-up shown on the public docs, and is paired with `public`. `content` is the step-by-step, agent-facing walkthrough returned by the MCP tool, names real endpoints, and is paired with `asTool`.
7. Re-run `GET /api/v1/projects/{slug}/usecases` to confirm the changes landed.

## Update the getting started page

Review and update the project's getting started documentation page.

The Getting Started page is the first thing a developer reads, and it goes stale faster than the rest of the docs because it describes the setup path rather than the API surface.

This reads the page as it stands today, agrees the changes with you, and writes the revision back. Edits are field by field, so revising the setup copy leaves the authentication section untouched.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. Read the current docs content with `GET /api/v1/projects/{slug}/content`. The Getting Started page is the `installation` field; `authentication` holds the auth section shown alongside it.
4. Show the user the existing copy and agree on what to change. Draft the replacement as Markdown.
5. Apply the change with `PATCH /api/v1/projects/{slug}/content`, sending only the fields you are changing (for example `{"installation": "..."}`). Anything you omit is left alone.
6. Re-run `GET /api/v1/projects/{slug}/content` to confirm the new copy is stored.

## Triage a spike in failed requests

Find what is behind a jump in errors and read the request that proves it.

When error volume jumps, the hard part is not noticing it, it is finding the one request that explains it. This walks from the shape of the spike down to a single failing exchange you can read end to end.

Reach for this when someone reports that things started breaking and you need to say what broke, where, and for whom, rather than just confirming that something did.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. Establish the shape of the spike with `GET /api/v1/projects/{slug}/metrics`, passing `groupBy=status` plus `since` and `until` to bracket the window the user is asking about.
4. Find where the errors are concentrated with `GET /api/v1/projects/{slug}/endpoints`, passing `withErrors=true` over the same window. This ranks endpoints by volume and reports their error rates.
5. Pull the failing requests themselves with `GET /api/v1/projects/{slug}/logs`, filtering on `status` and, once step 4 names an endpoint, `urlContains`.
6. Open one representative failure with `GET /api/v1/projects/{slug}/logs/{logId}` for the full request and response, then explain the failure from that record rather than from the aggregate.

## Find customers about to churn on errors

Surface the end-users whose error rate is climbing, then read what is failing for them.

Aggregate error rates hide the customers who are actually having a bad time. This finds the end-users whose failure rate stands out, then reads their traffic so you can tell a broken integration from a broken endpoint.

Reach for this on a regular sweep, or before a renewal conversation, when you want the list of accounts worth contacting and a specific reason for each one.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. List the users whose error rate is above the line with `GET /api/v1/projects/{slug}/users`, passing `atRisk=true`. Tune `threshold` (a percentage) and `minRequests` so a user with two total requests does not outrank a heavy user sitting at 30 percent.
4. For each user worth chasing, pull their recent failures with `GET /api/v1/projects/{slug}/logs`, passing their address as `groupEmail` and narrowing with `status`.
5. Open the clearest example with `GET /api/v1/projects/{slug}/logs/{logId}` and work out whether the fault is theirs (a malformed request, the wrong credential) or yours.
6. Report back per user: what they are calling, what is failing, and which of those two it is.

## Turn agent feedback into a docs fix

Read what confused a machine consumer of the API, fix the docs, then close the note out.

Agents reading an API leave notes when something confuses or blocks them. Those notes are the most direct signal you get about where the documentation is wrong, and they pile up unless someone works the queue.

This reads the open notes, sorts them into corrections to existing copy and knowledge that was never written down, applies each one, and archives what has been handled so the queue keeps reflecting real remaining work.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. Read the open notes with `GET /api/v1/projects/{slug}/feedback`, passing `status=active`. These are captured by the docs MCP server's `send_feedback` tool, newest first.
4. Sort them. A note about documentation that is missing or wrong is a content fix. A note about knowledge the docs never covered is a new context item.
5. For a content fix, read the current copy with `GET /api/v1/projects/{slug}/content` and apply the correction with `PATCH /api/v1/projects/{slug}/content`.
6. For missing knowledge, add it with `POST /api/v1/projects/{slug}/context`.
7. Close each note you acted on with `PATCH /api/v1/projects/{slug}/feedback/{feedbackId}`, setting `status` to `archived`. Leave anything you did not act on active.

## Write a recovery message for a recurring error

Attach next-step guidance to an error agents keep hitting, so it comes back with the failure.

A recovery message is guidance attached to a specific failure, so a caller that hits it is told what to do next instead of only what went wrong. They pay off most on the errors that repeat across many callers.

This identifies a recurring failure from real traffic, reads one instance closely enough to write accurate guidance, and attaches it to that error's fingerprint. These change what live callers see, so write them against a failure you have actually inspected.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. Find the recurring failure with `GET /api/v1/projects/{slug}/logs`, filtering on `status` and `urlContains`, and confirm it is one repeated condition rather than several stacked together.
4. Read one instance in full with `GET /api/v1/projects/{slug}/logs/{logId}`, so the guidance you write matches the error the caller actually sees.
5. Check what is already attached with `GET /api/v1/projects/{slug}/recovery`, so you update the right fingerprint instead of adding a duplicate.
6. Write the guidance with `POST /api/v1/projects/{slug}/recovery`, sending `fingerprintKey`, `message` (what to do next, addressed to the caller), and `strategy`. Posting to a `fingerprintKey` that already exists replaces its message.
7. If a message is no longer accurate, remove it with `DELETE /api/v1/projects/{slug}/recovery`, passing the `fingerprintKey`.

## Explain why a user got stuck, then close the gap

Find out why someone got stuck by reading their own traffic, then fix the cause.

Someone says they could not get your API working. Their traffic is already recorded, so you can see exactly what happened: what they were trying to do, which request failed, and whether they found a way through or gave up.

Reach for this when a customer or a teammate reports being stuck. It reads their calls in order. That is what tells you whether they made a mistake, or your API never gave them a way to get it right. If it was the second, fix it where someone will read it before the next call, not just in the error that comes back after it.

1. Confirm the identity and access behind the API key with `GET /api/v1/me`.
2. Pick the target project. If you only have an example slug, verify it with `GET /api/v1/projects/{slug}`, or browse options via `GET /api/v1/projects`.
3. Get the reporter's email address. Ask the user for it if you were not given one. You cannot do this from a name alone.
4. Pull that person's traffic with `GET /api/v1/projects/{slug}/logs`, passing the address as `groupEmail` and `limit=50`. Add `since` and `until` only if you know roughly when it happened.
5. If no rows come back, do not guess. Retry without `since` and `until`, and confirm you are on the right project. Then say you found no traffic, rather than inventing a cause.
6. Read the rows oldest first, as one session. Find the first non-200. The calls before it show what the person was trying to do. Repeated calls after it show whether they got through on their own.
7. Open that failing request with `GET /api/v1/projects/{slug}/logs/{logId}`. Read three things: the response body for the error text, the request body for what was actually sent, and `errorFingerprint.key` for the identifier you need in step 10.
8. Decide where the fix belongs. If the error text already said exactly what to change, the caller missed it. If the error named a rule the caller had no way to know in advance, such as a size limit or a required field that is not in the spec, the API is at fault. Several retries with different shapes is a strong sign of the second.
9. Tell the user what you found, and stop. The next two steps change what live callers see, so get agreement before making them.
10. Attach guidance to the failure with `POST /api/v1/projects/{slug}/recovery`, using the `fingerprintKey` from step 7. Read `GET /api/v1/projects/{slug}/recovery` first, so you replace the right message instead of adding a duplicate. Write for every error that shares that fingerprint, not just this one.
11. Record the rule where it is read before a call is made. Use `POST /api/v1/projects/{slug}/context` for knowledge the docs never had, or `PATCH /api/v1/projects/{slug}/content` to correct existing copy.
12. Report in the order it happened: what the person was doing, what failed and why, whether they recovered, and what you changed. Name the request id so the user can open it.

## Debug the most recent error

Find the latest failed request in a project's logs and diagnose its cause.

This use case locates the most recent failed request for a project and pulls the full log record so you can see what went wrong. It covers the request, the response, the status code, and the error message returned to the caller.

Reach for it when a user or agent reports a failure and you need the specifics fast. It also checks whether the error is isolated or part of a pattern on the same endpoint, and whether a recovery message already exists for it.

1. If the project slug is unknown, call `GET /api/v1/projects` and ask the user which project to inspect when more than one is returned.
2. Call `GET /api/v1/projects/{slug}/logs` filtered to error responses (status 4xx/5xx), sorted newest first, limit 1. If nothing comes back, tell the user no recent errors exist and stop.
3. Take the `logId` of that entry and call `GET /api/v1/projects/{slug}/logs/{logId}` to fetch the full request and response, including headers, body, status, and error message. This read is audited.
4. Call `GET /api/v1/projects/{slug}/endpoints` with error rates enabled to check whether the failing endpoint has an elevated error rate or this is a one-off.
5. Call `GET /api/v1/projects/{slug}/recovery` to see whether a recovery message already covers this error.
6. Report to the user: the endpoint and method, timestamp, status code, error message, the likely cause based on the request payload, whether the error is recurring, and a concrete fix. If no recovery message exists and the error is recurring, offer to create one with `POST /api/v1/projects/{slug}/recovery`, but only after the user confirms.

## Project summary fields

`GET /api/v1/projects/{slug}` and each row of `GET /api/v1/projects` return the same summary shape: `slug`, `name`, `endpoints` (operation count from the current OpenAPI spec), `docsStatus` (`disabled`, `public`, or `request-access`), `isOwner` (true when the caller owns the project, false when they are a member), `memberCount`, `createdAt`, and `updatedAt`. Neither endpoint returns the OpenAPI document, docs content, or metrics; use the dedicated endpoints for those.
