# List projects

URL: https://docs.hanzo.ai/docs/openapi/task/get-task-projects

> Returns the boards of your org — the places your work actually is.

`GET /v1/task/projects`

> [Task →](https://docs.hanzo.ai/docs/openapi/task) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                         |
| ------------- | --------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/task/projects` |
| **Method**    | `GET`                                   |
| **Operation** | `get_task_projects`                     |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY`  |

Returns the boards of your org — the places your work actually
is. The key addresses the board's issues.

A BOARD IS A PLACE WORK IS, not an object somebody provisioned. So the list is
assembled from the work itself: the repositories your org has filed issues on,
plus the boards the index holds. A repository with nothing on it is not in the
list and is still perfectly addressable — GET /projects/\<name> reads it and a
create files into it — so nothing is lost by leaving it out.

Measured, which is why: reading the forge's whole repository inventory put 745
boards here, of which all but a handful were vendored forks and mirrors
(.github, .profile, DOMPurify, BoatAttack) that will never carry this org's
work. A list that long is not a list — the estate's real roadmap was in it
somewhere and no one could see it.

The forge half is the FORGE's answer for your own account, so two people in
one org can legitimately see different boards.

## Request

`GET /v1/task/projects` takes no parameters and no body — the credential is the whole request.

## Response

| Status    | Body              | Meaning |
| --------- | ----------------- | ------- |
| `200`     | task.boardView\[] | ok      |
| `default` | problem-details   | refused |

`200` body — 7 fields.

| Field            | In   | Type            | Always | Description                                                                                                                            |
| ---------------- | ---- | --------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `[].createdAt`   | body | integer (int64) | —      | CreatedAt is when the board was created, in unix seconds.                                                                              |
| `[].description` | body | string          | —      | Description is whatever an index board was created with.                                                                               |
| `[].id`          | body | string          | —      | ID is the board's opaque handle, and it is NOT how you address it — Key is.                                                            |
| `[].key`         | body | string          | —      | Key addresses the board everywhere else — /v1/task/projects/\<key>/issues — and prefixes every issue identifier on it.                 |
| `[].name`        | body | string          | —      | Name is the board's display name.                                                                                                      |
| `[].org`         | body | string          | —      | Org is the IAM org the board belongs to, taken from the validated principal and never from the request.                                |
| `[].updatedAt`   | body | integer (int64) | —      | UpdatedAt is when the board record last changed, in unix seconds — the BOARD, not the work on it, so filing an issue does not move it. |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo task projects list
```

**SDK**

**.ts**

```ts
import { Configuration, TaskApi } from 'hanzoai';

const api = new TaskApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getTaskProjects();
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import TaskApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = TaskApi(client).get_task_projects()
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.TaskAPI.GetTaskProjects(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, task_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = task_api::get_task_projects(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.TaskApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new TaskApi(client).getTaskProjects();
```

**HTTP**

```bash
curl https://api.hanzo.ai/v1/task/projects \
  -H "Authorization: Bearer $HANZO_API_KEY"
```

**MCP**

MCP reaches **task** through the `task` tool, which names its 10 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "get_task_board"
         }
       }
     }'
```

---

[Task API](https://docs.hanzo.ai/docs/openapi/task) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
