{
  "openapi": "3.1.0",
  "info": {
    "title": "Kernel Public API",
    "version": "2026-06-17",
    "summary": "Read and write Kernel projects, ACDs, corpus documents, and sources from external systems.",
    "description": "The Kernel Public API is the external REST surface for [Kernel](https://kernel.tryaware.ai) — the source-of-truth context layer for AI workflows. Use it to list projects, fetch the latest ACD or corpus document version, push new ACD versions from automated pipelines, and ingest sources programmatically.\n\nAuthenticate with a bearer token (`Authorization: Bearer <api_key>`). API keys are scoped to a single workspace and can be created from **Settings → API keys**. All reads and writes (including ACD edits) are free; only ACD generations consume workspace credits, and generation is not exposed on this surface.\n\nResource lookups accept either a project UUID or its human-readable slug — whichever appears in your Kernel URL bar.",
    "contact": { "name": "Kernel support", "url": "https://kernel.tryaware.ai" }
  },
  "servers": [
    {
      "url": "https://lwzvxmjmpawlbvjzichz.supabase.co/functions/v1/kernel-public-api",
      "description": "Production"
    }
  ],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "Projects", "description": "Workspaces of context — one per product, customer segment, or initiative." },
    { "name": "ACDs", "description": "Anchor Context Documents — versioned, structured markdown documents." },
    { "name": "Corpus", "description": "Raw + cleaned corpus documents the ACDs are generated from." },
    { "name": "Sources", "description": "Ingest individual sources (files or text) into a project's corpus." }
  ],
  "paths": {
    "/projects": {
      "get": {
        "tags": ["Projects"],
        "summary": "List projects",
        "description": "Returns every project in the workspace the API key belongs to, most recently updated first.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": { "type": "array", "items": { "$ref": "#/components/schemas/Project" } }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/projects/{idOrSlug}": {
      "parameters": [{ "$ref": "#/components/parameters/IdOrSlug" }],
      "get": {
        "tags": ["Projects"],
        "summary": "Get a project",
        "responses": {
          "200": {
            "description": "OK",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/projects/{idOrSlug}/acds": {
      "parameters": [{ "$ref": "#/components/parameters/IdOrSlug" }],
      "get": {
        "tags": ["ACDs"],
        "summary": "List ACDs in a project",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "acds": { "type": "array", "items": { "$ref": "#/components/schemas/AcdSummary" } }
                  }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/projects/{idOrSlug}/acds/{slug}": {
      "parameters": [
        { "$ref": "#/components/parameters/IdOrSlug" },
        { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ACD slug, unique within the project." }
      ],
      "get": {
        "tags": ["ACDs"],
        "summary": "Fetch an ACD version",
        "description": "Returns the latest version of the ACD by default. Pass `?version=N` to fetch a specific version.",
        "parameters": [
          { "name": "version", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1 }, "description": "Specific version number to fetch. Omit for the latest." }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AcdVersion" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      },
      "post": {
        "tags": ["ACDs"],
        "summary": "Push a new ACD version",
        "description": "Creates a new version under the given ACD slug. The ACD is auto-created on first push. Pushing markdown via the public API is free and does not consume generation credits. Accepts either `application/json` with an inline `markdown` body, or `multipart/form-data` with a `file` field (UTF-8 markdown) for large documents. The body cap is 25 MB in both modes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["markdown"],
                "properties": {
                  "markdown": { "type": "string", "description": "Full ACD markdown body. Max 25 MB." },
                  "title": { "type": "string", "description": "Display title. Required on first push; optional thereafter." },
                  "model_used": { "type": "string", "description": "Free-text label of the model/tool that produced this version." },
                  "source_label": { "type": "string", "description": "Free-text provenance label stored alongside the version." }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary", "description": "UTF-8 markdown file. Max 25 MB. Filename (without extension) is used as the title when `title` is omitted." },
                  "markdown": { "type": "string", "description": "Inline markdown alternative to `file` (one or the other)." },
                  "title": { "type": "string", "description": "Display title. Required on first push if it can't be inferred from the filename." },
                  "model_used": { "type": "string" },
                  "source_label": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Version saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "acd_id": { "type": "string", "format": "uuid" },
                    "version_id": { "type": "string", "format": "uuid" },
                    "version_number": { "type": "integer" }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "413": { "description": "Payload too large — markdown body must be 25 MB or smaller." }
        }
      }
    },
    "/projects/{idOrSlug}/corpus": {
      "parameters": [{ "$ref": "#/components/parameters/IdOrSlug" }],
      "get": {
        "tags": ["Corpus"],
        "summary": "Fetch the corpus document",
        "description": "Returns the latest version of the project's auto-curated corpus document. Pass `?version=N` to fetch a specific version.",
        "parameters": [
          { "name": "version", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1 } }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CorpusDocVersion" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/projects/{idOrSlug}/sources": {
      "parameters": [{ "$ref": "#/components/parameters/IdOrSlug" }],
      "post": {
        "tags": ["Sources"],
        "summary": "Add a source",
        "description": "Add a new source (file or text). Audio/video files are rejected — use the Kernel UI for transcription. Returns `202` immediately; the source is processed asynchronously and will appear in the corpus once ready.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/SourcePayload" } },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary" },
                  "filename": { "type": "string" },
                  "external_id": { "type": "string" },
                  "source_modified_at": { "type": "string", "format": "date-time" }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted — source queued for processing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string", "format": "uuid" },
                    "status": { "type": "string", "example": "processing" },
                    "filename": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "409": { "description": "Duplicate — a source with identical content already exists." },
          "413": { "description": "Payload too large — files must be 25 MB or smaller." },
          "415": { "description": "Unsupported content type." }
        }
      },
      "put": {
        "tags": ["Sources"],
        "summary": "Upsert a source",
        "description": "Upsert by `source_id` or `external_id`. Returns `200 { unchanged: true }` when bytes + metadata are identical, `202 { replaced: true }` when an existing source was updated, or `202` like POST when `external_id` was supplied but no row existed yet.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/SourcePayload" } },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary" },
                  "filename": { "type": "string" },
                  "source_id": { "type": "string", "format": "uuid" },
                  "external_id": { "type": "string" },
                  "source_modified_at": { "type": "string", "format": "date-time" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "No-op — content unchanged" },
          "202": { "description": "Accepted — source updated or created" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "413": { "description": "Payload too large — files must be 25 MB or smaller." },
          "415": { "description": "Unsupported content type." }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Workspace API key. Create one in **Settings → API keys**."
      }
    },
    "parameters": {
      "IdOrSlug": {
        "name": "idOrSlug",
        "in": "path",
        "required": true,
        "schema": { "type": "string" },
        "description": "Project UUID or slug (e.g. `virtuo`). Slugs match what you see in the Kernel URL bar."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, invalid, or revoked API key.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "Resource not found in the caller's workspace.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "BadRequest": {
        "description": "Malformed request — see `message` for details.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    },
    "schemas": {
      "Project": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" },
          "organization_id": { "type": "string", "format": "uuid" }
        }
      },
      "AcdSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "slug": { "type": "string" },
          "title": { "type": "string" },
          "current_version_number": { "type": "integer", "nullable": true },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "AcdVersion": {
        "type": "object",
        "properties": {
          "acd_id": { "type": "string", "format": "uuid" },
          "slug": { "type": "string" },
          "title": { "type": "string" },
          "version_number": { "type": "integer" },
          "markdown": { "type": "string", "description": "Full ACD markdown body." },
          "source": { "type": "string", "enum": ["generation", "edit", "api"], "description": "How this version was produced." },
          "model_used": { "type": "string", "nullable": true },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "CorpusDocVersion": {
        "type": "object",
        "properties": {
          "project_id": { "type": "string", "format": "uuid" },
          "version_number": { "type": "integer" },
          "markdown": { "type": "string" },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "SourcePayload": {
        "type": "object",
        "required": ["filename"],
        "properties": {
          "filename": { "type": "string", "description": "Display name. Used for dedup with `external_id`." },
          "mime_type": { "type": "string", "nullable": true },
          "text": { "type": "string", "description": "Inline text body. Mutually exclusive with `content_base64`." },
          "content_base64": { "type": "string", "description": "Base64-encoded file body. Mutually exclusive with `text`." },
          "source_id": { "type": "string", "format": "uuid", "description": "Target an existing source by Kernel UUID (PUT only)." },
          "external_id": { "type": "string", "description": "Caller-provided stable ID for upserts." },
          "source_modified_at": { "type": "string", "format": "date-time" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "NOT_FOUND" },
          "message": { "type": "string" }
        }
      }
    }
  }
}
