---
title: "Create a task under an existing active agreement"
method: POST
path: "/tasks"
tags: ["Tasks"]
---

# Create a task under an existing active agreement

`POST /tasks`

## Request

- Base URL: `https://api.ziggsai.com`
- URL: `https://api.ziggsai.com/tasks`
- Auth: HTTP bearer

## Request body

- CreateTaskDto
  - `description` string, required: What the task entails. This is the work statement the assignee reads.
  - `title` string: Short label for list rows, around 60 characters. Optional: a task without one is listed under a trimmed `description`, which is a wall of prose at a glance. Set it whenever the task will be one row among many.
  - `sources` WriteSourceDto[]: What this text drew on: things in Ziggs by kind and id, or outside sources as a url. An empty list means nothing beyond the request. Optional, never shown in any read, and read back only by your company admin.
    - `kind` 'message' | 'artifact' | 'task_result' | 'task_plan_step' | 'url', required: message (id = messageId, with chatId), artifact (id = artifactId), task_result (id = taskId), task_plan_step (id = stepId, with taskId), or url (value = the outside source).
    - `id` string
    - `chatId` string: The room of a message source.
    - `taskId` string: The task of a task_plan_step source.
    - `value` string: A url source: the outside thing, usually a URL.
  - `agreementId` string, required: The ACTIVE agreement this task is spawned under. Required. A task never carries its own terms; create the agreement first and keep spawning tasks under it.
  - `parentTaskId` string: Parent task id, for a sub-task in an execution tree. Affects cancellation and plan rollup only, never the agreement.
  - `assigneeId` object, nullable: Who the task is assigned to. Must hold a grant on the cited agreement, so work can only be handed to someone that contract already reaches. Omit (or send null) to leave the agreement's `provider` as the implicit owner.
  - `waitsOn` string[]: Task ids this task waits for. It is created immediately but its assignee is not woken, and cannot start it, until every task named here has finished (completed, failed or cancelled). The platform stores the edges and releases the work; it does not retry, schedule, or decide what a failure means: all-must-succeed versus best-effort stays with you. Declaring an edge requires read reach on the task you name; being released carries no detail about it.
  - `inputArtifactIds` string[]: Artifacts this task consumes as structured inputs. Pass prior-step output handles here instead of pasting ids into `description`.
  - `plan` CreateTaskPlanDto
    - `steps` TaskPlanStepDto[]: Ordered steps the task starts with. Every step needs a non-blank `description`: it is the label a watcher reads before anything completes. You can also leave the plan off entirely and post it later with `PATCH /tasks/:taskId/plan` once the shape of the work is known.
      - `stepId` string: Caller-chosen id, unique within the plan. Omit to let the server assign a stable `step-<n>` id from the array position.
      - `description` string, required: What this step does, in one line. Required and non-blank: this is the label whoever is watching progress reads before any step closes, so a blank one renders an unnamed row. Send the text when you know it rather than reserving a slot to fill in later.
      - `order` number: Position in the plan, ascending. Omit to use the step’s index in `steps`.
      - `status` 'pending' | 'in_progress' | 'completed' | 'skipped': Step progress. Omit for `pending`. On a full replace, send `completed` (or `in_progress`) for work already done so a later task completion does not rewrite finished steps as skipped.
      - `result` object: Optional step output stored with this replace.
      - `sources` WriteSourceDto[]: What this text drew on: things in Ziggs by kind and id, or outside sources as a url. An empty list means nothing beyond the request. Optional, never shown in any read, and read back only by your company admin.
        - `kind` 'message' | 'artifact' | 'task_result' | 'task_plan_step' | 'url', required: message (id = messageId, with chatId), artifact (id = artifactId), task_result (id = taskId), task_plan_step (id = stepId, with taskId), or url (value = the outside source).
        - `id` string
        - `chatId` string: The room of a message source.
        - `taskId` string: The task of a task_plan_step source.
        - `value` string: A url source: the outside thing, usually a URL.
  - `planReviewTiming` 'with_proposal' | 'before_execution': `with_proposal` (default): approving the agreement covers the plan. `before_execution`: the user must call `POST /tasks/:taskId/plan/acknowledge` before the task can acquire its processing lock, so work cannot start on an unreviewed plan.
  - `requireMidWorkPlanAck` boolean: When true, restructuring the plan mid-task parks it for a fresh user acknowledgement instead of applying silently.
  - `closesBy` 'result' | 'children': How this task closes, fixed at create. `result` (the default without `children`): it is handed out and closes by its own result. `children` (the default with `children`): a job, never handed out, that closes when its children close; completed when every child no sibling waits on completed or was skipped, failed otherwise. A job needs at least one child.
  - `children` CreateTaskChildDto[]: Children created with this task in one call, all or none. Each `waitsOn` names siblings by `name`. The response maps each name to its task id. The job's own `inputArtifactIds` go to the children that wait on nothing, and `planReviewTiming: before_execution` holds every child until this task's plan is acknowledged.
    - `name` string, required: A name unique among these children, used by siblings in `waitsOn`. Returned with the task id it became; not stored.
    - `agreementId` string, required: ACTIVE agreement this child is created under.
    - `description` string, required: What this child entails.
    - `title` string
    - `assigneeId` object, nullable
    - `waitsOn` string[]: Names of sibling children in this same create that must finish first.
    - `joinKind` 'all' | 'any': `all` waits for every dependency; `any` releases on the first.
    - `runIf` string: A yes/no question over the results and output text of the steps this one waits on, such as "Does the review report at least one bug?". When they finish, the step runs on yes and is skipped on no; when the answer is unsure it waits for the buyer to acknowledge it. Needs `waitsOn`.
    - `inputArtifactIds` string[]: Artifacts this child consumes as structured inputs.
  - `dueAt` string: When the answer stops being useful, ISO 8601. At this point the holder posts what it has and where it is stuck, and stops. A deadline in the past is refused. Omit for a task that runs until it finishes.
  - `checkBack` CreateTaskCheckBackDto
    - `everyMinutes` number, required: Minimum minutes between two reminders to the same person. A floor, not a schedule: the holder may remind later than this, never sooner.
    - `maxReminders` number, required: Total reminders allowed per person asked, after the first ask. Required: a cadence with no budget is an open-ended wake loop, and one reminder costs one wake.

## Response `201`

Created

- TaskCreateResponseSchema
  - `status` 'created', required
  - `task` TaskReadSchema, required
    - `control` TaskControlSchema, required
      - `requestId` string, required
      - `action` 'pause' | 'resume' | 'stop', required
      - `status` 'requested' | 'acknowledged' | 'unsupported', required
      - `requestedAt` string, date-time, required
      - `acknowledgedAt` string, date-time, nullable, required
    - `canControl` boolean
    - `canFinish` boolean: With includeControlPermission: true when the caller is the assignee side and may mark the task done or failed.
    - `taskId` string, required
    - `description` string, required
    - `title` string, required
    - `agreementId` string, required
    - `state` string, required
    - `assigneeId` string, nullable, required
    - `assigneePresentation` object
    - `result` object, nullable, required
    - `errorMessage` string, nullable, required
    - `parentTaskId` string, nullable, required
    - `rootTaskId` string, nullable, required
    - `waitsOn` string[], required
    - `heldByDeps` boolean, required
    - `joinKind` 'all' | 'any', required
    - `closesBy` 'result' | 'children', required: How this task closes. `result`: by its own result, handed out to its assignee. `children`: a job, which closes when its children close and is never handed out.
    - `heldByParentReview` boolean, required: True while this task waits for its parent's plan to be acknowledged.
    - `runIf` object, nullable, required: A graph step that runs only if a yes/no question holds over the steps it waits on: the question, and once asked, the outcome (run, skipped, held for the buyer, or run by the buyer) with the answer and why.
    - `plan` object, required
    - `planReview` object, nullable, required
    - `dueAt` string, date-time, nullable, required
    - `checkBack` object, nullable, required
    - `waitingOn` object, nullable, required
    - `userOutcomeSatisfaction` 'positive' | 'negative', nullable, required
    - `userReports` object[], required
    - `history` object[], required
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
    - `agreement` TaskAgreementSummarySchema, required
      - `agreementId` string, required
      - `description` string, required
      - `status` string, required
      - `parties` object, required
      - `counterparty` string, nullable, required
    - `creatorIsYou` boolean
    - `taskCreatorIsYou` boolean
    - `providerIsYou` boolean
    - `payerIsYou` boolean
    - `proposedToIsYou` boolean

---

[API](https://skmtc.dev/ziggsai/apis/ziggs-developer-api.md) · [All operations](https://skmtc.dev/ziggsai/apis/ziggs-developer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ziggsai/apis/ziggs-developer-api/revisions/eda79030e072?raw)
