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

# Start Chat

> Starts a new chat. Returns immediately with the new `chat_id` +
`message_id`; poll `GET /v1/chats/{chat_id}/messages/{message_id}`
until that message's status is `done` or `error`. To append a turn
to an existing chat, use `POST /v1/chats/{id}/messages`.




## OpenAPI

````yaml /openapi.yaml post /v1/chats
openapi: 3.0.3
info:
  title: Chief Public API
  version: 1.0.0
  contact:
    name: Chief Support
    url: https://chief.bot
  description: |
    Chief's public REST API for programmatic access to chats and assets.

    All endpoints are authenticated with a Personal Access Token (PAT)
    sent in the `X-API-Key` header. PATs are minted out-of-band from the
    Chief settings UI.

    All endpoints that touch project-scoped resources require the
    `X-Project-Id` header. Missing or invalid project IDs respond with HTTP
    400 and the error code `publicapi.tenancy.project.missing`.

    ## Error envelope

    Every error response uses the same JSON envelope:

    ```json
    { "code": "publicapi.auth.invalid",
      "humane": "The provided API key is invalid or has been revoked.",
      "statusCode": 401 }
    ```

    `code` is a stable, dotted, lowercase identifier suitable for client-side
    i18n and analytics. `humane` is plain English safe to surface to end
    users. `statusCode` mirrors the HTTP status.

    ## Chat workflow — kickoff + poll

    Chats are asynchronous in v1. Callers need to poll the
    per-message endpoint until the content they need is present.

    1. `POST /v1/chats` with `{prompt}`. The server kicks off the
       workflow and returns `{chat_id, message_id, created_at}`
       immediately. `message_id` is the message you'll poll.
    2. `POST /v1/chats/{chat_id}/messages` with `{prompt}` to
       continue an existing chat — appends a new turn and returns
       `{message_id, created_at}`.
    3. `GET /v1/chats/{chat_id}/messages/{message_id}` to read the
       message. While the workflow is still writing, `prompt` and
       `response` are omitted; once written they're present. Treat the
       appearance of `response` as the signal that the assistant has
       produced output.
    4. `GET /v1/chats/{chat_id}` returns chat-level metadata only
       (`modified_at`). It does not carry messages.
    5. `GET /v1/chats/{chat_id}/messages` lists every message's id +
       `created_at` (no content); clients fetch one message at a time via
       `GET /v1/chats/{chat_id}/messages/{mid}` for the prompt + response
       body.

    ## Asset workflow — three-step upload

    Assets are uploaded directly to blob storage via a signed URL. The flow
    is:

    1. `POST /v1/assets` with `{filename, mime_type}`, optionally including
       the hex-encoded `md5` of the file. When `md5` matches content already
       in the project the server returns `200` with `already_exists: true` and
       no upload URL — skip to fetching the asset. Otherwise it returns `201`
       with `{asset_id, upload_url, upload_method:"PUT", upload_headers,
       expires_at}`.
    2. `PUT` the file bytes to `upload_url`, applying every header in
       `upload_headers` verbatim. The URL is valid until `expires_at`.
    3. `POST /v1/assets/{asset_id}/complete` with an empty body to
       hand the asset off to the ingest pipeline. The server reads the
       uploaded object's size and MD5 from blob storage at this step. The
       response carries the current `AssetResponse`; clients poll until
       `status` is `ready` or `failed`.
servers:
  - url: '{baseUrl}'
    description: Chief
    variables:
      baseUrl:
        default: https://api.storytell.ai
        description: Base URL of the deployment serving the API.
security:
  - apiKey: []
tags:
  - name: Chats
    description: Public chat lifecycle — kickoff, list, fetch.
  - name: Assets
    description: Public asset upload + ingest lifecycle.
  - name: Labels
    description: Public label CRUD and asset-label attachment.
  - name: Actions
    description: Public action CRUD plus enable/disable.
  - name: Sessions
    description: Public recording-session listing and CRUD.
  - name: Skills
    description: Public skill CRUD plus enable/disable.
  - name: Memories
    description: Public memory CRUD.
  - name: Projects
    description: Public project create/edit, membership, and invitations.
paths:
  /v1/chats:
    post:
      tags:
        - Chats
      summary: Start Chat
      description: |
        Starts a new chat. Returns immediately with the new `chat_id` +
        `message_id`; poll `GET /v1/chats/{chat_id}/messages/{message_id}`
        until that message's status is `done` or `error`. To append a turn
        to an existing chat, use `POST /v1/chats/{id}/messages`.
      operationId: createChat
      parameters:
        - $ref: '#/components/parameters/XProjectId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateChatRequest'
            example:
              prompt: Summarize this quarter's product launches.
      responses:
        '202':
          description: Chat accepted; workflow running.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateChatResponse'
              example:
                chat_id: chat_d8aad64dib2c7m3ae7j0
                message_id: message_d8aad64dib2c7m3ae7jg
                created_at: '2026-05-23T10:15:30Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - apiKey: []
components:
  parameters:
    XProjectId:
      in: header
      name: X-Project-Id
      required: true
      schema:
        type: string
        pattern: ^project_[a-z0-9]{20}$
      example: project_d8a4td4dib27i4beefb0
      description: |
        Project identifier scoping the request. Required on every
        project-scoped public endpoint. Missing or malformed values respond
        with HTTP 400 and code `publicapi.tenancy.project.missing`.
  schemas:
    CreateChatRequest:
      type: object
      required:
        - prompt
      properties:
        prompt:
          type: string
          description: The user's message to start the chat.
        intelligence:
          type: string
          enum:
            - auto
            - fast
            - expert
            - research
          description: |
            Mode preset that controls model class and tool selection.
            `auto` lets the backend classify the prompt and route. Defaults
            to `auto` when omitted.
        provider:
          type: string
          enum:
            - automatic
            - anthropic
            - openai
            - google
          description: |
            Biases model selection within the chosen `intelligence` mode
            toward a specific vendor. `automatic` (or omitted) leaves the
            router's default ordering. The mode preset still controls
            thinking depth and tool selection — provider only re-ranks
            candidate models. Mirrors the UI's AI Provider picker.
        skills:
          type: array
          items:
            type: string
          description: |
            Skill names to pre-load before the LLM runs. The Bluesky UI's
            "Expert Voice" picker sends one entry; the API accepts many.
            Each name must reference a skill the caller can access.
        public_data:
          type: boolean
          description: |
            When `false`, disables the public-web-search tool for this
            turn. Omitting or sending `true` leaves the mode default in
            place.
        scope:
          $ref: '#/components/schemas/ScopeRequest'
          description: |
            Optional. Narrows the knowledge the assistant may consult on
            this turn. Each id list is independently validated for shape;
            access is enforced server-side.
    CreateChatResponse:
      type: object
      required:
        - chat_id
        - message_id
        - created_at
      properties:
        chat_id:
          type: string
          pattern: ^chat_[a-z0-9]{20}$
        message_id:
          type: string
          pattern: ^message_[a-z0-9]{20}$
          description: |
            The new turn's id. Poll
            `GET /v1/chats/{chat_id}/messages/{message_id}` to follow its
            lifecycle.
        created_at:
          type: string
          format: date-time
    ScopeRequest:
      type: object
      description: |
        Caller-supplied references the assistant may consult on this turn.
        Tenancy (org, workspace, project) is derived from the
        `X-Project-Id` header and is never carried here.
      properties:
        asset_ids:
          type: array
          items:
            type: string
            pattern: ^asset_[a-z0-9]{20}$
          description: Specific assets (files) to include.
        chat_ids:
          type: array
          items:
            type: string
            pattern: ^chat_[a-z0-9]{20}$
          description: Past chats to include as additional context.
        label_ids:
          type: array
          items:
            type: string
            pattern: ^label_[a-z0-9]{20}$
          description: Labels to expand into associated assets and concepts.
        concept_ids:
          type: array
          items:
            type: string
            pattern: ^concept_[a-z0-9]{20}$
          description: Concepts to consult — semantically broader than assets.
        project_ids:
          type: array
          items:
            type: string
            pattern: ^project_[a-z0-9]{20}$
          description: Whole projects to consult. Wider scope than concepts or labels.
        view_ids:
          type: array
          items:
            type: string
            pattern: ^view_[a-z0-9]{20}$
          description: Saved views the assistant should consult.
    Error:
      type: object
      required:
        - code
        - statusCode
      properties:
        code:
          type: string
          pattern: ^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$
          description: |
            Stable dotted, lowercase identifier, namespaced by domain and
            operation (`<domain>.<op>.<reason>`). Suitable for client-side
            i18n keys and analytics. Codes are additive; existing codes are
            never reworded.
          example: publicapi.auth.invalid
        humane:
          type: string
          description: Plain-English message safe to display to end users.
          example: The provided API key is invalid or has been revoked.
        statusCode:
          type: integer
          minimum: 400
          maximum: 599
          description: |
            Mirror of the HTTP status code. (Field name is camelCase here
            only — owned by `nutils.Error` across the platform.)
          example: 401
  responses:
    BadRequest:
      description: Malformed request, validation failure, or missing tenancy header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missingProject:
              summary: Missing X-Project-Id
              value:
                code: publicapi.tenancy.project.missing
                humane: X-Project-Id header is required.
                statusCode: 400
    Unauthorized:
      description: Missing, malformed, or revoked credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: publicapi.auth.invalid
            humane: The provided API key is invalid or has been revoked.
            statusCode: 401
    NotFound:
      description: Resource does not exist or is outside the caller's reach.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        Personal Access Token, sent verbatim as `pat_<32 chars>`. PATs are
        minted from the Chief settings UI.

````