Skip to content

REST API Tasks

Ed Mozley edited this page Jul 3, 2026 · 1 revision

βœ… REST API: Tasks

The complete usage guide for the Tasks (kanban) module of the REST API β€” every URL, method, parameter and response shape, including moving cards on the board. Mirrors the interactive documentation at System β†’ API β†’ Documentation (with its live "Try it" tester).

Note

New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics β€” identical across all modules.

What's distinctive about Tasks:

πŸ“‹ It's a board Tasks live in status columns ordered by board_position. POST /tasks/{id}/move is the kanban drag as an API call β€” target column + 0-based position, re-packed automatically.
πŸͺ† Subtasks are tasks A subtask is just a task with parent_task_id set. Lists return top-level tasks by default (each with done/total subtask counts); pass parent_task_id=N to list a task's children.
πŸ”— Links respect company scope A task can link to a ticket, change or contract. Ticket links are validated against the key's company scope, and a linked ticket's details only appear in responses when the key could read that ticket directly β€” tighter than the UI.
🏷️ Tags are curated Task tags are a managed list (Tasks β†’ Settings) β€” the API accepts existing names or ids and returns 422 for unknown ones rather than creating tags on the fly.
🚫 No audit trail The product keeps no task history (comments are the closest thing) β€” the API doesn't invent one.

πŸš€ Quick start

Create a task from a monitoring runbook and walk it across the board:

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

# 1. Create (lands at the end of the To Do column)
TASK=$(curl -s -X POST "$B/tasks" -H "$K" -H "Content-Type: application/json" -d '{
  "title": "Renew SSL certificate for portal",
  "priority": "High", "due_date": "2026-07-20",
  "tags": ["Security"]}' | jq -r '.data.id')

# 2. Drag it to the top of In Progress
curl -s -X POST "$B/tasks/$TASK/move" -H "$K" -H "Content-Type: application/json" \
  -d '{"status": "In Progress", "position": 0}'

# 3. Done β†’ completed_at stamped, task.completed workflow fires
curl -s -X PATCH "$B/tasks/$TASK" -H "$K" -H "Content-Type: application/json" -d '{"status": "Done"}'

βœ… Tasks

🟒 GET /tasks β€” list / board feed Β  πŸ”‘ tasks.read

Top-level tasks in board order by default. Every task carries its tags, subtasks: {total, done} counts and board_position β€” enough to render a board.

Parameter Description
state open | closed | all (default all)
status / status_id One board column, by name (e.g. In Progress) or id
priority / priority_id By name or id
assigned_analyst_id / assigned_team_id Assignment filters Β· unassigned=true
ticket_id Β· change_id Β· contract_id Tasks linked to a record
parent_task_id List the subtasks of this task (default: top-level only)
tag Only tasks carrying this tag (exact name)
q Search title and description
due_before / due_after YYYY-MM-DD bounds
overdue true = open tasks past their due date ⏰
sort board_position (default), created_at, updated_at, due_date, completed_at, title, id β€” prefix - for descending
page / per_page Pagination β€” default 1 / 25, max 100

The task shape:

{ "id": 45, "title": "Renew SSL certificate for portal", "description": null,
  "status":   { "id": 2, "name": "In Progress", "is_closed": false, "colour": "#f59e0b" },
  "priority": { "id": 3, "name": "High", "colour": "#f59e0b" },
  "assigned_analyst": { "id": 1, "name": "Administrator" }, "assigned_team": null,
  "start_date": null, "due_date": "2026-07-20",
  "parent_task_id": null, "ticket_id": null, "change_id": null, "contract_id": null,
  "board_position": 0,
  "tags": ["Security"], "subtasks": { "total": 1, "done": 0 },
  "created_by": { "id": 1, "name": "Administrator" },
  "created_at": "2026-07-03T12:40:44Z", "updated_at": "2026-07-03T12:41:12Z",
  "completed_at": null }

πŸ”΅ POST /tasks β€” create Β  πŸ”‘ tasks.create

Only title is required. Defaults To Do / Medium; the card is appended to the end of its status column. Returns 201.

Field Description
title βœ… Task title
description Details
status / status_id Β· priority / priority_id By name or id
assigned_analyst_id / assigned_team_id Assignment (both validated)
start_date / due_date YYYY-MM-DD
parent_task_id Create as a subtask of this task
ticket_id / change_id / contract_id Link to a record β€” validated; ticket links must be within the key's company scope
tags Array of existing tag names or ids (422 for unknown)

🟒 GET /tasks/{id} β€” get one Β  πŸ”‘ tasks.read

Everything in the list shape plus parent summary, the ordered subtask_list, comments, and linked_ticket / linked_change summaries (linked-ticket details only when the key's scope allows).

🟠 PATCH /tasks/{id} β€” update Β  πŸ”‘ tasks.update

Everything creatable is patchable; null clears. Two behaviours worth knowing:

  • Closing: moving to a closed status (Done, Cancelled) stamps completed_at (kept if already set) and fires the task.completed workflow event; moving back to an open status clears it.
  • Tags: tags replaces the tag set.

πŸ”΅ POST /tasks/{id}/move β€” move on the board Β  πŸ”‘ tasks.update

The kanban drag as an API call:

{ "status": "In Progress", "position": 0 }
  • status / status_id β€” target column (omit to reorder within the current one)
  • position β€” 0-based slot in the column (omit = end)

The whole column is re-packed transactionally, so positions stay dense and ordered.

Note

Parity quirk, preserved deliberately: like the UI's drag, /move does not fire the task.completed workflow event when a card lands in Done β€” only a status change via PATCH does. That's exactly how the product behaves (drag = reorder.php, edit = save.php); the API mirrors it rather than silently diverging.

πŸ”΄ DELETE /tasks/{id} β€” delete Β  πŸ”‘ tasks.delete

Warning

Permanent, no trash. The whole subtask tree, comments and tag links are removed with it. The response reports subtasks_deleted.


πŸ’¬ Comments

🟒 GET /tasks/{id}/comments Β  πŸ”‘ task_comments.read

Comments oldest first, with the author.

πŸ”΅ POST /tasks/{id}/comments Β  πŸ”‘ task_comments.create

Body: {"text": "…"}. Attributed to the analyst the key acts as. Comments can't be edited or deleted (parity with the UI). Returns 201.


πŸ“š Reference data

Under the shared πŸ”‘ reference.read permission:

Endpoint Returns
🟒 GET /task-statuses The board columns with is_closed, colour, display_order (seeded To Do β†’ In Progress β†’ Blocked β†’ Done β†’ Cancelled)
🟒 GET /task-priorities Low / Medium / High / Urgent (plus custom)
🟒 GET /task-tags The curated tag list with colours and usage counts

πŸ§ͺ Worked example: sprint-bot standup report

A read-only key (tasks: read) posts a morning summary to your chat tool:

B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_…"

# Overdue tasks by assignee
curl -s -H "$K" "$B/tasks?overdue=true&sort=due_date&per_page=100" \
  | jq -r '.data[] | "\(.due_date)  \(.assigned_analyst.name // "unassigned")  \(.title)"'

# Board totals per column
for s in "To Do" "In Progress" "Blocked"; do
  n=$(curl -s -H "$K" "$B/tasks?status=$(echo $s | sed 's/ /+/g')" | jq '.meta.total')
  echo "$s: $n"
done

And the automation direction β€” a deployment pipeline creating a follow-up task with a subtask checklist:

P=$(curl -s -X POST "$B/tasks" -H "$K" -H "Content-Type: application/json" \
  -d '{"title":"Post-deploy checks for release 2.4","priority":"High","due_date":"2026-07-05"}' | jq -r '.data.id')
for step in "Smoke-test portal login" "Check error rates" "Confirm backups ran"; do
  curl -s -o /dev/null -X POST "$B/tasks" -H "$K" -H "Content-Type: application/json" \
    -d "{\"title\": \"$step\", \"parent_task_id\": $P}"
done

Under the hood: REST API β€” How It Works Β· Other modules: Tickets Β· Assets Β· Problems Β· Changes Β· Knowledge Β· Keys & permissions: System β†’ API (System module) Β· Module docs: Tasks.

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Blue sky thinking

Bugs resolved

Links

Clone this wiki locally