---
title: "Update Task"
method: PATCH
path: "/gtm-internal/tasks/{task_id}"
tags: ["gtm-internal"]
---

# Update Task

`PATCH /gtm-internal/tasks/{task_id}`

## Request

- Base URL: `https://api-v1.unusual.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api-v1.unusual.ai/gtm-internal/tasks/{task_id}`
- Auth: OAuth 2
  - Password
  - Token URL: `/auth/login`

Patch a task by id. Only fields present in the body are applied (an
explicit null clears). `status`/`disposition` are dual-written via
`apply_task_disposition` (work-layer expand/contract), so a sweep survives
the status backfill. Soft-delete = set `killed_at` (or `disposition`
="archived"); restore = `killed_at: null`. Mirrors the MCP `update_task` —
any internal user may edit any task (staff ops table). A changed content
field adopts a live suggestion unless the patch explicitly sets its
status, disposition, or killed_at. Authentication is internal JWT only;
MCP API-key/OAuth edits do not count as human acceptance.

## Path parameters

- `task_id` string, required

## Request body

- UpdateTaskRequest: Mirrors the MCP's `_TASK_PATCHABLE` set (no `domain_id`/`org_id` — the account rollup is set once at create). `extra="forbid"` rejects unknown fields (the MCP's "Unknown task fields" guard). Only fields the caller explicitly sends are applied, so an explicit null CLEARS a value (e.g. `killed_at: null` restores a soft-deleted task, `assignee: null` unassigns). Task-org L1 fields (owner_side/decision/deps) remain MCP-only. Human content edits on this internal JWT route implement no-second-accept.
  - `category` string, nullable
  - `title` string, nullable
  - `detail` string, nullable
  - `attachments` unknown
  - `labels` unknown
  - `priority` string, nullable
  - `assignee` string, nullable
  - `subscribers` unknown
  - `status` string, nullable
  - `disposition` string, nullable
  - `audience` string, nullable
  - `visibility_status` string, nullable
  - `external_ref` string, nullable
  - `external_url` string, nullable
  - `due_at` string, nullable
  - `completed_at` string, nullable
  - `killed_at` string, nullable
  - `position` integer, nullable
  - `parent_task_id` string, nullable
  - `priority_id` string, nullable
  - `contact_id` string, nullable

## Response `200`

Successful Response

- BackendDashboardServerRoutesGtmInternalTaskOut: Staff serializer — mirrors the MCP `_serialize_task` dict shape and so INCLUDES `detail` (staff-internal). The list route also enriches each row with human-readable `domain_host` / `org_name` so the cross-account table is not a wall of UUIDs (those two are not Task columns).
  - `id` string, required
  - `account_id` string, nullable
  - `domain_id` string, nullable
  - `org_id` string, nullable
  - `priority_id` string, nullable
  - `parent_task_id` string, nullable
  - `contact_id` string, nullable
  - `category` string, nullable
  - `title` string, required
  - `detail` string, nullable
  - `attachments` unknown
  - `labels` unknown
  - `priority` string, nullable
  - `created_by` string, nullable
  - `assignee` string, nullable
  - `subscribers` unknown
  - `status` string, nullable
  - `disposition` string, nullable
  - `source` string, nullable
  - `audience` string, nullable
  - `visibility_status` string, nullable
  - `external_ref` string, nullable
  - `external_url` string, nullable
  - `due_at` string, nullable
  - `completed_at` string, nullable
  - `killed_at` string, nullable
  - `position` integer, nullable
  - `created_at` string, nullable
  - `updated_at` string, nullable
  - `domain_host` string, nullable
  - `org_name` string, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/unusual/apis/dashboard-server.md) - [All operations](https://skmtc.dev/unusual/apis/dashboard-server/llms.txt) - [OpenAPI document](https://skmtc.dev/unusual/apis/dashboard-server/revisions/89f716930ead?raw)
