Tasks API
Tasks
One shared board belongs to each account. Tasks can optionally link to an event.
The fixed statuses are open, in_progress, and done.
All endpoints require Bearer authentication.
Send Accept: application/json, and Content-Type: application/json for JSON
request bodies. Reads accept a read or write token; mutations require a write
token. Personal co-organizer tokens see and manage only tasks for their current
assigned events. They cannot create account-wide tasks or remove a task’s event
link. Assigning a person never grants them event access.
Task representation
{
"id": "W1pjAZsT2T1aPLyfFM9pHJZc",
"title": "Confirm the door briefing",
"description": "Meet the entrance team at 18:00.",
"description_html": "<div class=\"trix-content\"><p>Meet the entrance team at 18:00.</p></div>",
"attachments": [],
"archived_at": null,
"status": "in_progress",
"position": 1,
"lock_version": 2,
"due_on": "2026-10-24",
"event": { "slug": "october-party", "title": "October Party" },
"assignee": { "id": 42, "name": "Lisa" },
"created_at": "2026-09-13T16:00:00Z",
"updated_at": "2026-09-13T16:10:00Z"
}
id is an opaque public ID. event, assignee, due_on, and archived_at may
be null. description is plain text (empty string when absent);
description_html contains the sanitized rendered rich text. Due dates are calendar dates (YYYY-MM-DD); timestamps are UTC.
Assignee IDs identify account memberships. Use the people endpoint below to
obtain eligible membership IDs. position is the ordering value within a status
column; clients should move tasks through the position endpoint instead of
writing this field directly.
List and show
GET /admin/tasks returns { "tasks": [...] }, ordered by position and ID.
Optional query parameters:
| Parameter | Meaning |
|---|---|
event_slug |
An accessible event slug, or none for tasks without an event. Omit for all accessible tasks. |
archived |
true lists archived tasks only. Omit or use false for the active board. |
hide_done |
true hides completed tasks on the active board. |
assignee_id |
An eligible membership ID, me for the current person, or none for unassigned tasks. Omit for everyone. |
GET /admin/tasks/:id returns one task using the representation above.
Missing or inaccessible tasks and event slugs return 404.
Create and update
POST /admin/tasks accepts a task object. Only title is required for an
account-wide task; co-organizers must also provide an accessible event_slug.
{
"task": {
"title": "Confirm the door briefing",
"event_slug": "october-party",
"assignee_id": 42,
"due_on": "2026-10-24"
}
}
Returns 201 Created, the task representation, and a Location header pointing
to the task’s JSON URL.
PATCH /admin/tasks/:id accepts the same fields plus lock_version:
{
"task": {
"description": "Meet the entrance team at 18:00.",
"status": "in_progress",
"lock_version": 1
}
}
Writable fields: title (maximum 200 characters), description (plain text or
HTML; maximum 20,000 plain-text characters),
status, due_on, event_slug, assignee_id, and lock_version.
Omitted fields are preserved. Updating description replaces all its rich text
and attachments; retain existing attachment markup when changing only the text. Set optional values to null or an empty string
to clear them. A co-organizer cannot clear event_slug.
Updates return 200 and the current task. Include the last returned
lock_version to detect concurrent edits. A stale version returns 409 with
{ "errors": { "base": ["..."] } }; read the latest task and reconcile changes
before retrying. Validation failures return 422 with field errors, for example
{ "errors": { "title": ["can't be blank"] } }. A person without access to the
task cannot be assigned; choose an eligible person first.
Move a card
PATCH /admin/tasks/:task_id/position:
{
"position": {
"status": "done",
"before_id": "B2L8pYqsDHwTrPc93MCzhGNY",
"lock_version": 2
}
}
status is required. Optional before_id identifies an accessible task in the
destination column. Omit it to place the card last. Moving within the same
column reorders the card. The anchor preserves the relative order of cards
hidden by filters. Returns 200 and the updated task; stale versions return
409. An invalid destination returns 422 and leaves the task unchanged.
People eligible for assignment
GET /admin/task_assignees?event_slug=october-party returns:
{ "people": [{ "id": 42, "name": "Lisa" }] }
An event includes active owners, managers, and co-organizers assigned to that
event. Omit event_slug to get eligible people for account-wide tasks (owners
and managers). Scanner, promoter, inactive and foreign memberships are excluded.
Comments and activity
GET /admin/tasks/:task_id/comments returns { "entries": [...] }, ordered
oldest first. Entries include comments and creation, status and assignment
history. Each entry has exactly these fields:
{
"id": "LAfgPyCWoSVpJhMF89YAzRTZ",
"kind": "comment",
"body": "Entrance team confirmed.",
"body_html": "<div class=\"trix-content\"><p>Entrance team confirmed.</p></div>",
"attachments": [],
"details": {},
"author": "Lisa",
"created_at": "2026-09-13T16:15:00Z"
}
kind is created, status, assignment, or comment. For status changes,
details contains from and to; for assignments it contains name, which is
null when unassigned. body is plain text and body_html is sanitized
rendered rich text; both are null for non-comment activity. author may be null
if the originating user has been removed.
POST /admin/tasks/:task_id/comments with
{ "comment": { "body": "Entrance team confirmed." } } adds a comment (maximum
10,000 plain-text characters; plain text or HTML). Returns 201, the entry representation and a Location
header pointing to the comments collection. Empty comments return 422; a
comment containing only an attachment is valid.
Archive and restore
POST /admin/tasks/:task_id/archive archives a completed (done) task.
DELETE /admin/tasks/:task_id/archive restores it to the active board in Done.
Both return 200 and the updated task, including archived_at (UTC timestamp
or null). Send optional { "lock_version": 4 } to protect against concurrent
changes; stale versions return 409.
Archiving an unfinished task returns 422. Archived tasks retain their
comments, attachments, assignments and event association. Restore a task before
moving it. Archived tasks remain available through their detail URL and follow
the same current access rules as the active board.
Both tasks and entries include an attachments array (empty when none). Each
attachment contains:
{
"signed_id": "SIGNED_BLOB_ID",
"attachable_sgid": "ATTACHABLE_SGID",
"filename": "door-briefing.pdf",
"content_type": "application/pdf",
"byte_size": 4096,
"url": "/admin/task_uploads/SIGNED_BLOB_ID"
}
Use signed_id for authenticated downloads and attachable_sgid for Action
Text markup. These IDs remain subject to current task access.
Images and files in rich text
The dashboard editor supports direct uploads. API clients use the same flow:
POST /admin/task_uploadswith ablobobject containingfilename,byte_size,checksum(base64 MD5), andcontent_type. Maximum file size is 20 MB. This requires a write token.- The
200response includessigned_id,attachable_sgid, anddirect_uploadwithurlandheaders. Upload the file bytes withPUTto that URL using those headers. - Include
<action-text-attachment sgid="ATTACHABLE_SGID"></action-text-attachment>in the task’sdescriptionor comment’sbodyHTML. Use the returnedattachable_sgid, notsigned_id, for this markup.
GET /admin/task_uploads/:signed_id downloads a file with current organizer
authentication. API clients must send their Bearer token and
Accept: application/json even though the response contains file bytes.
Supported image types render inline; ?disposition=attachment forces download.
Other files always download. HTML representations contain these authenticated
links, which are not public sharing links.
Unattached uploads are accessible only to their uploader in the current account. Attached files follow current task permissions. Only the uploader’s private draft files or files already attached to that same task can be embedded. Standard public Active Storage URLs cannot access task uploads.
Delete
DELETE /admin/tasks/:id returns 204 No Content. Deleting a task also removes
its comments, history and assignment notifications. Deleting an event removes
its tasks.
Live updates and notifications
API changes appear in the shared board through the same live refreshes as the admin UI. Assigning a task to another person sends a notification through their existing inbox and configured browser push. The actor is not notified about self-assignment. Delivery checks current task access and assignment; old notifications are hidden after assignment or access is removed. Comments update live without sending a notification to the whole team.