Skip to content

GET /containers

List containers

Query parameters

NameTypeRequiredDescription
typeContainerType
  • HUB
  • COLLECTION
optional
parent_idstring (uuid) optional
cursorstring optional
sizeinteger
  • default: 50
  • minimum: 1
  • maximum: 200
optional
include_archivedboolean
  • default: false
optional

Responses

Example bash
curl -X GET "$HUBTASK_URL/containers" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

POST /containers

Create container

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Request body application/json — ContainerCreate

NameTypeRequiredDescription
typeContainerType
  • HUB
  • COLLECTION
required
parent_idstring (uuid), or null optional
namestring
  • minLength: 1
  • maxLength: 200
required
descriptionstring, or null optional
iconstring, or null optional
color_tokenstring, or null optional
privateboolean
  • default: false
optionalMakes the new hub private: reached only by people holding a role on it or below it, not by the workspace's owners and administrators.

Responses

Example bash
curl -X POST "$HUBTASK_URL/containers" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)" \  -H "Content-Type: application/json" \  -d '{  "type": "HUB",  "parent_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c",  "name": "string",  "description": "string",  "icon": "string",  "color_token": "string",  "private": false}'

GET /containers/{containerId}

Get container

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Responses

Example bash
curl -X GET "$HUBTASK_URL/containers/{containerId}" \  -H "Authorization: Bearer $HUBTASK_TOKEN"

PATCH /containers/{containerId}

Rename container

Changes a container's own descriptive fields. A field that is not sent is left alone; sending description, icon or color_token as null clears it. The name stays unique among the containers at the same level. The policies are not here - they are their own sub-resource, so that a rename and a change of the way a collection works are two operations with two audit entries.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
If-Matchstring optionalThe ETag of the state last read (optimistic locking).

Request body application/merge-patch+json — ContainerUpdate

NameTypeRequiredDescription
namestring
  • minLength: 1
  • maxLength: 200
optional
descriptionstring, or null optional
iconstring, or null optional
color_tokenstring, or null optional

Responses

Example bash
curl -X PATCH "$HUBTASK_URL/containers/{containerId}" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H 'If-Match: "<the ETag you read>"' \  -H "Content-Type: application/merge-patch+json" \  -d '{  "name": "string",  "description": "string",  "icon": "string",  "color_token": "string"}'

DELETE /containers/{containerId}

Trash container

A soft delete: the hub or collection and everything under it move to the trash under one deletion - a hub takes its collections, and every collection takes its entries. It all stays for the tenant's trash retention period, 30 days by default, and comes back as one act through :restore until the retention job removes it for good. Anything already in the trash from an earlier deletion keeps that deletion rather than joining this one. Needs the owner's right to delete a container. Idempotent.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
If-Matchstring optionalThe ETag of the state last read (optimistic locking).

Responses

  • 204 Moved to the trash
  • 4XX An error per RFC 9457 Problem
Example bash
curl -X DELETE "$HUBTASK_URL/containers/{containerId}" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H 'If-Match: "<the ETag you read>"'

PUT /containers/{containerId}/policies

Update container policies

Replaces a collection's policies - the way it works, as opposed to what it is called. A key that is not sent falls back to its default rather than keeping the stored value: this is a PUT, and a document that partly remembers what it replaced is one nobody can reason about. A hub carries no policies and is refused.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
If-Matchstring optionalThe ETag of the state last read (optimistic locking).

Request body application/json — ContainerPolicies

NameTypeRequiredDescription
completion_policyCompletionPolicy
  • MANUAL
  • ROLLUP
  • default: "MANUAL"
optionalWhether a child's completion propagates upwards.
auto_assignone of AutoAssignPolicy, anything, or null optionalHow what is created in this collection is handed out, absent (or null) for not at all.

Responses

Example bash
curl -X PUT "$HUBTASK_URL/containers/{containerId}/policies" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H 'If-Match: "<the ETag you read>"' \  -H "Content-Type: application/json" \  -d '{  "completion_policy": "MANUAL",  "auto_assign": {    "strategy": "FIXED",    "candidates": [      {}    ]  }}'

PUT /containers/{containerId}/privacy

Set hub privacy

Makes a hub private - reached only by people holding a role on it, on a collection in it or on an entry in one, and no longer by the workspace's own roles, its owners and administrators included - or shared again. Making it private needs the right to create hubs and the role OWNER on the hub itself; sharing it again needs OWNER on the hub. A hub nobody may see answers not found. Refused with containers.private_hub_has_groups while a group holds a role in the hub, and with containers.private_only_hubs on a collection. Every device that loses the hub is told. Writing what is already stored changes nothing.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
If-Matchstring optionalThe ETag of the state last read (optimistic locking).

Request body application/json — HubPrivacy

NameTypeRequiredDescription
privateboolean requiredtrue to make the hub private, false to share it again.

Responses

Example bash
curl -X PUT "$HUBTASK_URL/containers/{containerId}/privacy" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H 'If-Match: "<the ETag you read>"' \  -H "Content-Type: application/json" \  -d '{  "private": true}'

POST /containers/{containerId}:move

Move container

Moves a collection into another hub, and ranks it there. The name has to be free at the destination; a collision is refused rather than resolved. A hub sits in nothing and cannot be moved.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Request body application/json

NameTypeRequiredDescription
target_parent_idstring (uuid) requiredThe hub the collection moves into.
before_container_idstring (uuid), or null optionalThe sibling to place this collection before at the destination.

Responses

Example bash
curl -X POST "$HUBTASK_URL/containers/{containerId}:move" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)" \  -H "Content-Type: application/json" \  -d '{  "target_parent_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c",  "before_container_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c"}'

POST /containers/{containerId}:reorder

Reorder container

Ranks a container within the level it already sits in: a hub among the tenant's hubs, a collection among its hub's collections. The position is given as the container to place it before; omitting it appends to the end of the level. This is the only way to rank a hub. :move ranks a collection as a consequence of naming the hub it goes into - which is why its target_parent_id is required - and a hub sits in nothing, so an operation whose destination is a hub cannot express it. Every Container answers an order_key, so without this one the rank of a hub is a field the API reports and nothing can change. The rank is a fractional index, so an insertion between two neighbours renumbers nothing else and two offline devices can insert into the same list without either one's order being discarded. An archived container is read-only (I-C3) and is refused, as it is for every other write. Idempotent: asking for the position a container already holds writes nothing.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.
If-Matchstring optionalThe ETag of the state last read (optimistic locking).

Request body application/json

NameTypeRequiredDescription
before_container_idstring (uuid), or null optionalThe sibling to place this container before, at its own level.

Responses

Example bash
curl -X POST "$HUBTASK_URL/containers/{containerId}:reorder" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)" \  -H 'If-Match: "<the ETag you read>"' \  -H "Content-Type: application/json" \  -d '{  "before_container_id": "018f6e2a-2b7c-7c1e-9b1a-3d5e6f7a8b9c"}'

POST /containers/{containerId}:restore

Restore container

Takes one container deletion back out of the trash, whole: the hub, its collections, and every entry that went in with them. Exactly what went in together comes back - a separate, younger deletion inside the same subtree stays where it is, because a restore is keyed on the deletion rather than on the subtree. A container archived when it was deleted comes back archived. Needs the same right as the deletion, which is the owner's. Idempotent.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Responses

Example bash
curl -X POST "$HUBTASK_URL/containers/{containerId}:restore" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)"

POST /containers/{containerId}:archive

Archive container

Archives the container. An archived container is read-only, and everything below it inherits that: a collection in an archived hub refuses writes without being archived itself, which is what effective_archived reports. Idempotent - archiving an archived container changes nothing.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Responses

Example bash
curl -X POST "$HUBTASK_URL/containers/{containerId}:archive" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)"

POST /containers/{containerId}:unarchive

Unarchive container

Makes the container writable again. A collection that was archived in its own right stays archived when its hub is unarchived - unarchiving restores what was archived, not what was merely covered by it. Idempotent.

Path parameters

NameTypeRequiredDescription
containerIdstring (uuid) required

Headers

NameTypeRequiredDescription
Idempotency-Keystring (uuid) optionalA UUID; identical requests return the same result for 24 h.

Responses

Example bash
curl -X POST "$HUBTASK_URL/containers/{containerId}:unarchive" \  -H "Authorization: Bearer $HUBTASK_TOKEN" \  -H "Idempotency-Key: $(uuidgen)"