components:
  responses:
    BadRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Invalid path, query or request input
    Unauthorized:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/UnauthorizedError'
      description: Missing, unknown, revoked or expired key; shared authentication envelope
    Forbidden:
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/ForbiddenError'
            - $ref: '#/components/schemas/Error'
      description: The shared key-scope gate uses the legacy envelope; an operation-specific refusal may use the v2 error envelope
    Conflict:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Idempotency-Key conflict, or an operation-specific concurrency conflict
    NotFound:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: The space does not exist, or is not available (deleted, left, or still joining)
    RequestTooLarge:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Request body exceeds this operation's documented cap
    RateLimited:
      content:
        application/json:
          schema:
            properties:
              code:
                example: rate_limit_exceeded
                type: string
              message:
                example: Rate limit exceeded
                type: string
              object:
                example: error
                type: string
              status:
                example: 429
                type: integer
            type: object
      description: Shared write rate limit; legacy error envelope
  schemas:
    ValidationError:
      properties:
        code:
          example: bad_request
          type: string
        message:
          example: Bad request
          type: string
        object:
          example: error
          type: string
        status:
          example: 400
          type: integer
      type: object
    ServerError:
      properties:
        code:
          example: internal_server_error
          type: string
        message:
          example: Internal server error
          type: string
        object:
          example: error
          type: string
        status:
          example: 500
          type: integer
      type: object
    ForbiddenError:
      properties:
        code:
          example: forbidden
          type: string
        message:
          example: Forbidden
          type: string
        object:
          example: error
          type: string
        status:
          example: 403
          type: integer
      required:
      - object
      - status
      - code
      - message
      type: object
    CreateChallengeResponse:
      properties:
        challenge_id:
          description: The challenge id associated with the displayed code and needed
            to solve the challenge for api_key
          example: GB6ZU3Y52UGUEQQCIJC33LM6XC
          type: string
      type: object
    CreateChallengeRequest:
      properties:
        app_name:
          description: The name of the app that is requesting the challenge
          example: anytype_mcp
          type: string
      type: object
    CreateApiKeyResponse:
      required: [api_key, grant]
      properties:
        api_key:
          description: |-
            ApiKey is an opaque bearer key in the format `anytype_<body>_<checksum>`.
            New keys match `\banytype_[0-9A-Za-z]{40,60}_[0-9a-f]{8}\b`; the body
            length varies. Previously issued unprefixed base64 keys remain valid.
          example: anytype_amfbcga7eywtio2cjfifoxtfnrzxvamir6lj3jflwk44br6o2xoa_3fe1d4b7
          type: string
        grant:
          $ref: '#/components/schemas/ApiKeyGrant'
      type: object
    CreateApiKeyRequest:
      properties:
        challenge_id:
          description: The challenge id associated with the previously displayed code
          example: GB6ZU3Y52UGUEQQCIJC33LM6XC
          type: string
        code:
          description: The 4-digit code retrieved from Anytype Desktop app
          example: "1234"
          type: string
      type: object
    ApiKeyGrant:
      required: [all_spaces, space_ids, permission]
      description: The grant approved by the user and persisted with this key; null
        for an unscoped key.
      properties:
        all_spaces:
          description: Covers all current and future user spaces when true; space_ids
            is then empty.
          type: boolean
        permission:
          description: The access approved by the user, which may differ from what
            the app requested.
          enum:
          - read
          - readwrite
          type: string
        space_ids:
          description: Full IDs of the granted spaces. An empty list alone never means
            all spaces.
          items:
            type: string
          type: array
          uniqueItems: false
      type: [object, 'null']
    UnauthorizedError:
      properties:
        code:
          example: unauthorized
          type: string
        message:
          example: Unauthorized
          type: string
        object:
          example: error
          type: string
        status:
          example: 401
          type: integer
      required:
      - object
      - status
      - code
      - message
      type: object
    AddChatMessageRequest:
      properties:
        attachments:
          items:
            type: string
          type: array
          uniqueItems: false
        reply_to:
          type: string
        text:
          type: string
      type: object
    ChatAttachment:
      properties:
        id:
          type: string
        type:
          type: string
      type: object
    ChatMessage:
      properties:
        at:
          type: string
        attachments:
          items:
            $ref: '#/components/schemas/ChatAttachment'
          type: array
          uniqueItems: false
        author:
          type: string
        author_id:
          type: string
        blocks_text:
          type: string
        edited_at:
          type: string
        id:
          type: string
        order:
          type: string
        pinned:
          type: boolean
        reacted_by:
          additionalProperties:
            items:
              type: string
            type: array
          type: object
        reactions:
          additionalProperties:
            type: integer
          type: object
        reply_to:
          type: string
        text:
          type: string
      type: object
    ChatMessageResult:
      properties:
        dry_run:
          type: boolean
        id:
          type: string
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ChatMessagesResponse:
      properties:
        has_more:
          description: more messages inside the requested bounds, not in the chat
            as a whole
          type: boolean
        lifetime_message_count:
          description: Messages ever posted, deleted ones included
          type: integer
        message_count:
          description: Messages the chat holds now; a deleted message leaves it
          type: integer
        messages:
          items:
            $ref: '#/components/schemas/ChatMessage'
          type: array
          uniqueItems: false
        next_after:
          type: string
        next_before:
          type: string
        state:
          $ref: '#/components/schemas/ChatState'
      type: object
    ChatReactionRequest:
      properties:
        emoji:
          type: string
      type: object
    ChatReactionResult:
      properties:
        added:
          type: boolean
        dry_run:
          type: boolean
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ChatReadRequest:
      properties:
        last_state_id:
          type: string
        scope:
          type: string
        up_to:
          type: string
      type: object
    ChatReadResult:
      properties:
        dry_run:
          type: boolean
        state:
          $ref: '#/components/schemas/ChatState'
      type: object
    ChatResult:
      properties:
        dry_run:
          type: boolean
        id:
          type: string
        name:
          type: string
      type: object
    ChatRow:
      properties:
        id:
          type: string
        name:
          type: string
      type: object
    ChatState:
      properties:
        last_state_id:
          type: string
        oldest_unread_mention_order:
          type: string
        oldest_unread_order:
          type: string
        unread_mentions:
          type: integer
        unread_messages:
          type: integer
        unread_reaction_order:
          type: string
      type: object
    CreateChatRequest:
      properties:
        name:
          type: string
      type: object
    CreateResult:
      properties:
        created:
          $ref: '#/components/schemas/SideEffects'
        created_views:
          additionalProperties:
            type: string
          description: The view id each insert_view op minted, keyed by the op's position,
            such as /ops/0.
          type: object
        dry_run:
          type: boolean
        etag:
          description: etag of the created object
          type: string
        id:
          type: string
        issues:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
        items:
          description: Count of the member objects a created collection holds, on
            every collection create
          type: integer
        key:
          description: identity key (types, properties)
          type: string
        removed:
          $ref: '#/components/schemas/SideEffects'
        type:
          description: type key of the created object
          type: string
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    CreateSpaceRequest:
      properties:
        description:
          type: string
        name:
          type: string
      type: object
    CreatedOption:
      properties:
        name:
          type: string
        property:
          description: property key
          type: string
      type: object
    DiffStats:
      properties:
        blocks_added:
          type: integer
        blocks_changed:
          type: integer
        blocks_moved:
          type: integer
        blocks_removed:
          type: integer
        items_added:
          description: Collection members the batch added, as a set difference; absent
            means none
          type: integer
        items_removed:
          description: Collection members the batch removed, as a set difference;
            absent means none
          type: integer
        properties_changed:
          type: integer
      type: object
    EditChatMessageRequest:
      properties:
        text:
          type: string
      type: object
    EditResult:
      properties:
        created:
          $ref: '#/components/schemas/SideEffects'
        created_blocks:
          additionalProperties:
            type: string
          description: |-
            Maps payload positions to new block IDs, including nested table rows,
            columns, and cell descendants (e.g. "ops[3].blocks[0].rows[1]").
            Existing IDs are omitted. Values match the resulting document:
            compact by default, full with ?ids=full. IDs absent from that document
            retain their minted spelling.
          type: object
        created_views:
          additionalProperties:
            type: string
          description: |-
            Maps payload positions to new view IDs: "ops[i]" for insert_view or
            "ops[i].set.views[j]" for update_block. Values match the resulting
            document and view listing: compact by default, full with ?ids=full.
            IDs absent from the document retain their minted spelling.
          type: object
        diff_stats:
          $ref: '#/components/schemas/DiffStats'
        dry_run:
          type: boolean
        etag:
          type: string
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    Error:
      properties:
        code:
          type: string
        issues:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
        message:
          type: string
        status:
          type: integer
      required:
      - status
      - code
      - message
      - issues
      type: object
    FileUploadResult:
      properties:
        dry_run:
          type: boolean
        id:
          type: string
        mime_type:
          type: string
        name:
          type: string
        size:
          type: integer
      type: object
    Issue:
      properties:
        hint:
          type: string
        message:
          type: string
        path:
          type: string
        see_also:
          description: 'The operations the hint names, as data: each renders in the
            hint as its method and path with params substituted and `?k=v` query sorted
            by key, so a caller with tools instead of routes can find and replace
            it by op.'
          items:
            $ref: '#/components/schemas/Ref'
          type: array
          uniqueItems: false
      required:
      - message
      type: object
    ListResponse-ChatRow:
      properties:
        data:
          items:
            $ref: '#/components/schemas/ChatRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListResponse-MemberRow:
      properties:
        data:
          items:
            $ref: '#/components/schemas/MemberRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListResponse-ObjectRow:
      properties:
        data:
          items:
            $ref: '#/components/schemas/ObjectRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListResponse-OptionRow:
      properties:
        data:
          items:
            $ref: '#/components/schemas/OptionRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListResponse-PropertyRow:
      properties:
        data:
          items:
            $ref: '#/components/schemas/PropertyRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListResponse-TypeRow:
      properties:
        data:
          items:
            $ref: '#/components/schemas/TypeRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListResponse-ViewObject:
      properties:
        data:
          items:
            $ref: '#/components/schemas/ViewObject'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ListSpacesResponse:
      properties:
        data:
          items:
            $ref: '#/components/schemas/SpaceRow'
          type: array
          uniqueItems: false
        has_more:
          type: boolean
        has_not_granted_spaces:
          description: True when other live user spaces are excluded by this key's
            grant, independently of the requested page. Ask the user to grant access
            if a requested space is missing.
          type: boolean
        limit:
          type: integer
        message:
          type: string
        offset:
          type: integer
        total:
          type: integer
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      required:
      - data
      - total
      - offset
      - limit
      - has_more
      - has_not_granted_spaces
      type: object
    MemberRow:
      properties:
        icon_image:
          description: Icon id; download with GET /v2/spaces/{space_id}/files/{file_id}/content.
          type: string
        id:
          type: string
        identity:
          type: string
        name:
          type: string
        role:
          type: string
      type: object
    ObjectRow:
      properties:
        id:
          type: string
        name:
          type: string
        properties:
          additionalProperties: {}
          type: object
        space_id:
          type: string
        type:
          type: string
      type: object
    OptionRow:
      properties:
        color:
          type: string
        name:
          type: string
      type: object
    PropertyRow:
      properties:
        format:
          type: string
        key:
          type: string
        name:
          type: string
      type: object
    Ref:
      properties:
        op:
          description: The operation's OpenAPI operationId, such as list_properties;
            absent means the request that produced this issue, resent with the query
            given, and the hint then spells only the query.
          type: string
        params:
          additionalProperties:
            type: string
          description: Path parameters by their OpenAPI name, each substituted into
            the path once and verbatim (no percent-encoding); one left out keeps its
            {name} placeholder in the hint for the caller to fill.
          type: object
        query:
          additionalProperties:
            type: string
          description: Query parameters to send with the operation, spelled in the
            hint as ?name=value pairs joined by & and sorted by name, values verbatim.
          type: object
      type: object
    SchemaEntry:
      properties:
        endpoint:
          type: string
        example:
          type: object
        example_body:
          description: An op schema's example wrapped as the request body it is sent
            in
          type: object
        grammar:
          type: string
        grammar_examples:
          items:
            type: string
          type: array
          uniqueItems: false
        kind:
          type: string
        schema:
          type: object
      type: object
    SchemaIndex:
      properties:
        kinds:
          items:
            $ref: '#/components/schemas/SchemaIndexEntry'
          type: array
          uniqueItems: false
        ops:
          items:
            $ref: '#/components/schemas/SchemaIndexEntry'
          type: array
          uniqueItems: false
      type: object
    SchemaIndexEntry:
      properties:
        endpoint:
          type: string
        kind:
          type: string
        url:
          type: string
      type: object
    SearchRequestDoc:
      properties:
        fields:
          items:
            type: string
          type: array
          uniqueItems: false
        filter:
          type: string
        filters:
          items:
            additionalProperties: {}
            type: object
          type: array
          uniqueItems: false
        query:
          description: Full-text query over object names and indexed content.
          type: string
        sorts:
          items:
            additionalProperties: {}
            type: object
          type: array
          uniqueItems: false
        type:
          type: string
      type: object
    SideEffects:
      properties:
        options:
          items:
            $ref: '#/components/schemas/CreatedOption'
          type: array
          uniqueItems: false
        properties:
          items:
            $ref: '#/components/schemas/PropertyRow'
          type: array
          uniqueItems: false
      type: object
    Space:
      properties:
        description:
          type: string
        dry_run:
          type: boolean
        icon_image:
          description: Icon id; download with GET /v2/spaces/{space_id}/files/{file_id}/content.
          type: string
        id:
          type: string
        name:
          type: string
      type: object
    SpaceRow:
      properties:
        description:
          type: string
        icon_image:
          description: Icon id; download with GET /v2/spaces/{space_id}/files/{file_id}/content.
          type: string
        id:
          description: |-
            Id is the space's short reference: the last six characters of the
            first half of its id. It is the full id instead when that tail is
            shared with another visible space, or when the request asked for
            `?ids=full`. Either spelling is accepted back on every route that
            takes a space.
          type: string
        name:
          type: string
      type: object
    TypeRow:
      properties:
        key:
          type: string
        name:
          type: string
      type: object
    UpdateSpaceRequest:
      properties:
        description:
          type: string
        name:
          type: string
      type: object
    UploadFileRequest:
      properties:
        name:
          type: string
        url:
          type: string
      required:
      - url
      type: object
    ValidateResponse:
      properties:
        issues:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
        warnings:
          items:
            $ref: '#/components/schemas/Issue'
          type: array
          uniqueItems: false
      type: object
    ViewObject:
      additionalProperties: {}
      type: object
    WhoamiApi:
      properties:
        version:
          type: string
      type: object
    WhoamiGrant:
      properties:
        all_spaces:
          description: 'the boundary field of an all-spaces grant: the key covers
            every space in the account, including spaces created later (the tech space
            excepted). Never infer the boundary from spaces'
          type: boolean
        permission:
          description: the compact form agents string-match on
          type: string
        restricted:
          description: 'The key reaches only the spaces listed: scoped, and not all_spaces.
            False for a legacy key and for an all-spaces grant alike'
          type: boolean
        scoped:
          description: A grant record exists. An all-spaces grant is scoped too; branch
            on restricted for the space boundary
          type: boolean
        space_count:
          description: 'For an all-spaces grant: how many live spaces the key covers
            now, zero included. spaces lists them only when the spaces parameter is
            true'
          type: integer
        spaces:
          description: the granted spaces of a restricted key; for an all-spaces grant,
            the current live spaces when the spaces parameter is true, else empty
          items:
            $ref: '#/components/schemas/WhoamiGrantSpace'
          type: array
          uniqueItems: false
      type: object
    WhoamiGrantSpace:
      properties:
        id:
          type: string
        name:
          type: string
        permission:
          type: string
      type: object
    WhoamiKey:
      properties:
        created_at:
          type: string
        expires_at:
          type: string
        id:
          description: 'An identifier of the key record, the one the key list in Settings
            shows: the hex sha256 of the key''s raw bytes, never the token itself'
          type: string
        name:
          type: string
      type: object
    WhoamiResponse:
      properties:
        api:
          $ref: '#/components/schemas/WhoamiApi'
        grant:
          $ref: '#/components/schemas/WhoamiGrant'
        key:
          $ref: '#/components/schemas/WhoamiKey'
        key_status:
          description: 'Credential kind: scoped means a grant record exists (all-spaces
            grants included), legacy means none. Use grant.restricted for the space
            boundary'
          type: string
        notice:
          description: the legacy sentence, verbatim printable
          type: string
        scope:
          description: '"jsonApi" | "full" | "limited"'
          type: string
      type: object
  securitySchemes:
    bearerauth:
      scheme: bearer
      type: http
externalDocs:
  description: OpenAPI
  url: https://swagger.io/resources/open-api/
info:
  description: |+
    Anytype API v2 exposes an object as one editable **AnyBlock JSON document**.
    A single `GET` reads its properties and content; a single `PATCH` applies a
    batch of edits. It is designed for agents, scripts, and integrations that
    need to work with whole documents.

    > **Pre-release:** API v2 can change without a new API version. Use
    > [API v1](https://developers.anytype.io/docs/reference) for production
    > integrations that need a stable contract.

    ## Connect and authenticate

    The API runs locally with Anytype, at `http://127.0.0.1:31009` by default.
    Both API majors share the same process, port, and API keys. v2 routes start
    with `/v2/` and do not require the `Anytype-Version` request header.

    To obtain a key through Desktop pairing:

    1. Send `POST /v2/auth/challenges` with an `app_name`.
    2. The user approves spaces and permissions in Anytype Desktop, then receives
       a four-digit code.
    3. Send `POST /v2/auth/api_keys` with the `challenge_id` and `code`. The
       response contains an `api_key` and the approved grant.

    These two pairing endpoints require no existing key. For authenticated
    requests, send the key in the `Authorization` header:

    ```bash
    curl http://127.0.0.1:31009/v2/auth/whoami \
      -H "Authorization: Bearer $api_key"
    ```

    Set `api_key` to your key before running the example. The `whoami` response
    describes which spaces and permissions it grants.

    The bearer credential is an opaque Anytype API key. It is not a JWT, and it
    is never read from a query or body parameter. An unknown, revoked, or expired
    key returns `401`.

    ## Objects, properties, and blocks

    - **Spaces** contain objects. Most routes are scoped to one space.
    - **Objects** combine typed `properties` with document content in `blocks`.
    - **Types** describe an object's shape and are addressed by a type key, such
      as `page` or `task`.
    - **Queries** show a live selection of objects. **Collections** hold a
      hand-curated list.
    - **Chats** store messages separately from document blocks.

    Blocks form a flat array in document order, with `indent` describing the
    hierarchy. Inline text formatting uses Markdown. The title and description
    live in the `name` and `description` properties.

    | Task | Request |
    | --- | --- |
    | Find available spaces | `GET /v2/spaces` |
    | Search within a space | `POST /v2/spaces/{space_id}/search` |
    | Search across spaces | `POST /v2/search` |
    | Read a document | `GET /v2/spaces/{space_id}/objects/{object_id}` |
    | Create an object | `POST /v2/spaces/{space_id}/objects` |
    | Edit a document | `PATCH /v2/spaces/{space_id}/objects/{object_id}` |

    ## Names and identifiers

    Names owned by v2 use `snake_case`: path and query parameters, request and
    response fields, and `PATCH` operation names. Content inside an AnyBlock
    document retains the format's own field vocabulary.

    ### Property and type keys

    Reads use stable keys such as `due_date` by default. A key is minted when
    the property or type is created and stays the same after a rename. Use keys
    in scripts, configuration, and integrations.

    Use `?keys=name` to read display names such as `Due date` instead. This is
    useful when showing users their own vocabulary.

    Inputs accept keys, display names, and forgiving spelling variants. For
    example, `due_date`, `dueDate`, `due-date`, and `Due date` can address the same
    property. An ambiguous spelling returns `400` with the candidates. An
    unknown spelling never creates a property implicitly.

    Select options are addressed by their names. Object references remain full
    object ids and are included inline.

    ### Block and view ids

    Default object reads shorten machine-minted block ids to document-local
    suffixes. Use ids exactly as the read returns them when editing. Routes and
    operations that address a block or view accept a full id or a unique suffix;
    an ambiguous suffix is refused with a list of candidates.

    Use `?ids=full` for the export shape, with full ids throughout. This is the
    shape to store for a backup or use when cloning a document.

    PATCH receipts follow the same choice: `created_blocks` and `created_views`
    use the labels from the resulting document by default, and full ids with
    `?ids=full`. This also applies to dry runs. Collision handling can leave an
    id full. An id removed by a later operation or omitted from the resulting
    document retains its minted spelling in the receipt.

    ### Space references

    A space is normally served with a short reference: the last six characters
    of the first half of its full `<cid>.<replicationKey>` id. Space-scoped routes
    accept either spelling. Resolution tries an exact id first, then a unique
    suffix among the spaces the key can access.

    An ambiguous reference returns `400` with the candidates. Spaces whose
    suffixes collide are served with full ids.

    A short reference is only unique among the spaces currently visible to the
    key. Joining another space can make it ambiguous. Use `?ids=full` whenever a
    space reference will be stored outside the API.

    ## Read and search efficiently

    Object reads return the editable document by default. For a smaller read:

    - `?outline=true` returns the block structure with shortened text.
    - `?include=properties` or `?include=blocks` selects part of the object.
    - `?block={block_id}` returns one subtree, marked as a partial document.
    - `?format=md` returns a read-only Markdown rendering.

    Partial documents and Markdown renderings cannot be sent back as whole
    document writes. Use `PATCH` operations to edit the object.

    List and search rows are compact: `id`, `name`, `type`, and the properties
    you request. They do not embed a type object. Request the fields you need
    instead of reading every object separately.

    Lists use `offset` and `limit`, with 25 rows by default. Responses include
    `total` and `has_more`, plus a narrowing hint when truncated. Chat messages
    use an order-id cursor instead.

    Search accepts full text in the JSON body's `query` field, for example
    `{"query":"meeting notes"}`. Cross-space search uses the currently loaded
    spaces. Its `total` is a lower bound when results are clipped; use `has_more`
    to continue paging. Warnings indicate when stores are still loading or
    unavailable, so retry later for a complete view.

    ## Edit with a batch of operations

    Send an `ops` array to the object's `PATCH` endpoint. For example, this body
    changes the title and appends a paragraph:

    ```json
    {
      "ops": [
        {
          "op": "set_properties",
          "set": { "name": "Meeting notes" }
        },
        {
          "op": "insert_blocks",
          "markdown": "Next step: review the proposal."
        }
      ]
    }
    ```

    The batch is atomic: an invalid operation rejects the whole request.
    Discover the accepted fields for each operation at
    `GET /v2/schemas/ops/{op}`.

    ### Concurrency, retries, and dry runs

    | Control | Behavior |
    | --- | --- |
    | `ETag` / `If-Match` | Object reads return an `etag` in the body and an `ETag` header. Send it back in `If-Match` to check for concurrent changes. A stale value returns `409` with the current etag. Without the header, the last write wins. |
    | `Idempotency-Key` | Resource mutations replay the stored response when retried with the same key and request. `POST /v2/validate` also accepts a key. Search requests do not. |
    | `?dry_run=true` | Resource mutations validate the request and report the outcome without committing. A dry run returns `200` where the committed create would return `201`. Each operation documents any limits to its dry-run result. |

    Chats use order ids and `last_state_id` for concurrency, and have no etag.

    Resource bodies reject unknown fields with `400` and name the offending
    field. Document bodies are capped at 10 MiB; structured bodies at 1 MiB.

    Deleting an object, type, or property archives it in Bin, where the Anytype
    app can restore it. Object deletion is limited by creator provenance; see
    the [delete operation](https://developers.anytype.io/docs/reference/v2/delete-object)
    for its requirements. Deleting a chat message, including any attachment
    cleanup that follows, is not an archive.

    ## Errors and warnings

    Errors from v2 handlers have this structure:

    ```json
    {
      "status": 400,
      "code": "...",
      "message": "...",
      "issues": [
        { "path": "...", "message": "...", "hint": "..." }
      ]
    }
    ```

    All four top-level fields are always present. `issues` is an empty array
    when there is no path to name. Issues identify the failing input and can
    describe the allowed values or how to repair the request.

    Some refusals occur before v2 handlers run:

    - Pairing, authentication, key-scope checks, request-origin checks, and the
      shared write rate limit use the older shared error envelope.
    - An unmatched route or an unhandled panic returns no error envelope.

    A read does not fail because it encounters content its representation
    cannot express. Such content is reported in `warnings` beside the result.

    ## Stream chat messages

    `GET /v2/spaces/{space_id}/chats/{chat_id}/messages/stream` opens a
    Server-Sent Events connection. It starts with the last `limit` messages as
    `message_added` events, then delivers live changes:

    - `message_added`, `message_updated`, and `message_deleted`
    - `reactions_updated`, `state_updated`, and `pinned_updated`

    Idle connections stay open with comment lines that clients ignore.

    Each addition carries the chat state id as its event id. An id-only frame
    after the opening window carries the highest such id. Send the last id back
    as `Last-Event-ID` to resume a dropped connection against the same node.

    **Only additions replay.** Edits, deletions, pins, and reactions do not
    change that state id. Re-read messages to refresh changes made while the
    connection was down.

    A `resync_required` event means the retained messages could not establish
    coverage of the gap since your last event id. Content outside the following
    window is unverified. The absence of this event does not guarantee a
    complete history: out-of-order additions or reindexing can create gaps the
    stream cannot detect. Re-read messages when you need certainty.

    ## Download files and icons

    Use `GET /v2/spaces/{space_id}/files/{file_id}/content` with a file id or the
    `icon_image` value from a space or member. The response contains bytes with
    the matching `Content-Type`.

    Downloads support byte ranges and conditional requests with `ETag` or
    `Last-Modified`. File preconditions use standard status codes, including
    `304` and `412`. Access is checked on every request.

    ## Discover schemas at runtime

    | Request | Result |
    | --- | --- |
    | `GET /v2/schemas` | Available schema kinds |
    | `GET /v2/schemas/{kind}` | The schema for one kind |
    | `GET /v2/schemas/ops/{op}` | The schema for one edit operation |

    The schemas support strict constrained decoding. Read them before writing
    requests, and use `POST /v2/validate` to check an AnyBlock document.
  contact:
    email: support@anytype.io
    name: Anytype Support
    url: https://anytype.io/contact
  license:
    name: Any Source Available License 1.0
    url: https://github.com/anyproto/anytype-api/blob/main/LICENSE.md
  termsOfService: https://anytype.io/terms_of_use
  title: Anytype API
  version: "2025-11-08"
openapi: 3.1.0
paths:
  /v2/auth/api_keys:
    post:
      security: []
      description: Exchanges a challenge_id from /v2/auth/challenges and the code
        revealed after Desktop approval for an api_key and the grant approved by the
        user. The grant states the permission, full space_ids, and whether all current
        and future user spaces are covered. Use the key as a bearer credential in
        the Authorization header. No existing API key is required.
      operationId: create_api_key
      parameters:
      - description: The version of the API to use
        in: header
        name: Anytype-Version
        required: true
        schema:
          default: "2025-11-08"
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateApiKeyRequest'
        description: The request body containing the challenge ID and code
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateApiKeyResponse'
          description: The API key and its approved grant
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
          description: Bad request
        "403":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
          description: Untrusted request origin or host
        "500":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServerError'
          description: Internal server error
      summary: Create an API key
      tags:
      - Auth
  /v2/auth/challenges:
    post:
      security: []
      description: Starts pairing for the named app and returns a challenge_id. The
        user chooses spaces and permissions in Anytype Desktop, then approves to reveal
        a 4-digit code. Submit the challenge_id and code to /v2/auth/api_keys. No
        existing API key is required.
      operationId: create_auth_challenge
      parameters:
      - description: The version of the API to use
        in: header
        name: Anytype-Version
        required: true
        schema:
          default: "2025-11-08"
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateChallengeRequest'
        description: The request body containing the app name
        required: true
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateChallengeResponse'
          description: The challenge ID associated with the started challenge
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
          description: Bad request
        "403":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
          description: Untrusted request origin or host
        "500":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServerError'
          description: Internal server error
      summary: Create a challenge
      tags:
      - Auth
  /v2/auth/whoami:
    get:
      description: 'Describes the key, not a person. Branch on `grant.restricted`:
        true means the key reaches only the spaces in `spaces`; false means every
        space, either an all-spaces grant or a legacy key with no grant. An all-spaces
        grant reports `space_count` and lists its spaces only when `spaces` is true.'
      operationId: auth_whoami
      parameters:
      - description: 'How grant.spaces[].id is spelled: compact (default) is the short
          space reference; full is the whole <cid>.<replicationKey> id, and the spelling
          to store outside this API'
        in: query
        name: ids
        schema:
          type: string
      - description: 'For an all-spaces grant: list the current live spaces in grant.spaces.
          Default false, the count alone'
        in: query
        name: spaces
        schema:
          type: boolean
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhoamiResponse'
          description: The key's grant, as it is enforced
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
      security:
      - bearerauth: []
      summary: Get API key details
      tags:
      - Auth
  /v2/schemas:
    get:
      operationId: list_schemas
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SchemaIndex'
          description: Schema index
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
      security:
      - bearerauth: []
      summary: List schemas
      tags:
      - Schemas
  /v2/schemas/{kind}:
    get:
      operationId: get_schema
      parameters:
      - description: Schema kind, as listed by GET /v2/schemas
        in: path
        name: kind
        required: true
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SchemaEntry'
          description: Schema + example
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unknown kind
      security:
      - bearerauth: []
      summary: Get a schema
      tags:
      - Schemas
  /v2/schemas/ops/{op}:
    get:
      description: The example is a single op object, ready to drop into an edit request's
        `ops` array, not a whole request body.
      operationId: get_op_schema
      parameters:
      - description: 'Op name: set_properties, update_block, replace_subtree, insert_blocks,
          move_block, delete_block, replace_text, set_cell, update_view, insert_view,
          move_view, delete_view, add_items, remove_items'
        in: path
        name: op
        required: true
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SchemaEntry'
          description: Schema + example
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unknown op
      security:
      - bearerauth: []
      summary: Get an edit operation schema
      tags:
      - Schemas
  /v2/search:
    post:
      description: Type keys and option names resolve per space; unresolved spaces
        produce warnings. Searches loaded spaces using query as full text over names
        and indexed content. total is a lower bound when clipped; use has_more to
        request further pages. Warnings report loading or unavailable stores. Each
        row carries space_id.
      operationId: search_global
      parameters:
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      - description: 'How each row''s space_id is spelled: compact (default) is the
          short space reference; full is the whole <cid>.<replicationKey> id, and
          the spelling to store outside this API'
        in: query
        name: ids
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequestDoc'
        description: Search request
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ObjectRow'
          description: Minimal object rows with space_id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid request
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
      security:
      - bearerauth: []
      summary: Search objects across spaces
      tags:
      - Search
  /v2/spaces:
    get:
      description: 'Returns only live spaces accessible to this API key. A space that
        is deleted, left, or still joining does not appear. has_not_granted_spaces
        is true when other live user spaces are excluded by the key''s grant; if a
        requested space is missing, ask the user to grant access. This flag is independent
        of pagination: total and has_more describe only accessible spaces.'
      operationId: list_spaces
      parameters:
      - description: compact (default) is the short space reference; full is the whole
          <cid>.<replicationKey> id, and the spelling to store outside this API
        in: query
        name: ids
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListSpacesResponse'
          description: Granted space rows and whether other live spaces require access
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
      security:
      - bearerauth: []
      summary: List spaces
      tags:
      - Spaces
    post:
      description: A retry the server already handled makes a second space unless
        it carries the same idempotency key. A dry run validates the body and stops
        there; creating a space cannot be simulated.
      operationId: create_space
      parameters:
      - description: Validate the body without creating
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: compact (default) is the short space reference; full is the whole
          <cid>.<replicationKey> id of the new space, and the spelling to store outside
          this API
        in: query
        name: ids
        schema:
          type: string
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSpaceRequest'
        description: The space to create
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Space'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Space'
          description: Created space
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a space
      tags:
      - Spaces
  /v2/spaces/{space_id}:
    get:
      description: Only live spaces are served. A space that is deleted, left, or
        still joining is a 404.
      operationId: get_space
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: compact (default) is the short space reference; full is the whole
          <cid>.<replicationKey> id, and the spelling to store outside this API
        in: query
        name: ids
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Space'
          description: The space row
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found
      security:
      - bearerauth: []
      summary: Get a space
      tags:
      - Spaces
    patch:
      description: At least one of the two fields must be present; a field left out
        keeps its current value. The space icon and the default object type are not
        writable through this API.
      operationId: update_space
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: compact (default) is the short space reference; full is the whole
          <cid>.<replicationKey> id, and the spelling to store outside this API
        in: query
        name: ids
        schema:
          type: string
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSpaceRequest'
        description: The fields to change
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Space'
          description: The updated space row
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found or not live
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Update a space
      tags:
      - Spaces
  /v2/spaces/{space_id}/chats:
    get:
      description: A row carries no unread counters. Per-chat unread state comes back
        with the messages read instead.
      operationId: list_chats
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Rows to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Rows to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ChatRow'
          description: Chat rows
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found
      security:
      - bearerauth: []
      summary: List chats
      tags:
      - Chat
    post:
      description: Messages are not blocks. Add them through the messages route; a
        document edit cannot reach them.
      operationId: create_chat
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateChatRequest'
        description: The chat to create
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatResult'
          description: Created chat row
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a chat
      tags:
      - Chat
  /v2/spaces/{space_id}/chats/{chat_id}/messages:
    get:
      description: '`after` alone walks forward, oldest first, continuing from `next_after`.
        Every other query is anchored at the newest end and walks backward from `next_before`.
        Both bounds are exclusive; messages are always ascending. `message_count`
        is the number of messages the chat holds now; `lifetime_message_count` counts
        every message ever posted. `offset` is refused.'
      operationId: get_chat_messages
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat object id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Return messages after this order id (exclusive)
        in: query
        name: after
        schema:
          type: string
      - description: Return messages before this order id (exclusive)
        in: query
        name: before
        schema:
          type: string
      - description: Messages to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      - description: counts (default) returns the emoji counts; full adds the participant
          ids behind each count
        in: query
        name: reactions
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatMessagesResponse'
          description: Messages + state + message_count
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Not a chat, or invalid params
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Chat not found
      security:
      - bearerauth: []
      summary: List chat messages
      tags:
      - Chat
    post:
      description: The text is markup source, so `*`, `[` and a mention tag mint real
        marks; escape a literal one with a backslash. The cap is 8000 UTF-16 code
        units, where one emoji can cost two or more. Attachments are object ids, at
        most 32, and each one's kind is taken from the target's layout.
      operationId: add_chat_message
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat object id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddChatMessageRequest'
        description: The message to send
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatMessageResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatMessageResult'
          description: Created message id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Chat not found
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Send a chat message
      tags:
      - Chat
  /v2/spaces/{space_id}/chats/{chat_id}/messages/{message_id}:
    delete:
      description: An attachment whose only reference was this message is erased for
        good afterwards, not moved to Bin. The response names those ids in `warnings`,
        and a dry run reports the same list without deleting anything. A message that
        does not exist is a 404 on the dry run too.
      operationId: delete_chat_message
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat object id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Message id
        in: path
        name: message_id
        required: true
        schema:
          type: string
      - description: Report what would be deleted, attachments included, without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatMessageResult'
          description: Deleted message id
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Chat or message not found
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Delete a chat message
      tags:
      - Chat
    patch:
      description: Every mark is re-derived from the text you send, so a mark the
        old text carried and the new text does not spell out is lost. Attachments,
        the reply target and the style survive. Editing another member's message is
        a 403.
      operationId: edit_chat_message
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat object id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Message id
        in: path
        name: message_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EditChatMessageRequest'
        description: The replacement text
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatMessageResult'
          description: Edited message id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Chat or message not found
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Update chat message text
      tags:
      - Chat
  /v2/spaces/{space_id}/chats/{chat_id}/messages/{message_id}/reactions:
    post:
      description: '`added` says which way the toggle went. A dry run predicts it,
        but when there is no account identity to predict with it omits the field and
        says so in `warnings`.'
      operationId: toggle_chat_reaction
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat object id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Message id
        in: path
        name: message_id
        required: true
        schema:
          type: string
      - description: Report the would-be outcome without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatReactionRequest'
        description: The emoji to toggle
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatReactionResult'
          description: Toggle outcome
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Chat or message not found
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Toggle a chat reaction
      tags:
      - Chat
  /v2/spaces/{space_id}/chats/{chat_id}/messages/stream:
    get:
      description: Only additions are replayed on resume. A message deleted, edited,
        or reacted to while you were disconnected keeps its old form in your copy
        until you read the messages again, because none of those restamp the state
        id a resume is measured against.
      operationId: stream_chat_messages
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Messages in the opening window
        in: query
        name: limit
        schema:
          default: 25
          maximum: 1000
          minimum: 1
          type: integer
      - description: Keepalive cadence in seconds
        in: query
        name: heartbeat
        schema:
          default: 30
          maximum: 60
          minimum: 1
          type: integer
      - description: Resume from this chat state id
        in: header
        name: Last-Event-ID
        schema:
          type: string
      responses:
        "200":
          content:
            text/event-stream:
              schema:
                type: string
          description: Server-Sent Events stream
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space or chat not found
        "429":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Too many streams held at once; close one, retrying cannot succeed
      security:
      - bearerauth: []
      summary: Stream chat messages
      tags:
      - Chat
  /v2/spaces/{space_id}/chats/{chat_id}/read:
    post:
      description: '`up_to` is inclusive; it and `last_state_id` come from one messages
        read: the newest order and the state''s id. An empty value would silently
        mark nothing, so both are required. Later messages stay unread. The reactions
        scope takes neither field. The receipt carries the chat''s state after the
        move when it could be read back.'
      operationId: read_chat
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Chat object id
        in: path
        name: chat_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Replay guard: the same key with the same body replays the stored
          response'
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChatReadRequest'
        description: The watermark move
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatReadResult'
          description: Watermark moved
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Chat not found
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Mark chat activity as read
      tags:
      - Chat
  /v2/spaces/{space_id}/collections:
    post:
      description: Item ids are checked against the space; an id that does not resolve
        there is refused rather than dropped.
      operationId: create_collection
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'Collection to create. Body schema and example: GET /v2/schemas/collection'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Created collection id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation or reference failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a collection
      tags:
      - Lists
  /v2/spaces/{space_id}/collections/{collection_id}/objects:
    get:
      description: A collection's objects are its membership, so without view the
        whole set comes back in the order the collection stores it and no view filter
        applies, even when the collection has one view. A view's filters and sorts
        apply only when view names it.
      operationId: get_collection_objects
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Collection object id
        in: path
        name: collection_id
        required: true
        schema:
          type: string
      - description: Stored view id (exact or unique suffix). Omitted, no view applies
          and the whole membership is returned.
        in: query
        name: view
        schema:
          type: string
      - description: Comma-separated property keys to include per row
        in: query
        name: fields
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ObjectRow'
          description: Minimal object rows
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Wrong-layout target or invalid params
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space, collection or view not found
      security:
      - bearerauth: []
      summary: List collection objects
      tags:
      - Lists
  /v2/spaces/{space_id}/collections/{collection_id}/views:
    get:
      operationId: get_collection_views
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Collection object id
        in: path
        name: collection_id
        required: true
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ViewObject'
          description: The stored views, with their sorts, filters and columns
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Wrong-layout target
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space or collection not found
      security:
      - bearerauth: []
      summary: List collection views
      tags:
      - Lists
  /v2/spaces/{space_id}/files:
    post:
      description: 'Send multipart/form-data with a `file` field, or JSON {"url":
        …}. A source that refuses the fetch, or a URL that cannot be fetched, is a
        400 naming /url; only a genuine server fault answers 500. The id that comes
        back is the one file blocks, image blocks and icon_image values reference.'
      operationId: upload_file
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              additionalProperties: false
              properties:
                name:
                  type: string
                url:
                  type: string
              required:
              - url
              type: object
          multipart/form-data:
            schema:
              additionalProperties: false
              properties:
                file:
                  format: binary
                  type: string
              required:
              - file
              type: object
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileUploadResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileUploadResult'
          description: Created file object id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure, or a source URL that did not yield the
            file
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Upload a file
      tags:
      - Files
  /v2/spaces/{space_id}/files/{file_id}/content:
    get:
      description: Returns a file or icon from this space. Pass a file id or the icon_image
        value from a space or member. Images support width variants. Range and conditional
        requests are supported.
      operationId: download_file
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: File or icon id
        in: path
        name: file_id
        required: true
        schema:
          type: string
      - description: Image variant width; zero selects the original
        in: query
        name: width
        schema:
          minimum: 0
          type: integer
      - description: Byte range
        in: header
        name: Range
        schema:
          type: string
      - description: Previously received ETag
        in: header
        name: If-None-Match
        schema:
          type: string
      - description: ETag or modification date for a range request
        in: header
        name: If-Range
        schema:
          type: string
      responses:
        "200":
          content:
            application/octet-stream:
              schema:
                format: binary
                type: string
          description: File contents; Content-Type matches the stored media type
          headers:
            ETag:
              description: File representation validator
              schema:
                type: string
            Cache-Control:
              description: Private cache; revalidate before reuse
              schema:
                type: string
            Last-Modified:
              description: File modification date, when available
              schema:
                type: string
            Content-Length:
              description: Response length in bytes
              schema:
                type: string
            Accept-Ranges:
              description: Supported range unit
              schema:
                type: string
        "206":
          content:
            application/octet-stream:
              schema:
                format: binary
                type: string
          description: Requested byte range
          headers:
            ETag:
              description: File representation validator
              schema:
                type: string
            Cache-Control:
              description: Private cache; revalidate before reuse
              schema:
                type: string
            Last-Modified:
              description: File modification date, when available
              schema:
                type: string
            Content-Length:
              description: Response length in bytes
              schema:
                type: string
            Accept-Ranges:
              description: Supported range unit
              schema:
                type: string
            Content-Range:
              description: Returned byte range or total file length
              schema:
                type: string
        "304":
          description: Not modified; no response body
          headers:
            ETag:
              description: File representation validator
              schema:
                type: string
            Cache-Control:
              description: Private cache; revalidate before reuse
              schema:
                type: string
            Last-Modified:
              description: File modification date, when available
              schema:
                type: string
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: File or icon not found in this space
        "412":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Request precondition failed
        "416":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid or unsatisfiable byte range
          headers:
            Content-Range:
              description: Returned byte range or total file length
              schema:
                type: string
        "500":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: File content could not be read
      security:
      - bearerauth: []
      summary: Get file content
      tags:
      - Files
    head:
      description: Returns the file or icon headers without a response body. Accepts
        the same ids as file download.
      operationId: head_file
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: File or icon id
        in: path
        name: file_id
        required: true
        schema:
          type: string
      - description: Image variant width; zero selects the original
        in: query
        name: width
        schema:
          minimum: 0
          type: integer
      responses:
        "200":
          description: File headers; no response body
          headers:
            ETag:
              description: File representation validator
              schema:
                type: string
            Cache-Control:
              description: Private cache; revalidate before reuse
              schema:
                type: string
            Last-Modified:
              description: File modification date, when available
              schema:
                type: string
            Content-Length:
              description: Response length in bytes
              schema:
                type: string
            Accept-Ranges:
              description: Supported range unit
              schema:
                type: string
        "304":
          description: Not modified; no response body
          headers:
            ETag:
              description: File representation validator
              schema:
                type: string
            Cache-Control:
              description: Private cache; revalidate before reuse
              schema:
                type: string
            Last-Modified:
              description: File modification date, when available
              schema:
                type: string
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: File or icon not found in this space
        "412":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Request precondition failed
        "500":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: File content could not be read
      security:
      - bearerauth: []
      summary: Get file headers
      tags:
      - Files
  /v2/spaces/{space_id}/members:
    get:
      operationId: list_members
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-MemberRow'
          description: Minimal member rows
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found or unavailable
      security:
      - bearerauth: []
      summary: List members
      tags:
      - Members
  /v2/spaces/{space_id}/members/me:
    get:
      description: The identity is taken from the account this API runs against; there
        is no member id to send.
      operationId: get_member_me
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemberRow'
          description: The caller's member row
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found, or no account identity
      security:
      - bearerauth: []
      summary: Get the current member
      tags:
      - Members
  /v2/spaces/{space_id}/objects:
    get:
      operationId: list_objects
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Comma-separated property keys to include per row
        in: query
        name: fields
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ObjectRow'
          description: Minimal object rows
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid fields query
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found or unavailable
      security:
      - bearerauth: []
      summary: List objects
      tags:
      - Objects
    post:
      description: A select value naming an option the property does not hold is refused
        unless `create_missing_options=true` is set. An unknown type or property key
        is rejected either way, with the closest matches named. The body is either
        a full AnyBlock document or the shortcut {type, name, properties, markdown};
        `formatVersion` or `blocks` picks the document form.
      operationId: create_object
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Create select options for names the property does not hold yet
          (default false: an unmatched name is refused)'
        in: query
        name: create_missing_options
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'AnyBlock object document. Body schema and example: GET /v2/schemas/object'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Created object id + etag
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation or reference failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create an object
      tags:
      - Objects
  /v2/spaces/{space_id}/objects/{object_id}:
    delete:
      description: Only objects this key created can be deleted. The creator is recorded
        at creation time and never added later, so objects made in the app, imported,
        made by another member, or made before this route shipped are refused for
        good. System objects are a 403 as well. A dry run reports the verdict without
        the checks that run at archive time, so a deletable verdict can still meet
        a 403.
      operationId: delete_object
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Object id
        in: path
        name: object_id
        required: true
        schema:
          type: string
      - description: Probe deletability without writing
        in: query
        name: dry_run
        schema:
          type: boolean
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Archived object, or the dry-run verdict. Deleting again is
            a 200 carrying a warning.
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: 'A type or a property: use their own delete routes'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Object or space not found
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Delete an object
      tags:
      - Objects
    get:
      description: A `block` subtree comes back flagged as a subtree, and no write
        path accepts that partial body. `format=md` is read-only; markdown cannot
        be sent back.
      operationId: get_object
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Object id
        in: path
        name: object_id
        required: true
        schema:
          type: string
      - description: Subset of properties,blocks (default both)
        in: query
        name: include
        schema:
          type: string
      - description: 'Return the outline instead of full blocks: every block''s indent/id/type
          plus its text truncated to 80 runes'
        in: query
        name: outline
        schema:
          type: boolean
      - description: Return only this block's subtree
        in: query
        name: block
        schema:
          type: string
      - description: compact (default) is the edit shape, where minted block ids relabel
          to short suffixes; full is the export shape, with full ids everywhere, and
          the shape to send back. Object references are full and inline in both.
        in: query
        name: ids
        schema:
          type: string
      - description: anyblock (default) or md
        in: query
        name: format
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                additionalProperties: {}
                type: object
          description: The flat AnyBlock document + etag
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Illegal parameter combination (ambiguous_input)
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Object or space not found
      security:
      - bearerauth: []
      summary: Get an object
      tags:
      - Objects
    patch:
      description: Applies ops in order as one atomic edit. A failed op or invalid
        result leaves the object unchanged. Text locators must match exactly one block.
        New block and view IDs are returned by payload position in `created_blocks`
        and `created_views`, compact by default or full with `ids=full`.
      operationId: patch_object
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Object id
        in: path
        name: object_id
        required: true
        schema:
          type: string
      - description: The etag the object must still carry
        in: header
        name: If-Match
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: ID spelling in created_blocks and created_views
        in: query
        name: ids
        schema:
          default: compact
          enum:
          - compact
          - full
          type: string
      - description: 'Create select options for names the property does not hold yet
          (default false: an unmatched name is refused)'
        in: query
        name: create_missing_options
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'PATCH ops envelope, an array of ops. Body schema and example
          per op: GET /v2/schemas/ops/<op>'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EditResult'
          description: New etag + created block ids + diff_stats
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid ops or post-op document
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Object, space, or referenced block not found
        "409":
          $ref: '#/components/responses/Conflict'
        "422":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Existing content cannot be represented losslessly for this
            edit
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Update an object
      tags:
      - Objects
  /v2/spaces/{space_id}/properties:
    get:
      operationId: list_properties
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-PropertyRow'
          description: Property rows
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found or unavailable
      security:
      - bearerauth: []
      summary: List properties
      tags:
      - Properties
    post:
      description: 'Names are not identities: without an explicit key, a name a visible
        property already carries is refused. Supply a different available key to create
        another property with that name; the response carries a warning.'
      operationId: create_property
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'Property to create. Body schema and example: GET /v2/schemas/property'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Created property id + key
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a property
      tags:
      - Properties
  /v2/spaces/{space_id}/properties/{key}:
    delete:
      operationId: delete_property
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Property key
        in: path
        name: key
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Archived property
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: No live property with this key. A property that is already
            deleted is a 404 too, not a second delete.
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Delete a property
      tags:
      - Properties
    patch:
      description: Only the display name can change. The key is the property's identity,
        and its format is fixed once it exists.
      operationId: update_property
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Property key
        in: path
        name: key
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'Fields of the property to change. Body schema and example: GET
          /v2/schemas/property'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Updated property
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Property not found
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Update a property
      tags:
      - Properties
  /v2/spaces/{space_id}/properties/{key}/options:
    get:
      operationId: list_property_options
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Property key
        in: path
        name: key
        required: true
        schema:
          type: string
      - description: Case-insensitive name prefix filter
        in: query
        name: prefix
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-OptionRow'
          description: Option rows
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Property not found
      security:
      - bearerauth: []
      summary: List property options
      tags:
      - Properties
  /v2/spaces/{space_id}/queries:
    post:
      description: Filter and sort property keys are checked against the type the
        query runs over; a key that type does not carry is refused.
      operationId: create_query
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Create select options for names the property does not hold yet
          (default false: an unmatched name is refused)'
        in: query
        name: create_missing_options
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'Query to create. Body schema and example: GET /v2/schemas/query'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Created query id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation or reference failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a query
      tags:
      - Lists
  /v2/spaces/{space_id}/queries/{query_id}/objects:
    get:
      description: Without view, the query's first stored view applies, so its filters
        and sorts shape the rows; when the query has several views a warning names
        the one applied and the others. A view's dynamic placeholders, such as the
        calling member, are resolved here; one that cannot be resolved becomes a warning
        rather than a silently empty result.
      operationId: get_query_objects
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Query object id
        in: path
        name: query_id
        required: true
        schema:
          type: string
      - description: Stored view id (exact or unique suffix). Omitted, the query's
          first view applies.
        in: query
        name: view
        schema:
          type: string
      - description: Comma-separated property keys to include per row
        in: query
        name: fields
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ObjectRow'
          description: Minimal object rows
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Wrong-layout target or invalid params
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space, query or view not found
      security:
      - bearerauth: []
      summary: List query results
      tags:
      - Lists
  /v2/spaces/{space_id}/queries/{query_id}/views:
    get:
      operationId: get_query_views
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Query object id
        in: path
        name: query_id
        required: true
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ViewObject'
          description: The stored views, with their sorts, filters and columns
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Wrong-layout target
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space or query not found
      security:
      - bearerauth: []
      summary: List query views
      tags:
      - Lists
  /v2/spaces/{space_id}/search:
    post:
      description: '`filter` and `filters` are two spellings of the same thing, the
        compact string and the structured array; sending both is refused. This is
        a read carried by POST because the query needs a body, so pagination stays
        in the query string and a `limit` or `offset` in the body is refused.'
      operationId: search_space
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequestDoc'
        description: Search request
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-ObjectRow'
          description: Minimal object rows
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid request (validation_failed / ambiguous_input)
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found
      security:
      - bearerauth: []
      summary: Search objects in a space
      tags:
      - Search
  /v2/spaces/{space_id}/templates:
    post:
      description: '`template_for` names the type key this template starts an object
        of.'
      operationId: create_template
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Create select options for names the property does not hold yet
          (default false: an unmatched name is refused)'
        in: query
        name: create_missing_options
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'AnyBlock template document. Body schema and example: GET /v2/schemas/template'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Created template id
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation or reference failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a template
      tags:
      - Templates
  /v2/spaces/{space_id}/types:
    get:
      operationId: list_types
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Items to skip
        in: query
        name: offset
        schema:
          default: 0
          type: integer
      - description: Items to return
        in: query
        name: limit
        schema:
          default: 25
          type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListResponse-TypeRow'
          description: Type rows
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Space not found or unavailable
      security:
      - bearerauth: []
      summary: List types
      tags:
      - Types
    post:
      description: A `property_definitions` entry naming a property that does not
        exist creates it alongside the type. The body is either the flat type body
        or an AnyBlock document with kind "object_type"; `formatVersion`, `kind` or
        `type_settings` picks the document form.
      operationId: create_type
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Create select options for names the property does not hold yet
          (default false: an unmatched name is refused)'
        in: query
        name: create_missing_options
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'Flat type body: GET /v2/schemas/type. Full document: GET /v2/schemas/type_document'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Dry run; validation result without committing
        "201":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Created type id + key
        "400":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failure
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Create a type
      tags:
      - Types
  /v2/spaces/{space_id}/types/{type}:
    delete:
      operationId: delete_type
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Type key
        in: path
        name: type
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Archived type
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: No live type with this key. A type that is already deleted
            is a 404 too, not a second delete.
        "409":
          $ref: '#/components/responses/Conflict'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Delete a type
      tags:
      - Types
    get:
      operationId: get_type
      parameters:
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Type key
        in: path
        name: type
        required: true
        schema:
          type: string
      - description: compact (default) is the edit shape, with short labels for minted
          view and block ids; full is the export shape, with full ids
        in: query
        name: ids
        schema:
          type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                additionalProperties: {}
                type: object
          description: The kind:objectType AnyBlock document + etag
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Type not found
      security:
      - bearerauth: []
      summary: Get a type
      tags:
      - Types
    patch:
      description: Takes an ops envelope or the type body. Ops add, remove and reorder
        one property at a time; a removal also drops its column from the views, except
        any view that groups, covers, sorts or filters by it. In the body, `property_definitions`
        replaces the whole field list rather than adding to it, and names under `removed`
        whatever that detached. `api_key` is create-only.
      operationId: update_type
      parameters:
      - description: The etag the type must still carry
        in: header
        name: If-Match
        schema:
          type: string
      - description: Space id
        in: path
        name: space_id
        required: true
        schema:
          type: string
      - description: Type key
        in: path
        name: type
        required: true
        schema:
          type: string
      - description: Validate and report without committing
        in: query
        name: dry_run
        schema:
          type: boolean
      - description: 'Create select options for names the property does not hold yet
          (default false: an unmatched name is refused)'
        in: query
        name: create_missing_options
        schema:
          type: boolean
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: Either an ops envelope (GET /v2/schemas/ops/add_property) or
          the fields of the type to change (GET /v2/schemas/type)
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateResult'
          description: Updated type
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "404":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Type not found
        "409":
          $ref: '#/components/responses/Conflict'
        "413":
          $ref: '#/components/responses/RequestTooLarge'
        "429":
          $ref: '#/components/responses/RateLimited'
      security:
      - bearerauth: []
      summary: Update a type
      tags:
      - Types
  /v2/validate:
    post:
      description: 'Structure and format rules only. Nothing is resolved against a
        space, so option names and a type''s property keys are not checked here. Findings
        come back as data: an invalid document is still a 200, carrying the issues,
        and a valid one carries empty lists.'
      operationId: validate
      parameters:
      - description: Retry key; identical requests replay, different requests conflict
        in: header
        name: Idempotency-Key
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'Document to validate. Body schema and example: GET /v2/schemas/object'
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidateResponse'
          description: Issue and warning lists, empty when the document is valid
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: '#/components/responses/Unauthorized'
        "403":
          $ref: '#/components/responses/Forbidden'
        "409":
          $ref: '#/components/responses/Conflict'
      security:
      - bearerauth: []
      summary: Validate an AnyBlock document
      tags:
      - Schemas
servers:
- url: http://127.0.0.1:31009
tags:
- description: Obtain an API key with Desktop approval, then inspect which spaces
    and permissions it grants.
  name: Auth
- description: The containers everything else lives in. Nearly every other route is
    scoped to one.
  name: Spaces
- description: 'Read and write whole AnyBlock documents: one GET returns an editable
    document, one PATCH edits it.'
  name: Objects
- description: Find objects by query, filter and sort, within one space or across
    all of them.
  name: Search
- description: 'An object''s shape: the properties it recommends and the views it
    opens with.'
  name: Types
- description: The typed key-value fields objects carry, and the option vocabularies
    select fields draw from.
  name: Properties
- description: Sets (a live query over a type) and collections (a hand-curated list),
    with their views.
  name: Lists
- description: Messages, reactions and read state. Chats store messages outside blocks,
    paged by order-id cursors.
  name: Chat
- description: Who is in a space, and which of them you are.
  name: Members
- description: Upload files and download file or icon content.
  name: Files
- description: Starting documents for a type.
  name: Templates
- description: 'The format itself: what a valid document looks like, what each PATCH
    op accepts, and a validator to check one against them. Read these before writing.'
  name: Schemas
