{
  "openapi": "3.1.0",
  "info": {
    "title": "thisflow REST API",
    "version": "1.0.0",
    "summary": "Read and write your thisflow tasks from your own scripts and tools.",
    "description": "A small REST API for the tasks in thisflow, with personal tokens.\n\n- **Tokens:** create one in Settings → API (API and AI assistants) → Create token and send it as `Authorization: Bearer tf_…`. A token acts as you, with your roles in each project, and can be revoked there at any time.\n- **Tasks** are addressed by id or by code, such as `SAL-12`.\n- **Writes** go through the same commands as the apps, so roles, activity, mentions and sync behave the same.\n- **Dates** are `yyyy-mm-dd` in your time zone; times are `HH:MM`; timestamps are UTC.\n- **Errors** are JSON with an `error` code (the Error schema).\n- **Pagination:** GET /tasks returns the first `limit` tasks (default 50, at most 200) and `total`, the number that match. There is no offset or cursor; narrow the list with `view`, `project` and `q`.\n- **Limits:** request bodies up to 1 MB (413 `too_large` above). Each token may make 120 requests a minute, in bursts of up to 30, REST and MCP together; beyond that the answer is 429 `rate_limited` with `Retry-After`, the seconds to wait.\n- **Browsers:** the API only allows cross-origin requests from the thisflow app itself, so call it from a server, a script or a tool, not from a web page on another site.\n- **MCP:** the same token works for the MCP server at `/api/mcp` (Streamable HTTP).",
    "contact": {
      "name": "thisflow",
      "email": "help@thisflow.com",
      "url": "https://thisflow.com/developers/api"
    },
    "x-limits": {
      "requestBodyMaxBytes": 1048576,
      "listDefault": 50,
      "listMax": 200,
      "rateLimit": {
        "scope": "token",
        "perMinute": 120,
        "burst": 30
      }
    }
  },
  "externalDocs": {
    "description": "API reference",
    "url": "https://thisflow.com/developers/api"
  },
  "servers": [
    {
      "url": "https://app.thisflow.com/api/v1",
      "description": "thisflow"
    }
  ],
  "security": [
    {
      "bearerToken": []
    }
  ],
  "tags": [
    {
      "name": "Projects",
      "description": "The projects you can see, with their sections."
    },
    {
      "name": "Tasks",
      "description": "List, read, create, change and complete tasks, and comment on them."
    },
    {
      "name": "Specification",
      "description": "This document."
    }
  ],
  "paths": {
    "/projects": {
      "get": {
        "operationId": "listProjects",
        "tags": [
          "Projects"
        ],
        "summary": "List projects",
        "description": "Every project you can see that is not archived, your Inbox included, with its sections and how many open top-level tasks it has.",
        "responses": {
          "200": {
            "description": "Your projects.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                },
                "example": {
                  "projects": [
                    {
                      "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e02",
                      "name": "Inbox",
                      "key": "INB",
                      "inbox": true,
                      "workspace": "Personal",
                      "sections": [],
                      "openTasks": 3
                    },
                    {
                      "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                      "name": "Sales",
                      "key": "SAL",
                      "inbox": false,
                      "workspace": "Acme",
                      "sections": [
                        {
                          "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e11",
                          "name": "To do",
                          "status": "todo"
                        },
                        {
                          "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e12",
                          "name": "Doing",
                          "status": "in_progress"
                        },
                        {
                          "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e13",
                          "name": "Done",
                          "status": "done"
                        }
                      ],
                      "openTasks": 14
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl \"https://app.thisflow.com/api/v1/projects\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\""
          }
        ]
      }
    },
    "/tasks": {
      "get": {
        "operationId": "listTasks",
        "tags": [
          "Tasks"
        ],
        "summary": "List tasks",
        "description": "The tasks of one of the app's views, in every project you can see or in one, optionally searched. Today, Upcoming and Inbox list top-level tasks; Overdue, Someday and all include subtasks. Today and Overdue are measured against your date in your time zone.",
        "parameters": [
          {
            "name": "view",
            "in": "query",
            "description": "The view, as in the app: Today (due or started by today), Upcoming (later), Overdue (due before today), Inbox (the Inbox project, not waiting for a start date), Someday, or all.",
            "schema": {
              "default": "all",
              "type": "string",
              "enum": [
                "today",
                "upcoming",
                "overdue",
                "inbox",
                "someday",
                "all"
              ]
            }
          },
          {
            "name": "project",
            "in": "query",
            "description": "Only tasks in this project (an id from GET /projects).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Search the titles, notes and comments, as the app's search does.",
            "schema": {
              "examples": [
                "invoice"
              ],
              "type": "string"
            }
          },
          {
            "name": "completed",
            "in": "query",
            "description": "1 or true includes completed tasks (never in overdue); 0, false or left out lists only open tasks. Any other value is 400 invalid.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "How many tasks to return, 1 to 200. An integer outside is clamped; one that is not an integer is 400 invalid. There is no offset or cursor: total says how many match, and view, project and q narrow the list.",
            "schema": {
              "minimum": 1,
              "maximum": 200,
              "default": 50,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The first limit tasks that match, and how many match in all.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskList"
                },
                "example": {
                  "today": "2026-10-23",
                  "total": 1,
                  "tasks": [
                    {
                      "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                      "code": "SAL-12",
                      "title": "Call Anna",
                      "note": "",
                      "project": {
                        "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                        "name": "Sales"
                      },
                      "section": "To do",
                      "status": "todo",
                      "priority": 2,
                      "dueDate": "2026-10-23",
                      "dueTime": "15:00",
                      "startDate": null,
                      "someday": false,
                      "recurrence": null,
                      "assignees": [
                        {
                          "id": "u_8kq2m4",
                          "name": "Erik Lund"
                        }
                      ],
                      "tags": [
                        "calls"
                      ],
                      "parentId": null,
                      "completedAt": null,
                      "url": "https://app.thisflow.com/t/SAL-12"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Invalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl \"https://app.thisflow.com/api/v1/tasks?view=today\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\""
          }
        ]
      },
      "post": {
        "operationId": "createTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Create a task",
        "description": "Creates a task from one line of text, read exactly as quick add reads it (English and Swedish, in your time zone). Tags that do not exist yet are created in the project's workspace. A top-level task joins the first section of its project. Any role but viewer may add tasks.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTaskBody"
              },
              "example": {
                "text": "Call Anna tomorrow 15:00 p2 #Sales @calls"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new task.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDetail"
                },
                "example": {
                  "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                  "code": "SAL-12",
                  "title": "Call Anna",
                  "note": "",
                  "project": {
                    "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                    "name": "Sales"
                  },
                  "section": "To do",
                  "status": "todo",
                  "priority": 2,
                  "dueDate": "2026-10-23",
                  "dueTime": "15:00",
                  "startDate": null,
                  "someday": false,
                  "recurrence": null,
                  "assignees": [
                    {
                      "id": "u_8kq2m4",
                      "name": "Erik Lund"
                    }
                  ],
                  "tags": [
                    "calls"
                  ],
                  "parentId": null,
                  "completedAt": null,
                  "url": "https://app.thisflow.com/t/SAL-12",
                  "subtasks": [],
                  "comments": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Invalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://app.thisflow.com/api/v1/tasks\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\":\"Call Anna tomorrow 15:00 p2 #Sales @calls\"}'"
          }
        ]
      }
    },
    "/tasks/{idOrCode}": {
      "get": {
        "operationId": "getTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Get a task",
        "description": "One task with its subtasks and comments.",
        "parameters": [
          {
            "$ref": "#/components/parameters/idOrCode"
          }
        ],
        "responses": {
          "200": {
            "description": "The task.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDetail"
                },
                "example": {
                  "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                  "code": "SAL-12",
                  "title": "Call Anna",
                  "note": "",
                  "project": {
                    "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                    "name": "Sales"
                  },
                  "section": "To do",
                  "status": "todo",
                  "priority": 2,
                  "dueDate": "2026-10-23",
                  "dueTime": "15:00",
                  "startDate": null,
                  "someday": false,
                  "recurrence": null,
                  "assignees": [
                    {
                      "id": "u_8kq2m4",
                      "name": "Erik Lund"
                    }
                  ],
                  "tags": [
                    "calls"
                  ],
                  "parentId": null,
                  "completedAt": null,
                  "url": "https://app.thisflow.com/t/SAL-12",
                  "subtasks": [
                    {
                      "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d61",
                      "code": "SAL-13",
                      "title": "Find the last offer",
                      "note": "",
                      "project": {
                        "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                        "name": "Sales"
                      },
                      "section": "To do",
                      "status": "todo",
                      "priority": 2,
                      "dueDate": null,
                      "dueTime": null,
                      "startDate": null,
                      "someday": false,
                      "recurrence": null,
                      "assignees": [],
                      "tags": [],
                      "parentId": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                      "completedAt": null,
                      "url": "https://app.thisflow.com/t/SAL-13"
                    }
                  ],
                  "comments": [
                    {
                      "id": "0199f3a6-77e0-7b1c-a2d3-e4f5a6b7c8d9",
                      "author": "Erik Lund",
                      "body": "Sent the draft, waiting for Anna.",
                      "createdAt": "2026-10-22T09:41:07.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl \"https://app.thisflow.com/api/v1/tasks/SAL-12\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\""
          }
        ]
      },
      "patch": {
        "operationId": "updateTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Update a task",
        "description": "Changes only the fields you send; null clears a date or time. Each field is its own change, so a teammate's edit to another field is kept.",
        "parameters": [
          {
            "$ref": "#/components/parameters/idOrCode"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateTaskBody"
              },
              "example": {
                "priority": 1,
                "dueDate": "2026-10-24"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The task after the change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDetail"
                },
                "example": {
                  "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                  "code": "SAL-12",
                  "title": "Call Anna",
                  "note": "",
                  "project": {
                    "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                    "name": "Sales"
                  },
                  "section": "To do",
                  "status": "todo",
                  "priority": 1,
                  "dueDate": "2026-10-24",
                  "dueTime": "15:00",
                  "startDate": null,
                  "someday": false,
                  "recurrence": null,
                  "assignees": [
                    {
                      "id": "u_8kq2m4",
                      "name": "Erik Lund"
                    }
                  ],
                  "tags": [
                    "calls"
                  ],
                  "parentId": null,
                  "completedAt": null,
                  "url": "https://app.thisflow.com/t/SAL-12",
                  "subtasks": [
                    {
                      "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d61",
                      "code": "SAL-13",
                      "title": "Find the last offer",
                      "note": "",
                      "project": {
                        "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                        "name": "Sales"
                      },
                      "section": "To do",
                      "status": "todo",
                      "priority": 2,
                      "dueDate": null,
                      "dueTime": null,
                      "startDate": null,
                      "someday": false,
                      "recurrence": null,
                      "assignees": [],
                      "tags": [],
                      "parentId": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                      "completedAt": null,
                      "url": "https://app.thisflow.com/t/SAL-13"
                    }
                  ],
                  "comments": [
                    {
                      "id": "0199f3a6-77e0-7b1c-a2d3-e4f5a6b7c8d9",
                      "author": "Erik Lund",
                      "body": "Sent the draft, waiting for Anna.",
                      "createdAt": "2026-10-22T09:41:07.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Invalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X PATCH \"https://app.thisflow.com/api/v1/tasks/SAL-12\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"priority\":1,\"dueDate\":\"2026-10-24\"}'"
          }
        ]
      }
    },
    "/tasks/{idOrCode}/complete": {
      "post": {
        "operationId": "completeTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Complete or reopen a task",
        "description": "Completes the task, as ticking it in the app does: a top-level task moves to its project's Done section when there is one, and a repeating task rolls forward to its next date instead. Send { \"completed\": false } to reopen it.",
        "parameters": [
          {
            "$ref": "#/components/parameters/idOrCode"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompleteTaskBody"
              },
              "example": {
                "completed": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The task after the change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDetail"
                },
                "example": {
                  "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                  "code": "SAL-12",
                  "title": "Call Anna",
                  "note": "",
                  "project": {
                    "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                    "name": "Sales"
                  },
                  "section": "Done",
                  "status": "done",
                  "priority": 2,
                  "dueDate": "2026-10-23",
                  "dueTime": "15:00",
                  "startDate": null,
                  "someday": false,
                  "recurrence": null,
                  "assignees": [
                    {
                      "id": "u_8kq2m4",
                      "name": "Erik Lund"
                    }
                  ],
                  "tags": [
                    "calls"
                  ],
                  "parentId": null,
                  "completedAt": "2026-10-23T14:02:55.000Z",
                  "url": "https://app.thisflow.com/t/SAL-12",
                  "subtasks": [
                    {
                      "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d61",
                      "code": "SAL-13",
                      "title": "Find the last offer",
                      "note": "",
                      "project": {
                        "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                        "name": "Sales"
                      },
                      "section": "To do",
                      "status": "todo",
                      "priority": 2,
                      "dueDate": null,
                      "dueTime": null,
                      "startDate": null,
                      "someday": false,
                      "recurrence": null,
                      "assignees": [],
                      "tags": [],
                      "parentId": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                      "completedAt": null,
                      "url": "https://app.thisflow.com/t/SAL-13"
                    }
                  ],
                  "comments": [
                    {
                      "id": "0199f3a6-77e0-7b1c-a2d3-e4f5a6b7c8d9",
                      "author": "Erik Lund",
                      "body": "Sent the draft, waiting for Anna.",
                      "createdAt": "2026-10-22T09:41:07.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Invalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://app.thisflow.com/api/v1/tasks/SAL-12/complete\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"completed\":true}'"
          }
        ]
      }
    },
    "/tasks/{idOrCode}/comments": {
      "post": {
        "operationId": "addComment",
        "tags": [
          "Tasks"
        ],
        "summary": "Add a comment",
        "description": "Adds a comment to the task as you.",
        "parameters": [
          {
            "$ref": "#/components/parameters/idOrCode"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommentBody"
              },
              "example": {
                "body": "Sent the draft, waiting for Anna."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The task with its comments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDetail"
                },
                "example": {
                  "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                  "code": "SAL-12",
                  "title": "Call Anna",
                  "note": "",
                  "project": {
                    "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                    "name": "Sales"
                  },
                  "section": "To do",
                  "status": "todo",
                  "priority": 2,
                  "dueDate": "2026-10-23",
                  "dueTime": "15:00",
                  "startDate": null,
                  "someday": false,
                  "recurrence": null,
                  "assignees": [
                    {
                      "id": "u_8kq2m4",
                      "name": "Erik Lund"
                    }
                  ],
                  "tags": [
                    "calls"
                  ],
                  "parentId": null,
                  "completedAt": null,
                  "url": "https://app.thisflow.com/t/SAL-12",
                  "subtasks": [
                    {
                      "id": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d61",
                      "code": "SAL-13",
                      "title": "Find the last offer",
                      "note": "",
                      "project": {
                        "id": "0199f3a2-5b1c-7d2e-9f30-4a5b6c7d8e01",
                        "name": "Sales"
                      },
                      "section": "To do",
                      "status": "todo",
                      "priority": 2,
                      "dueDate": null,
                      "dueTime": null,
                      "startDate": null,
                      "someday": false,
                      "recurrence": null,
                      "assignees": [],
                      "tags": [],
                      "parentId": "0199f3a4-0c21-7a6b-8d4e-1f2a3b4c5d60",
                      "completedAt": null,
                      "url": "https://app.thisflow.com/t/SAL-13"
                    }
                  ],
                  "comments": [
                    {
                      "id": "0199f3a6-77e0-7b1c-a2d3-e4f5a6b7c8d9",
                      "author": "Erik Lund",
                      "body": "Sent the draft, waiting for Anna.",
                      "createdAt": "2026-10-22T09:41:07.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Invalid"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://app.thisflow.com/api/v1/tasks/SAL-12/comments\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"body\":\"Sent the draft, waiting for Anna.\"}'"
          }
        ]
      }
    },
    "/overdue/move-to-today": {
      "post": {
        "operationId": "moveOverdueToToday",
        "tags": [
          "Tasks"
        ],
        "summary": "Move overdue tasks to today",
        "description": "Moves your own open tasks that were due before today to today, as Today's Move to today does: tasks assigned to you, and unassigned tasks in your personal workspace. Teammates' tasks stay where they are; a task you may not change is skipped.",
        "responses": {
          "200": {
            "description": "How many tasks moved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MoveOverdueResult"
                },
                "example": {
                  "moved": 2,
                  "skipped": 0,
                  "today": "2026-10-23",
                  "tomorrow": "2026-10-24"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST \"https://app.thisflow.com/api/v1/overdue/move-to-today\" \\\n  -H \"Authorization: Bearer $THISFLOW_TOKEN\""
          }
        ]
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "tags": [
          "Specification"
        ],
        "summary": "Get this document",
        "description": "This OpenAPI 3.1 document, as JSON. No token needed; it may be cached for an hour and answers If-None-Match with 304.",
        "security": [],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl \"https://app.thisflow.com/api/v1/openapi.json\""
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "tf_ followed by 43 characters",
        "description": "A personal token from Settings → API (API and AI assistants) → Create token. It acts as you, with your roles, until you revoke it."
      }
    },
    "parameters": {
      "idOrCode": {
        "name": "idOrCode",
        "in": "path",
        "required": true,
        "description": "The task's id, or its code such as SAL-12.",
        "schema": {
          "type": "string",
          "maxLength": 80,
          "examples": [
            "SAL-12"
          ]
        }
      }
    },
    "headers": {
      "RetryAfter": {
        "description": "Seconds to wait before the next request with this token.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "examples": [
            1
          ]
        }
      },
      "WWWAuthenticate": {
        "description": "The scheme to authenticate with: a bearer token.",
        "schema": {
          "type": "string",
          "const": "Bearer realm=\"thisflow\""
        }
      }
    },
    "responses": {
      "Invalid": {
        "description": "The request does not validate: issues lists each field that did not, or message says why the change was refused (error is invalid_view for an unknown view).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "invalid",
              "issues": [
                {
                  "code": "custom",
                  "path": [
                    "dueDate"
                  ],
                  "message": "Expected a date as yyyy-mm-dd"
                }
              ]
            }
          }
        }
      },
      "Unauthenticated": {
        "description": "No token, or one that is unknown or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "unauthenticated"
            }
          }
        },
        "headers": {
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WWWAuthenticate"
          }
        }
      },
      "Forbidden": {
        "description": "Your role in the project does not allow this, such as a viewer changing a task.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "forbidden",
              "message": "A viewer cannot do this"
            }
          }
        }
      },
      "NotFound": {
        "description": "No task or project you can see has this id or code.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "not_found",
              "message": "Task not found"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests with this token: 120 a minute, in bursts of up to 30. Retry-After (and retryAfter) says how many seconds to wait.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "rate_limited",
              "message": "Too many requests with this token: 120 a minute, bursts of up to 30. Try again in 1 s.",
              "retryAfter": 1
            }
          }
        },
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        }
      },
      "Error": {
        "description": "Any other error: plan_limit (402) when your plan does not allow it, conflict (409), too_large (413, a body over 1 MB) or internal_error (500).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "internal_error"
            }
          }
        }
      }
    },
    "schemas": {
      "Task": {
        "description": "A task, as every endpoint returns it.",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "code": {
            "type": "string",
            "description": "The project key and the task's number, such as SAL-12. Works wherever an id does."
          },
          "title": {
            "type": "string"
          },
          "note": {
            "type": "string",
            "description": "The note (Markdown), or an empty string."
          },
          "project": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "description": "The project the task is in."
          },
          "section": {
            "description": "The name of its section, or null.",
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "todo",
              "in_progress",
              "in_review",
              "done"
            ],
            "description": "done when completed, else the status of its section (todo without one)."
          },
          "priority": {
            "description": "1 is the highest (P1), 4 is none.",
            "type": "integer",
            "enum": [
              1,
              2,
              3,
              4
            ]
          },
          "dueDate": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The due date in your time zone."
          },
          "dueTime": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                "examples": [
                  "15:00"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The time on the due date, or null for all day."
          },
          "startDate": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The day it starts showing in Today."
          },
          "someday": {
            "type": "boolean"
          },
          "recurrence": {
            "description": "How it repeats, as an RRULE (FREQ=WEEKLY;BYDAY=MO), or null.",
            "type": [
              "string",
              "null"
            ]
          },
          "assignees": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Person"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Tag names."
          },
          "parentId": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "The parent task's id for a subtask, else null."
          },
          "completedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was completed (UTC), or null while open."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Opens the task in thisflow."
          }
        },
        "required": [
          "id",
          "code",
          "title",
          "note",
          "project",
          "section",
          "status",
          "priority",
          "dueDate",
          "dueTime",
          "startDate",
          "someday",
          "recurrence",
          "assignees",
          "tags",
          "parentId",
          "completedAt",
          "url"
        ]
      },
      "TaskDetail": {
        "description": "A task with its subtasks and comments.",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "code": {
            "type": "string",
            "description": "The project key and the task's number, such as SAL-12. Works wherever an id does."
          },
          "title": {
            "type": "string"
          },
          "note": {
            "type": "string",
            "description": "The note (Markdown), or an empty string."
          },
          "project": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "description": "The project the task is in."
          },
          "section": {
            "description": "The name of its section, or null.",
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "todo",
              "in_progress",
              "in_review",
              "done"
            ],
            "description": "done when completed, else the status of its section (todo without one)."
          },
          "priority": {
            "description": "1 is the highest (P1), 4 is none.",
            "type": "integer",
            "enum": [
              1,
              2,
              3,
              4
            ]
          },
          "dueDate": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The due date in your time zone."
          },
          "dueTime": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                "examples": [
                  "15:00"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The time on the due date, or null for all day."
          },
          "startDate": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The day it starts showing in Today."
          },
          "someday": {
            "type": "boolean"
          },
          "recurrence": {
            "description": "How it repeats, as an RRULE (FREQ=WEEKLY;BYDAY=MO), or null.",
            "type": [
              "string",
              "null"
            ]
          },
          "assignees": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Person"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Tag names."
          },
          "parentId": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "description": "The parent task's id for a subtask, else null."
          },
          "completedAt": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was completed (UTC), or null while open."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Opens the task in thisflow."
          },
          "subtasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            },
            "description": "Its open and completed subtasks."
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            }
          }
        },
        "required": [
          "id",
          "code",
          "title",
          "note",
          "project",
          "section",
          "status",
          "priority",
          "dueDate",
          "dueTime",
          "startDate",
          "someday",
          "recurrence",
          "assignees",
          "tags",
          "parentId",
          "completedAt",
          "url",
          "subtasks",
          "comments"
        ]
      },
      "Comment": {
        "description": "A comment on a task.",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "author": {
            "type": "string",
            "description": "The author's name."
          },
          "body": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "author",
          "body",
          "createdAt"
        ]
      },
      "Person": {
        "description": "Someone you share a project with.",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The user id."
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "Project": {
        "description": "A project you can see.",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "The project's name; the Inbox is called Inbox."
          },
          "key": {
            "type": "string",
            "description": "The prefix of its task codes, such as SAL in SAL-12."
          },
          "inbox": {
            "type": "boolean",
            "description": "true for your Inbox."
          },
          "workspace": {
            "type": "string",
            "description": "The name of the project's workspace."
          },
          "sections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Section"
            },
            "description": "Its sections in order: list headings and board columns."
          },
          "openTasks": {
            "type": "integer",
            "minimum": 0,
            "description": "Open top-level tasks in it."
          }
        },
        "required": [
          "id",
          "name",
          "key",
          "inbox",
          "workspace",
          "sections",
          "openTasks"
        ]
      },
      "Section": {
        "description": "A section of a project: a list heading and a board column.",
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "todo",
              "in_progress",
              "in_review",
              "done"
            ],
            "description": "What the section means on the board: a task in it has this status."
          }
        },
        "required": [
          "id",
          "name",
          "status"
        ]
      },
      "ProjectList": {
        "description": "The answer of GET /projects.",
        "type": "object",
        "properties": {
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          }
        },
        "required": [
          "projects"
        ]
      },
      "TaskList": {
        "description": "The answer of GET /tasks.",
        "type": "object",
        "properties": {
          "today": {
            "type": "string",
            "description": "Your date today, in your time zone: what Today and Overdue are measured against.",
            "format": "date",
            "examples": [
              "2026-10-23"
            ]
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Every task that matches; tasks holds the first limit of them."
          },
          "tasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            },
            "description": "Sorted by due date (none last), priority, then position."
          }
        },
        "required": [
          "today",
          "total",
          "tasks"
        ]
      },
      "MoveOverdueResult": {
        "description": "What Move to today did.",
        "type": "object",
        "properties": {
          "moved": {
            "type": "integer",
            "minimum": 0
          },
          "skipped": {
            "type": "integer",
            "minimum": 0,
            "description": "Overdue tasks you may not change, left as they were."
          },
          "today": {
            "type": "string",
            "format": "date",
            "examples": [
              "2026-10-23"
            ]
          },
          "tomorrow": {
            "type": "string",
            "format": "date",
            "examples": [
              "2026-10-23"
            ]
          }
        },
        "required": [
          "moved",
          "skipped",
          "today",
          "tomorrow"
        ]
      },
      "Error": {
        "description": "Every error answer has this shape.",
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "What went wrong: invalid, invalid_view, unauthenticated, forbidden, not_found, conflict, plan_limit, too_large, rate_limited or internal_error.",
            "examples": [
              "not_found"
            ]
          },
          "message": {
            "description": "A sentence for people, when there is one.",
            "type": "string"
          },
          "issues": {
            "description": "For invalid: each field that did not validate.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "path": {
                  "type": "array",
                  "items": {
                    "type": [
                      "string",
                      "number"
                    ]
                  }
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "code",
                "path",
                "message"
              ],
              "additionalProperties": {}
            }
          },
          "retryAfter": {
            "description": "For rate_limited: the seconds to wait before the next request, as in the Retry-After header.",
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "error"
        ]
      },
      "CreateTaskBody": {
        "description": "A new task, in natural language.",
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000,
            "description": "The task in natural language, read like quick add in English or Swedish: a date or time, p1 to p4, #project, @tag and +person become fields, the rest is the title.",
            "examples": [
              "Call Anna tomorrow 15:00 p2 #Sales @calls"
            ]
          },
          "projectId": {
            "description": "The project to add it to. Wins over a #project in the text. Without either, the task goes to the Inbox.",
            "type": "string",
            "format": "uuid"
          },
          "note": {
            "description": "The task's note (Markdown).",
            "type": "string",
            "maxLength": 20000
          },
          "parentId": {
            "description": "Make it a subtask of this task: its id or its code, such as SAL-12. The subtask joins the parent's project.",
            "type": "string",
            "maxLength": 80
          }
        },
        "required": [
          "text"
        ]
      },
      "UpdateTaskBody": {
        "description": "The fields to change; at least one.",
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "description": "The title, as it is (not read as quick add)."
          },
          "note": {
            "type": "string",
            "maxLength": 20000,
            "description": "The note (Markdown)."
          },
          "priority": {
            "description": "1 is the highest (P1), 4 is none.",
            "type": "integer",
            "enum": [
              1,
              2,
              3,
              4
            ]
          },
          "dueDate": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The due date in your time zone, or null to clear it."
          },
          "dueTime": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                "examples": [
                  "15:00"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "A time of day on the due date, HH:MM (24 h), or null for all day."
          },
          "startDate": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The day the task starts showing in Today, or null."
          },
          "someday": {
            "type": "boolean",
            "description": "true moves the task to Someday."
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "description": "Move the task to another project you can edit."
          },
          "sectionId": {
            "type": "string",
            "format": "uuid",
            "description": "Move the task to a section of its project (an id from GET /projects)."
          },
          "assigneeIds": {
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The people assigned, by user id. Replaces the current list; [] clears it."
          }
        }
      },
      "CompleteTaskBody": {
        "description": "Send {} to complete the task.",
        "type": "object",
        "properties": {
          "completed": {
            "default": true,
            "description": "false reopens a completed task.",
            "type": "boolean"
          },
          "dueDate": {
            "description": "The due date you last read. On a repeating task the call does nothing if the task has moved on to another occurrence, so a retried call never completes two.",
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "examples": [
                  "2026-10-23"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "CommentBody": {
        "description": "A new comment.",
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000,
            "description": "The comment (Markdown). @name mentions notify, as in the app.",
            "examples": [
              "Sent the draft, waiting for Anna."
            ]
          }
        },
        "required": [
          "body"
        ]
      }
    }
  }
}
