# Tasks

> Your team's to-dos: list, add, change and complete them, about a client or not.

Source: https://hubfit.com/developers/api/tasks


Your team's to-dos, the same tasks as on the Tasks page in the app. A task can be about a client, and only your team sees it; the client is never told. A workspace has at most 250 open tasks.

Endpoints:

- `GET /v1/tasks`: [List tasks](https://hubfit.com/developers/api/tasks#list-tasks)
- `POST /v1/tasks`: [Add a task](https://hubfit.com/developers/api/tasks#create-task)
- `GET /v1/tasks/{taskId}`: [Get a task](https://hubfit.com/developers/api/tasks#get-task)
- `PATCH /v1/tasks/{taskId}`: [Change a task](https://hubfit.com/developers/api/tasks#update-task)

## Task object

### Attributes

- `id` (string): Its unique ID.
- `title` (string)
- `status` (enum): One of `open`, `completed`.
- `dueDate` (date, nullable): The day it's due, in your own calendar. `null` if it has none.
- `client` (object, nullable): The client it's about. `null` if it's about no one, or about a client you can't reach (not assigned to you, archived or deleted).
  - `id` (string): Its unique ID.
  - `name` (string)
- `assignee` (object, nullable): The coach it's assigned to. `null` if it's unassigned.
  - `id` (string): Its unique ID.
  - `name` (string, nullable): The coach's name. `null` if their account no longer exists.
- `createdBy` (object, nullable): The coach who added it.
  - `id` (string): Its unique ID.
  - `name` (string, nullable): The coach's name. `null` if their account no longer exists.
- `createdAt` (timestamp): When it was created.
- `updatedAt` (timestamp): When the task last changed. A change to its client or coaches, such as a new name, doesn't count.
- `completedAt` (timestamp, nullable)
- `completedBy` (object, nullable): The coach who completed it. `null` while it's open.
  - `id` (string): Its unique ID.
  - `name` (string, nullable): The coach's name. `null` if their account no longer exists.

### Example

```json
{
  "id": "6ad6af8764ce168864cfa985",
  "title": "Call Jordan about their new program",
  "status": "open",
  "dueDate": "2026-10-30",
  "client": {
    "id": "6ad6af41d3199442d31b2743",
    "name": "Jordan Miller"
  },
  "assignee": {
    "id": "6ad6af42386c5341386ac044",
    "name": "Alex Carter"
  },
  "createdBy": {
    "id": "6ad6af42386c5341386ac044",
    "name": "Alex Carter"
  },
  "createdAt": "2026-03-02T15:04:11.000Z",
  "updatedAt": "2026-10-26T09:12:40.000Z",
  "completedAt": null,
  "completedBy": null
}
```

## List tasks

`GET https://api.hubfit.com/v1/tasks`

Your team's tasks, as you see them in the app: an owner or admin sees every task in the workspace, a team member the tasks assigned to them or that they added. Open tasks come newest first; completed ones newest completed first. A task about a client you can't reach (not assigned to you, archived or deleted) shows `client: null`. Requires `tasks:write`.

### Query parameters

- `status` (enum): `open` (the default) or `completed`. One of `open`, `completed`. Default `open`.
- `clientId` (string): Only tasks about this client.
- `assigneeId` (string): Only tasks assigned to this coach (an `assignee.id`).
- `limit` (integer): How many results to return, from 1 to 100. Default `25`.
- `cursor` (string): The `nextCursor` from the previous page.

### Returns

A page of tasks.

### Example request

cURL:

```bash
curl -G https://api.hubfit.com/v1/tasks \
  -H "Authorization: Bearer $HUBFIT_API_KEY" \
  -d status=open
```

Node.js:

```javascript
const response = await fetch("https://api.hubfit.com/v1/tasks?status=open", {
  headers: {
    Authorization: `Bearer ${process.env.HUBFIT_API_KEY}`,
  },
});

const { data, nextCursor } = await response.json();
```

Python:

```python
import os
import requests

response = requests.get(
    "https://api.hubfit.com/v1/tasks",
    headers={"Authorization": f"Bearer {os.environ['HUBFIT_API_KEY']}"},
    params={
        "status": "open",
    },
)

page = response.json()
data, next_cursor = page["data"], page["nextCursor"]
```

### Example response (200 OK)

```json
{
  "data": [
    {
      "id": "6ad6af8764ce168864cfa985",
      "title": "Call Jordan about their new program",
      "status": "open",
      "dueDate": "2026-10-30",
      "client": {
        "id": "6ad6af41d3199442d31b2743",
        "name": "Jordan Miller"
      },
      "assignee": {
        "id": "6ad6af42386c5341386ac044",
        "name": "Alex Carter"
      },
      "createdBy": {
        "id": "6ad6af42386c5341386ac044",
        "name": "Alex Carter"
      },
      "createdAt": "2026-03-02T15:04:11.000Z",
      "updatedAt": "2026-10-26T09:12:40.000Z",
      "completedAt": null,
      "completedBy": null
    }
  ],
  "nextCursor": "eyJpZCI6IjZhZDZhZjNmMjljNTk3ZjE1In0",
  "totalCount": 48
}
```

## Add a task

`POST https://api.hubfit.com/v1/tasks`

Adds a task, as adding one in the app does. It's assigned to you unless you choose a team member. A workspace has at most 250 open tasks; past that it's `409 open_task_limit_reached`. Each call adds another task, so send an `Idempotency-Key` to retry safely. Requires `tasks:write`.

### Headers

- `Idempotency-Key` (string): Any unique string, such as a UUID, up to 255 characters. Retrying with the same key within 24 hours returns the first response instead of repeating the write. See [Idempotency](https://hubfit.com/developers/idempotency).

### Body parameters

- `title` (string, required): What needs doing. Can't be blank.
- `dueDate` (date): The day it's due, as `YYYY-MM-DD`, in your own calendar.
- `assigneeId` (string): The team member to give it to (a coach who has joined your workspace). Defaults to you.
- `clientId` (string): The client the task is about. Only your team sees the task; the client isn't told.

### Returns

The new task.

### Example request

cURL:

```bash
curl -X POST https://api.hubfit.com/v1/tasks \
  -H "Authorization: Bearer $HUBFIT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Call Jordan about their new program",
    "dueDate": "2026-10-30",
    "clientId": "6ad6af41d3199442d31b2743"
  }'
```

Node.js:

```javascript
const response = await fetch("https://api.hubfit.com/v1/tasks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.HUBFIT_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    title: "Call Jordan about their new program",
    dueDate: "2026-10-30",
    clientId: "6ad6af41d3199442d31b2743",
  }),
});

const { data } = await response.json();
```

Python:

```python
import os
import uuid
import requests

response = requests.post(
    "https://api.hubfit.com/v1/tasks",
    headers={"Authorization": f"Bearer {os.environ['HUBFIT_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
        "title": "Call Jordan about their new program",
        "dueDate": "2026-10-30",
        "clientId": "6ad6af41d3199442d31b2743",
    },
)

data = response.json()["data"]
```

### Example response (201 Created)

```json
{
  "data": {
    "id": "6ad6af8764ce168864cfa985",
    "title": "Call Jordan about their new program",
    "status": "open",
    "dueDate": "2026-10-30",
    "client": {
      "id": "6ad6af41d3199442d31b2743",
      "name": "Jordan Miller"
    },
    "assignee": {
      "id": "6ad6af42386c5341386ac044",
      "name": "Alex Carter"
    },
    "createdBy": {
      "id": "6ad6af42386c5341386ac044",
      "name": "Alex Carter"
    },
    "createdAt": "2026-03-02T15:04:11.000Z",
    "updatedAt": "2026-10-26T09:12:40.000Z",
    "completedAt": null,
    "completedBy": null
  }
}
```

## Get a task

`GET https://api.hubfit.com/v1/tasks/{taskId}`

One task you can see. Requires `tasks:write`.

### Path parameters

- `taskId` (string, required): A task `id` from `GET /tasks`.

### Returns

The task.

### Example request

cURL:

```bash
curl https://api.hubfit.com/v1/tasks/6ad6af8764ce168864cfa985 \
  -H "Authorization: Bearer $HUBFIT_API_KEY"
```

Node.js:

```javascript
const response = await fetch("https://api.hubfit.com/v1/tasks/6ad6af8764ce168864cfa985", {
  headers: {
    Authorization: `Bearer ${process.env.HUBFIT_API_KEY}`,
  },
});

const { data } = await response.json();
```

Python:

```python
import os
import requests

response = requests.get(
    "https://api.hubfit.com/v1/tasks/6ad6af8764ce168864cfa985",
    headers={"Authorization": f"Bearer {os.environ['HUBFIT_API_KEY']}"},
)

data = response.json()["data"]
```

### Example response (200 OK)

```json
{
  "data": {
    "id": "6ad6af8764ce168864cfa985",
    "title": "Call Jordan about their new program",
    "status": "open",
    "dueDate": "2026-10-30",
    "client": {
      "id": "6ad6af41d3199442d31b2743",
      "name": "Jordan Miller"
    },
    "assignee": {
      "id": "6ad6af42386c5341386ac044",
      "name": "Alex Carter"
    },
    "createdBy": {
      "id": "6ad6af42386c5341386ac044",
      "name": "Alex Carter"
    },
    "createdAt": "2026-03-02T15:04:11.000Z",
    "updatedAt": "2026-10-26T09:12:40.000Z",
    "completedAt": null,
    "completedBy": null
  }
}
```

## Change a task

`PATCH https://api.hubfit.com/v1/tasks/{taskId}`

Changes only the fields you send. `null` clears the due date or the client, or unassigns the task. `status` completes a task, as ticking it in the app does, or reopens it; a task that already has that status is left as it is. Reopening counts toward the workspace's 250 open tasks; past that it's `409 open_task_limit_reached` and nothing changes. Requires `tasks:write`.

### Path parameters

- `taskId` (string, required): A task `id` from `GET /tasks`.

### Body parameters

- `title` (string)
- `dueDate` (date, nullable): `YYYY-MM-DD` in your own calendar, or `null` for no due date.
- `assigneeId` (string, nullable): A coach who has joined your workspace, or `null` to unassign it.
- `clientId` (string, nullable): The client it's about, or `null` for none.
- `status` (enum): One of `open`, `completed`.

### Returns

The task as it is now.

### Example request

cURL:

```bash
curl -X PATCH https://api.hubfit.com/v1/tasks/6ad6af8764ce168864cfa985 \
  -H "Authorization: Bearer $HUBFIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dueDate": "2026-10-30"
  }'
```

Node.js:

```javascript
const response = await fetch("https://api.hubfit.com/v1/tasks/6ad6af8764ce168864cfa985", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.HUBFIT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    dueDate: "2026-10-30",
  }),
});

const { data } = await response.json();
```

Python:

```python
import os
import requests

response = requests.patch(
    "https://api.hubfit.com/v1/tasks/6ad6af8764ce168864cfa985",
    headers={"Authorization": f"Bearer {os.environ['HUBFIT_API_KEY']}"},
    json={
        "dueDate": "2026-10-30",
    },
)

data = response.json()["data"]
```

### Example response (200 OK)

```json
{
  "data": {
    "id": "6ad6af8764ce168864cfa985",
    "title": "Call Jordan about their new program",
    "status": "open",
    "dueDate": "2026-10-30",
    "client": {
      "id": "6ad6af41d3199442d31b2743",
      "name": "Jordan Miller"
    },
    "assignee": {
      "id": "6ad6af42386c5341386ac044",
      "name": "Alex Carter"
    },
    "createdBy": {
      "id": "6ad6af42386c5341386ac044",
      "name": "Alex Carter"
    },
    "createdAt": "2026-03-02T15:04:11.000Z",
    "updatedAt": "2026-10-26T09:12:40.000Z",
    "completedAt": null,
    "completedBy": null
  }
}
```
