{
  "openapi": "3.0.4",
  "info": {
    "title": "Cortex API",
    "description": "The **Cortex brain API**: read and write auth-gated, versioned markdown knowledge bases over HTTP. The same brains are also reachable by AI agents over **MCP** at `/mcp`.\n\n## Authentication\nEvery request carries a **bearer token** in the `Authorization` header. Two kinds are accepted:\n\n- **Service credential** (`ck_…`) for scripts and automation. Issue one in the app under a brain's **Settings → Service credentials** (shown once). It is pinned to one brain and role.\n- **OAuth access token** for interactive agents, obtained through the authorization-code flow.\n\n```\nAuthorization: Bearer ck_your_service_credential\n```\n\n## Quick start\n```bash\ncurl -H \"Authorization: Bearer ck_...\" \\\n  https://your-cortex-host/api/v1/brains\n```\n\nBrain-scoped routes take the brain's GUID as `{brainId}`. List your brains first (`GET /api/v1/brains`) to find it, or read `GET /api/v1/brains/{brainId}/schema` to learn a brain's folders and entity types.\n\n## Rate limits\nRequests are rate-limited per credential. Exceeding the limit returns `429 Too Many Requests`.",
    "contact": {
      "name": "Cortex"
    },
    "version": "v1"
  },
  "paths": {
    "/api/v1/brains": {
      "get": {
        "tags": [
          "Brains"
        ],
        "summary": "Gets the brains the current caller can access. A ck_ service credential is pinned to a\nsingle brain (it has no user), so it returns just that brain; an OAuth user gets all the\nbrains their access list allows.",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "Brains"
        ],
        "summary": "Creates a new brain from the chosen schema template.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBrainRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBrainRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBrainRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{id}": {
      "get": {
        "tags": [
          "Brains"
        ],
        "summary": "Gets a single brain by id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/inbox": {
      "post": {
        "tags": [
          "DefaultInbox"
        ],
        "summary": "Uploads into the caller's default sink. Multipart form data (binary) or an\napplication/json body of Cortex.Application.Services.InboxService.DTOs.UploadInboxRequest (text; set externalId so\nre-posts are idempotent).",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/inbox": {
      "get": {
        "tags": [
          "Inbox"
        ],
        "summary": "Lists the brain's inbox items, newest first, optionally filtered by status.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/InboxStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "Inbox"
        ],
        "summary": "Uploads a new inbox item. Two shapes: multipart form data (first file wins; binary OK)\nor an application/json body of Cortex.Application.Services.InboxService.DTOs.UploadInboxRequest (text content, e.g. a\ntranscript pushed by an agent hook - set externalId so re-posts are idempotent).\nRequires Write+ on the brain. Duplicate content or a repeated externalId returns the\nexisting item's id with an explanatory message rather than creating a second item.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/inbox/{itemId}": {
      "get": {
        "tags": [
          "Inbox"
        ],
        "summary": "Gets one inbox item with its extracted text (capped server-side).",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/inbox/{itemId}/status": {
      "put": {
        "tags": [
          "Inbox"
        ],
        "summary": "Applies a status transition, optionally recording a suggested placement. Requires Write+.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateInboxStatusRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateInboxStatusRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateInboxStatusRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/inbox/{itemId}/archive": {
      "post": {
        "tags": [
          "Inbox"
        ],
        "summary": "Archives an item after ingest (marks it ingested/done). Requires Write+.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/instructions": {
      "get": {
        "tags": [
          "Instructions"
        ],
        "summary": "Gets the brain's instructions markdown (empty string when none is set).",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/pages": {
      "get": {
        "tags": [
          "Pages"
        ],
        "summary": "Lists the brain's pages when no path is supplied, or returns a single\nhydrated page (metadata + body) when `?path=` is provided.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "put": {
        "tags": [
          "Pages"
        ],
        "summary": "Creates or updates a page via the durable write path (pending row, bytes, finalise, audit).",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PutPageRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/PutPageRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/PutPageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "delete": {
        "tags": [
          "Pages"
        ],
        "summary": "Deletes the page identified by `?path=`.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "path",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/schema": {
      "get": {
        "tags": [
          "Schema"
        ],
        "summary": "Gets the brain's own folder + entity-type schema.",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/brains/{brainId}/search": {
      "get": {
        "tags": [
          "Search"
        ],
        "summary": "Searches the brain: `?q=` is the query text, `?mode=` is semantic, exact or\nhybrid (default hybrid) and `?limit=` caps the hit count (default 8).",
        "parameters": [
          {
            "name": "brainId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BrainVisibility": {
        "enum": [
          0,
          1,
          2
        ],
        "type": "integer",
        "format": "int32"
      },
      "CreateBrainRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "slug": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "visibility": {
            "$ref": "#/components/schemas/BrainVisibility"
          },
          "templateKey": {
            "type": "string",
            "nullable": true
          },
          "embeddingProvider": {
            "$ref": "#/components/schemas/EmbeddingProvider"
          },
          "embeddingModel": {
            "type": "string",
            "nullable": true
          },
          "embeddingDimensions": {
            "type": "integer",
            "format": "int32"
          }
        },
        "additionalProperties": false
      },
      "EmbeddingProvider": {
        "enum": [
          0,
          1,
          2,
          3,
          4
        ],
        "type": "integer",
        "format": "int32"
      },
      "InboxStatus": {
        "enum": [
          0,
          1,
          2,
          3
        ],
        "type": "integer",
        "format": "int32"
      },
      "PutPageRequest": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "nullable": true
          },
          "markdown": {
            "type": "string",
            "nullable": true
          },
          "summary": {
            "type": "string",
            "nullable": true
          },
          "expectedVersion": {
            "type": "integer",
            "format": "int32"
          },
          "expectedToken": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "UpdateInboxStatusRequest": {
        "type": "object",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/InboxStatus"
          },
          "targetFolder": {
            "type": "string",
            "nullable": true
          },
          "targetSlug": {
            "type": "string",
            "nullable": true
          },
          "entityType": {
            "type": "string",
            "nullable": true
          },
          "confidence": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "rationale": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "description": "An OAuth access token or a ck_ service credential, sent as `Authorization: Bearer <token>`.",
        "scheme": "bearer",
        "bearerFormat": "OAuth access token or ck_ service credential"
      }
    }
  },
  "security": [
    {
      "Bearer": [ ]
    }
  ]
}