---
openapi: 3.1.0
info:
  title: Move Task List API
  summary: Read and write the tasks on a Move task list.
  description: |
    The public REST API for [Move](https://m0ve.app) — the personal
    timeline app that blends calendars, events and groups.

    This is the API over a single **task list**: a Kanban-style board
    that lives on a Move calendar. It is switched on per list from that
    list's Integrations page, which mints an API key.

    ## Authentication

    The API key is the whole credential and it names exactly one task
    list, which is why no list id appears in any path — the key already
    said which list. Send it as a bearer token:

        Authorization: Bearer move_xxxxxxxxxxxxxxxx

    or, for clients that can only send a fixed custom header:

        X-Move-Api-Key: move_xxxxxxxxxxxxxxxx

    A key that leaks can be rotated from the same Integrations page
    without touching the calendar it belongs to.

    ## Permissions

    A key is read-only unless writes are enabled on the list. A
    read-only key gets `403 read_only` from every write operation. The
    two permission levels are published as OAuth-style scope names in
    the [protected resource metadata](https://m0ve.app/.well-known/oauth-protected-resource):
    `tasks:read` and `tasks:write`.

    ## Naming a column

    Anywhere a column is named — the `status` filter, create, update
    and move — you may use its slug (`verify`), its display name
    (`Verify`) or its stored id (`section_2845be76`). Prefer the slug:
    it is readable and it is what the API returns alongside every id.

    ## Errors

    Every error is JSON with the same shape: a stable machine-readable
    `error` code, a human `message` that says how to fix it, and a
    `documentation_url`. Branch on `error`, not on the status code.
  version: 1.0.0
  termsOfService: https://m0ve.app/application-terms
  contact:
    name: Move API support
    url: https://m0ve.app/developers
    email: support@9thdesigns.com
servers:
- url: https://m0ve.app
  description: Move
externalDocs:
  description: Move API documentation
  url: https://docs.m0ve.app
tags:
- name: Task list
  description: 'The list itself: its columns, its counts and what this key may do
    to it.'
- name: Tasks
  description: The tasks on the list — reading, filtering, creating, updating and
    moving them.
- name: Comments
  description: The comment thread on a task.
security:
- moveApiKey: []
- moveApiKeyHeader: []
paths:
  "/api/v1/task-list":
    get:
      operationId: getTaskList
      summary: Get the task list this API key belongs to
      description: 'Returns the list the API key names — its title, its columns and
        how many tasks sit in each — plus what this key is allowed to do. Call this
        first: the `sections` it returns are the only valid values for `status` anywhere
        else in the API, so a client can discover the columns instead of hardcoding
        them.'
      tags:
      - Task list
      x-required-scope: tasks:read
      responses:
        '200':
          description: The task list.
          content:
            application/json:
              schema:
                type: object
                required:
                - list
                properties:
                  list:
                    "$ref": "#/components/schemas/TaskList"
        '401':
          description: The API key is missing, unrecognised, or its list has API access
            switched off.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/task-list/tasks":
    get:
      operationId: listTasks
      summary: List the tasks on the task list
      description: 'Returns a page of tasks. Every filter is optional and they compose,
        so `?status=verify&priority=high&due_before=2026-01-01T00:00:00Z` is one request.
        Results carry the list itself alongside them so a client can render a board
        from a single call. Use `include=none` when polling: comments and attachments
        are returned by default and they are the expensive part of the payload.'
      tags:
      - Tasks
      x-required-scope: tasks:read
      parameters:
      - name: status
        in: query
        required: false
        description: 'Filter by column. Accepts a column slug, its display name or
          its stored id, or a comma-separated list of them. Two reserved words cut
          across columns: `open` (not completed) and `completed`. `all` is the same
          as omitting the filter.'
        schema:
          type: string
        examples:
          oneColumn:
            value: verify
            summary: A single column, by slug
          severalColumns:
            value: todo,in-progress
            summary: More than one column
          openOnly:
            value: open
            summary: Everything not completed
      - name: completed
        in: query
        required: false
        description: Filter on the completion flag regardless of column. Truthy values
          are `true`, `1`, `yes` and `on`; anything else reads as false.
        schema:
          type: boolean
      - name: priority
        in: query
        required: false
        description: Filter by priority. Comma-separate to match more than one.
        schema:
          type: string
        examples:
          urgent:
            value: high
            summary: High priority only
      - name: source
        in: query
        required: false
        description: Filter by how the task arrived. Tasks created through this API
          carry `api`; the hosted intake form and the error inbox carry their own.
        schema:
          type: string
          examples:
          - api
      - name: assignee_user_id
        in: query
        required: false
        description: Only tasks assigned to this Move user id.
        schema:
          type: integer
          format: int64
      - name: due_before
        in: query
        required: false
        description: Only tasks due at or before this time. A value that does not
          parse is ignored rather than rejected, so an unused filter may be sent empty.
        schema:
          type: string
          format: date-time
      - name: due_after
        in: query
        required: false
        description: Only tasks due at or after this time.
        schema:
          type: string
          format: date-time
      - name: updated_since
        in: query
        required: false
        description: Only tasks changed at or after this time. This is the field to
          poll on for an incremental sync.
        schema:
          type: string
          format: date-time
      - name: q
        in: query
        required: false
        description: Case-insensitive substring search over task titles and notes.
        schema:
          type: string
      - name: include
        in: query
        required: false
        description: Which nested collections to embed in each task. Omit for both.
          Send `comments`, `attachments`, `comments,attachments`, or `none` for neither
          — `none` is simply a value that names neither collection.
        schema:
          type: string
          examples:
          - none
          - comments
          - comments,attachments
      - name: page
        in: query
        required: false
        description: Page number, starting at 1. A value below 1 is treated as 1.
        schema:
          type: integer
          format: int32
          minimum: 1
          default: 1
      - name: per_page
        in: query
        required: false
        description: Tasks per page. Values above the maximum are clamped to it.
        schema:
          type: integer
          format: int32
          minimum: 1
          maximum: 200
          default: 50
      responses:
        '200':
          description: A page of tasks.
          content:
            application/json:
              schema:
                type: object
                required:
                - list
                - tasks
                - pagination
                properties:
                  list:
                    "$ref": "#/components/schemas/TaskList"
                  tasks:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Task"
                  pagination:
                    "$ref": "#/components/schemas/Pagination"
        '401':
          description: The API key is missing, unrecognised, or its list has API access
            switched off.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      operationId: createTask
      summary: Create a task
      description: Adds a task to the list. Only `title` really matters; everything
        else has a sensible default. An unrecognised or absent `status` lands the
        task in the list's first column rather than being rejected. Send `multipart/form-data`
        with `files[]` to attach files at creation.
      tags:
      - Tasks
      x-required-scope: tasks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskCreateRequest"
            examples:
              minimal:
                summary: Just a title
                value:
                  title: Ship the changelog
              full:
                summary: Placed in a column, with a due date and an assignee
                value:
                  title: Ship the changelog
                  notes: Draft is in the shared doc.
                  status: in-progress
                  priority: high
                  due_date: '2026-09-01T17:00:00Z'
                  assignees:
                  - user_id: 42
                  actor: release-bot
          multipart/form-data:
            schema:
              allOf:
              - "$ref": "#/components/schemas/TaskCreateRequest"
              - type: object
                properties:
                  files:
                    type: array
                    description: Up to 20 files per task, 25MB each.
                    items:
                      type: string
                      format: binary
      responses:
        '201':
          description: The task that was created.
          content:
            application/json:
              schema:
                type: object
                required:
                - task
                properties:
                  task:
                    "$ref": "#/components/schemas/Task"
        '401':
          description: The API key is missing or unrecognised.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: This API key is read-only.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '413':
          description: The JSON request body is larger than 512KB.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: The task could not be saved. `details` carries the per-field
            errors.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/task-list/tasks/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: The task id. Scoped to the list the API key names — an id belonging
        to another list is a 404, not a way to read across calendars.
      schema:
        type: integer
        format: int64
    get:
      operationId: getTask
      summary: Get one task in full
      description: Returns a single task whole — status, priority, people, provenance,
        the comment thread and signed links to every attachment.
      tags:
      - Tasks
      x-required-scope: tasks:read
      parameters:
      - name: include
        in: query
        required: false
        description: Which nested collections to embed. Omit for both comments and
          attachments; send `none` for neither.
        schema:
          type: string
          examples:
          - none
          - comments
          - attachments
      responses:
        '200':
          description: The task.
          content:
            application/json:
              schema:
                type: object
                required:
                - task
                properties:
                  task:
                    "$ref": "#/components/schemas/Task"
        '401':
          description: The API key is missing or unrecognised.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: No task with that id on this list.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      operationId: updateTask
      summary: Update a task (PATCH)
      description: 'Applies the fields present in the body and leaves every other
        field alone — including with PUT, which behaves as a partial update here rather
        than a replacement. Omitting a field is not the same as sending it null. To
        change which column a task sits in, prefer `moveTask`: it keeps `completed`
        and the column from disagreeing.'
      tags:
      - Tasks
      x-required-scope: tasks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskUpdateRequest"
            examples:
              retitle:
                summary: Change the title
                value:
                  title: Ship the changelog today
              complete:
                summary: Mark it done
                value:
                  completed: true
          multipart/form-data:
            schema:
              allOf:
              - "$ref": "#/components/schemas/TaskUpdateRequest"
              - type: object
                properties:
                  files:
                    type: array
                    description: Files to add to the task. Existing attachments are
                      kept.
                    items:
                      type: string
                      format: binary
      responses:
        '200':
          description: The updated task.
          content:
            application/json:
              schema:
                type: object
                required:
                - task
                properties:
                  task:
                    "$ref": "#/components/schemas/Task"
        '401':
          description: The API key is missing or unrecognised.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: This API key is read-only.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: No task with that id on this list.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '413':
          description: The JSON request body is larger than 512KB.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: The task could not be saved. `details` carries the per-field
            errors.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    put:
      operationId: replaceTask
      summary: Update a task (PUT)
      description: 'Applies the fields present in the body and leaves every other
        field alone — including with PUT, which behaves as a partial update here rather
        than a replacement. Omitting a field is not the same as sending it null. To
        change which column a task sits in, prefer `moveTask`: it keeps `completed`
        and the column from disagreeing.'
      tags:
      - Tasks
      x-required-scope: tasks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskUpdateRequest"
            examples:
              retitle:
                summary: Change the title
                value:
                  title: Ship the changelog today
              complete:
                summary: Mark it done
                value:
                  completed: true
          multipart/form-data:
            schema:
              allOf:
              - "$ref": "#/components/schemas/TaskUpdateRequest"
              - type: object
                properties:
                  files:
                    type: array
                    description: Files to add to the task. Existing attachments are
                      kept.
                    items:
                      type: string
                      format: binary
      responses:
        '200':
          description: The updated task.
          content:
            application/json:
              schema:
                type: object
                required:
                - task
                properties:
                  task:
                    "$ref": "#/components/schemas/Task"
        '401':
          description: The API key is missing or unrecognised.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: This API key is read-only.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: No task with that id on this list.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '413':
          description: The JSON request body is larger than 512KB.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: The task could not be saved. `details` carries the per-field
            errors.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/task-list/tasks/{id}/move":
    parameters:
    - name: id
      in: path
      required: true
      description: The task id. Scoped to the list the API key names — an id belonging
        to another list is a 404, not a way to read across calendars.
      schema:
        type: integer
        format: int64
    post:
      operationId: moveTask
      summary: Move a task to another column
      description: Moves a task between columns. This is its own operation rather
        than a field on update because completion has to move with it — moving a task
        into the completed column marks it done, and moving it out un-marks it, so
        the flag and the column can never disagree. Name the column by slug, display
        name or id; `getTaskList` returns all three for every column.
      tags:
      - Tasks
      x-required-scope: tasks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - status
              properties:
                status:
                  type: string
                  description: The destination column, by slug, display name or stored
                    id.
                kanban_status:
                  type: string
                  description: Accepted as an alias for `status`. Prefer `status`.
            examples:
              toVerify:
                value:
                  status: verify
      responses:
        '200':
          description: The task after the move.
          content:
            application/json:
              schema:
                type: object
                required:
                - task
                properties:
                  task:
                    "$ref": "#/components/schemas/Task"
        '401':
          description: The API key is missing or unrecognised.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: This API key is read-only.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: No task with that id on this list.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: No `status` was sent, or it is not a column on this list. The
            `message` lists the columns that are.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/api/v1/task-list/tasks/{id}/comments":
    parameters:
    - name: id
      in: path
      required: true
      description: The task id. Scoped to the list the API key names — an id belonging
        to another list is a 404, not a way to read across calendars.
      schema:
        type: integer
        format: int64
    post:
      operationId: createTaskComment
      summary: Comment on a task
      description: 'Adds a comment to a task''s thread. An API key names a list, not
        a person, so every comment posted this way is a guest comment: send `author_name`
        (or `actor`) to say who it is from, or the thread will attribute it to "API".
        Send `multipart/form-data` with `files[]` to attach up to 5 files — a CI job
        can post the log it is complaining about rather than a link to it. Returns
        the whole task, so the caller sees the refreshed thread.'
      tags:
      - Comments
      x-required-scope: tasks:write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CommentCreateRequest"
            examples:
              fromCI:
                summary: A note from an automated caller
                value:
                  body: Reproduced on main at 4f2c1a9.
                  author_name: ci-bot
          multipart/form-data:
            schema:
              allOf:
              - "$ref": "#/components/schemas/CommentCreateRequest"
              - type: object
                properties:
                  files:
                    type: array
                    description: Up to 5 files per comment.
                    items:
                      type: string
                      format: binary
      responses:
        '201':
          description: The task, including the new comment.
          content:
            application/json:
              schema:
                type: object
                required:
                - task
                properties:
                  task:
                    "$ref": "#/components/schemas/Task"
        '401':
          description: The API key is missing or unrecognised.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: This API key is read-only.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: No task with that id on this list.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '413':
          description: The JSON request body is larger than 512KB.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: The comment had no `body`, carried too many files, or could
            not be saved.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '500':
          description: Something went wrong handling the request.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
components:
  securitySchemes:
    moveApiKey:
      type: http
      scheme: bearer
      bearerFormat: Move API key (move_…)
      description: |-
        The task list's API key, sent as `Authorization: Bearer move_…`. Mint and rotate it on the list's Integrations page.

        `tasks:read` — Read the task list, its columns and its tasks, including comments and signed attachment links.

        `tasks:write` — Create, update, move and comment on tasks. Granted only to a key whose task list has writes switched on.
      x-scopes:
        tasks:read: Read the task list, its columns and its tasks, including comments
          and signed attachment links.
        tasks:write: Create, update, move and comment on tasks. Granted only to a
          key whose task list has writes switched on.
    moveApiKeyHeader:
      type: apiKey
      in: header
      name: X-Move-Api-Key
      description: The same API key, for clients that can only send a fixed custom
        header.
      x-scopes:
        tasks:read: Read the task list, its columns and its tasks, including comments
          and signed attachment links.
        tasks:write: Create, update, move and comment on tasks. Granted only to a
          key whose task list has writes switched on.
  schemas:
    TaskList:
      type: object
      description: A task list and what this API key may do to it.
      required:
      - id
      - title
      - sections
      - counts
      - permissions
      properties:
        id:
          type: integer
          format: int64
          description: The task list id.
        title:
          type: string
          description: The list name as shown in Move.
        description:
          type:
          - string
          - 'null'
          description: The list summary, if one is set.
        calendar:
          type: object
          description: The Move calendar the list lives on.
          properties:
            id:
              type: integer
              format: int64
            name:
              type:
              - string
              - 'null'
            slug:
              type:
              - string
              - 'null'
        kanban_enabled:
          type: boolean
          description: Whether the list is in Kanban mode. A list that is not still
            answers the reserved `open` and `completed` status filters.
        sections:
          type: array
          description: The columns, in board order. These are the only valid `status`
            values.
          items:
            "$ref": "#/components/schemas/Section"
        counts:
          type: object
          description: Task totals for the whole list, not for the current page.
          properties:
            total:
              type: integer
            open:
              type: integer
            completed:
              type: integer
        permissions:
          type: object
          description: What this key may do. `write` false means every write returns
            403 read_only.
          properties:
            read:
              type: boolean
            write:
              type: boolean
        url:
          type:
          - string
          - 'null'
          format: uri
          description: The list in the Move web app.
    Section:
      type: object
      description: One column on the board.
      required:
      - id
      - slug
      - name
      properties:
        id:
          type: string
          description: The stored id. Survives a rename, which is why a client that
            caches a column should key off this.
          examples:
          - completed
          - section_2845be76
        slug:
          type: string
          description: The readable alias, derived from the name. Prefer this when
            a person or a model has to read it.
          examples:
          - verify
          - in-progress
        name:
          type: string
          description: The column name as shown on the board.
        color:
          type:
          - string
          - 'null'
          description: The column colour, if one is set.
        position:
          type: integer
          description: Left-to-right board order, from 0.
        task_count:
          type: integer
          description: How many tasks sit in this column.
    Task:
      type: object
      description: A task on the list. `comments` and `attachments` are present unless
        the request narrowed `include`.
      required:
      - id
      - title
      - status
      - completed
      properties:
        id:
          type: integer
          format: int64
        title:
          type:
          - string
          - 'null'
          description: The task title.
        notes:
          type:
          - string
          - 'null'
          description: Free-text notes on the task.
        status:
          type:
          - string
          - 'null'
          description: The stored column id. May name a column that has since been
            deleted, in which case `status_slug` and `status_name` are null.
        status_slug:
          type:
          - string
          - 'null'
          description: The column slug.
        status_name:
          type:
          - string
          - 'null'
          description: The column display name.
        completed:
          type: boolean
          description: Whether the task is done.
        priority:
          type:
          - string
          - 'null'
          enum:
          - low
          - normal
          - high
          -
          description: Task priority. New tasks default to `normal`.
        position:
          type:
          - integer
          - 'null'
          description: Order within its column.
        due_date:
          type:
          - string
          - 'null'
          format: date-time
        reminder_time:
          type:
          - string
          - 'null'
          format: date-time
        duration:
          type:
          - string
          - 'null'
          description: Estimated duration, as stored on the task.
        recurring:
          type:
          - object
          - 'null'
          description: Present only when the task repeats.
          properties:
            interval:
              type:
              - string
              - 'null'
              enum:
              - daily
              - weekly
              - bi-weekly
              - monthly
              - quarterly
              - yearly
              -
            ends_at:
              type:
              - string
              - 'null'
              format: date-time
        requesters:
          type: array
          description: Who asked for it.
          items:
            "$ref": "#/components/schemas/Person"
        assignees:
          type: array
          description: Who is doing it.
          items:
            "$ref": "#/components/schemas/Person"
        created_by:
          type:
          - object
          - 'null'
          description: The Move user who created the task. Null for a task created
            by an API key.
          properties:
            id:
              type: integer
              format: int64
            name:
              type:
              - string
              - 'null'
            email:
              type:
              - string
              - 'null'
        source:
          type:
          - object
          - 'null'
          description: How the task arrived, when it came from an integration rather
            than from the board. Tasks created through this API carry kind `api`.
          properties:
            kind:
              type:
              - string
              - 'null'
            label:
              type:
              - string
              - 'null'
            url:
              type:
              - string
              - 'null'
              format: uri
            reference:
              type:
              - string
              - 'null'
            environment:
              type:
              - string
              - 'null'
            level:
              type:
              - string
              - 'null'
            occurrences:
              type: integer
            last_seen_at:
              type:
              - string
              - 'null'
              format: date-time
            submitted_by:
              type:
              - string
              - 'null'
            submitted_by_email:
              type:
              - string
              - 'null'
        created_at:
          type:
          - string
          - 'null'
          format: date-time
        updated_at:
          type:
          - string
          - 'null'
          format: date-time
        url:
          type:
          - string
          - 'null'
          format: uri
          description: The task in the Move web app.
        comments:
          type: array
          items:
            "$ref": "#/components/schemas/Comment"
        attachments:
          type: array
          items:
            "$ref": "#/components/schemas/Attachment"
    TaskCreateRequest:
      type: object
      description: A new task. Only `title` is required.
      required:
      - title
      additionalProperties: false
      properties:
        title:
          type: string
          description: The task title.
        notes:
          type: string
          description: Free-text notes.
        status:
          type: string
          description: The column, by slug, display name or stored id.
        kanban_status:
          type: string
          description: Accepted as an alias for `status`.
        completed:
          type: boolean
          description: Wins over whatever the column implied, and drags the column
            with it.
        priority:
          type: string
          enum:
          - low
          - normal
          - high
        due_date:
          type: string
          format: date-time
        reminder_time:
          type: string
          format: date-time
        duration:
          type: string
          description: Estimated duration.
        assignees:
          type: array
          description: Who is doing it. A `user_id` must be a member of the list's
            calendar — an id that is not is dropped, so an API key cannot attach a
            stranger to a task. Guests (name and email) pass through untouched.
          items:
            "$ref": "#/components/schemas/Person"
        requesters:
          type: array
          description: Who asked for it. Same membership rule as `assignees`.
          items:
            "$ref": "#/components/schemas/Person"
        actor:
          type: string
          description: A label for whoever or whatever made this call, shown on the
            task.
          examples:
          - release-bot
    TaskUpdateRequest:
      type: object
      description: The fields to change. Anything omitted is left alone.
      minProperties: 1
      additionalProperties: false
      properties:
        title:
          type: string
          description: The task title.
        notes:
          type: string
          description: Free-text notes.
        status:
          type: string
          description: The column, by slug, display name or stored id.
        kanban_status:
          type: string
          description: Accepted as an alias for `status`.
        completed:
          type: boolean
          description: Wins over whatever the column implied, and drags the column
            with it.
        priority:
          type: string
          enum:
          - low
          - normal
          - high
        due_date:
          type: string
          format: date-time
        reminder_time:
          type: string
          format: date-time
        duration:
          type: string
          description: Estimated duration.
        assignees:
          type: array
          description: Who is doing it. A `user_id` must be a member of the list's
            calendar — an id that is not is dropped, so an API key cannot attach a
            stranger to a task. Guests (name and email) pass through untouched.
          items:
            "$ref": "#/components/schemas/Person"
        requesters:
          type: array
          description: Who asked for it. Same membership rule as `assignees`.
          items:
            "$ref": "#/components/schemas/Person"
        actor:
          type: string
          description: A label for whoever or whatever made this call, shown on the
            task.
          examples:
          - release-bot
    CommentCreateRequest:
      type: object
      description: A comment to add to a task's thread.
      required:
      - body
      additionalProperties: false
      properties:
        body:
          type: string
          description: The comment text.
        author_name:
          type: string
          description: Who the comment is from. Defaults to "API" when neither this
            nor `actor` is sent.
        author_email:
          type: string
          format: email
        actor:
          type: string
          description: Used as the author when `author_name` is absent.
        pinned:
          type: boolean
          description: Pin the comment to the top of the thread.
    Comment:
      type: object
      description: One comment. Replies hang off a top-level comment, one level deep.
      required:
      - id
      - body
      properties:
        id:
          type: integer
          format: int64
        body:
          type: string
        author:
          type:
          - string
          - 'null'
        author_user_id:
          type:
          - integer
          - 'null'
          format: int64
          description: Set when a Move user wrote it; null for a guest or an API comment.
        pinned:
          type: boolean
        resolved:
          type: boolean
        attachments:
          type: array
          items:
            "$ref": "#/components/schemas/Attachment"
        created_at:
          type:
          - string
          - 'null'
          format: date-time
        replies:
          type: array
          description: Replies to this comment. Present on top-level comments only.
          items:
            type: object
    Attachment:
      type: object
      description: A file attached to a task or a comment.
      required:
      - id
      - filename
      properties:
        id:
          type: integer
          format: int64
        filename:
          type: string
        content_type:
          type:
          - string
          - 'null'
        byte_size:
          type:
          - integer
          - 'null'
          format: int64
        checksum:
          type:
          - string
          - 'null'
        created_at:
          type:
          - string
          - 'null'
          format: date-time
        url:
          type:
          - string
          - 'null'
          format: uri
          description: A signed link that expires. Follow it now rather than storing
            it.
    Person:
      type: object
      description: Someone on a task — either a Move user (`user_id`) or a guest (`name`
        and `email`).
      properties:
        user_id:
          type:
          - integer
          - 'null'
          format: int64
        name:
          type:
          - string
          - 'null'
        email:
          type:
          - string
          - 'null'
          format: email
    Pagination:
      type: object
      description: Where this page sits in the filtered set. `total` counts every
        matching task, not the ones on this page.
      required:
      - page
      - per_page
      - total
      - pages
      properties:
        page:
          type: integer
          description: The page returned, from 1.
        per_page:
          type: integer
          description: How many were asked for, after clamping.
        total:
          type: integer
          description: Matching tasks across all pages.
        pages:
          type: integer
          description: How many pages that is.
    Error:
      type: object
      description: A failed request.
      required:
      - error
      - message
      properties:
        error:
          type: string
          description: A stable machine-readable code. Branch on this.
          enum:
          - missing_key
          - invalid_key
          - read_only
          - task_not_found
          - invalid_status
          - invalid_comment
          - too_many_files
          - invalid
          - body_too_large
          - server_error
        message:
          type: string
          description: A human-readable explanation that says how to fix it.
        details:
          type:
          - object
          - 'null'
          description: Per-field validation errors, when the failure was a validation
            failure.
          additionalProperties: true
        documentation_url:
          type: string
          format: uri
          description: Where this error is documented.
x-oauth-protected-resource: https://m0ve.app/.well-known/oauth-protected-resource
