# Projects and tags: Mosaic API reference

> Projects and tags in Mosaic’s local REST API: 9 routes, each with its method, path, fields, what it returns and the errors it names.

Source: https://mosaicbrowser.com/docs/api/organisation

**Profiles** REST API

## Projects and tags

The two axes profiles are organised on: one project each, any number of tags.

- [GETList projects](#list-projects)
- [POSTCreate a project](#create-project)
- [GETRead one project](#get-project)
- [PATCHUpdate a project](#update-project)
- [DELETEMove a project to the trash](#delete-project)
- [GETList tags](#list-tags)
- [POSTCreate a tag](#create-tag)
- [PATCHUpdate a tag](#update-tag)
- [DELETEDelete a tag](#delete-tag)

## [List projects](#list-projects)

GET`/api/v1/projects`

Every project with its profile count.

#### Returns

`{ total, projects: Project[] }` — each with `profileCount` (every profile in the project) and `mobileProfileCount` (the Android ones among them). Exactly one carries `system: true`; see `PATCH /projects/:id` for what that fixes.

## [Create a project](#create-project)

POST`/api/v1/projects`

A project is a workspace with its own profiles, proxies and extensions. Its colour and icon are what appear on the Dock icon of every profile launched from it.

#### Body

| Field | Type | What it is |
| --- | --- | --- |
| `name`required | `string` | Display name. |
| `icon` | `string` | Icon id from the built-in set, e.g. "rocket". |
| `color` | `string` | Hex colour. |

#### Returns

The created `Project`.

## [Read one project](#get-project)

GET`/api/v1/projects/:id`

One project with its profile count.

#### Path parameters

| Field | Type | What it is |
| --- | --- | --- |
| `id`required | `string` | The record’s id. |

#### Returns

A `Project`.

#### Errors

- 404 — no such project.

## [Update a project](#update-project)

PATCH`/api/v1/projects/:id`

Rename, recolour or change the icon. Changing colour or icon changes the Dock icon of its profiles on their next launch. **One project refuses all three.** Exactly one project carries `system: true` — the one Mosaic created at first launch, where every profile lands before anybody files it. It wears the Mosaic mark on white and its `name`, `icon` and `color` are fixed, so that what every other surface calls it stays true; sending any of them is a `400` naming the field, never a silent no-op. `sortOrder` is still yours: where it sits in the list changes nothing about what it is.

#### Path parameters

| Field | Type | What it is |
| --- | --- | --- |
| `id`required | `string` | The record’s id. |

#### Body

`Partial<Project>`. name, icon, color, sortOrder.

#### Returns

The updated `Project`.

#### Errors

- `400` — `name`, `icon` or `color` on the `system` project.

## [Move a project to the trash](#delete-project)

DELETE`/api/v1/projects/:id`

Takes its profiles with it. Everything stays restorable for 30 days. Refused for the last remaining project, and for the `system` project — nothing re-creates that one, so deleting it would quietly end the concept for this installation. Every browser open in the project is closed first, and one that will not close keeps the whole project.

#### Path parameters

| Field | Type | What it is |
| --- | --- | --- |
| `id`required | `string` | The record’s id. |

#### Returns

`{ deleted: true, stopped }` — `stopped` counts the browsers closed on the way.

#### Errors

- `400` — the last project, the `system` project, or a browser that would not close.

## [List tags](#list-tags)

GET`/api/v1/tags`

Tags defined in a project.

#### Query parameters

| Field | Type | What it is |
| --- | --- | --- |
| `projectId` | `string` | Restrict to one project. |

#### Returns

`{ total, tags: Tag[] }`

## [Create a tag](#create-tag)

POST`/api/v1/tags`

Tags are a secondary axis within a project, and carry a colour used throughout the interface.

#### Body

| Field | Type | What it is |
| --- | --- | --- |
| `name`required | `string` | Tag name. |
| `color` | `string` | Hex colour. |
| `projectId` | `string` | Owning project. |

#### Returns

The created `Tag`.

## [Update a tag](#update-tag)

PATCH`/api/v1/tags/:id`

Rename a tag or change its colour. A rename reaches every profile carrying it, because profiles store tags by name — this is the only correct way to change one. Renaming onto a name that already exists in the same project is a `400` rather than a merge: two tags with one name would both match the same filter, and merging them is a bigger decision than a rename. Any field other than `name` and `color` is a `400`, so a misspelled key cannot be a `200` that changed nothing.

#### Path parameters

| Field | Type | What it is |
| --- | --- | --- |
| `id`required | `string` | The record’s id. |

#### Body

| Field | Type | What it is |
| --- | --- | --- |
| `name` | `string` | The new name. Renames it on every profile that carries it. |
| `color` | `string` | A hex colour like `#2b7fbd`. Anything else is a `400` — a colour the browser cannot parse renders as no colour at all. |

#### Returns

The updated `Tag`.

#### Errors

- 400 — an unknown field, an empty name, a colour that is not `#rrggbb`, or a name another tag in the project already has.
- 404 — no tag with that id.

## [Delete a tag](#delete-tag)

DELETE`/api/v1/tags/:id`

Removes it from every profile that carries it.

#### Path parameters

| Field | Type | What it is |
| --- | --- | --- |
| `id`required | `string` | The record’s id. |

#### Returns

`{ deleted: true }`

## Run the API on your own profiles

The REST API and the MCP server are part of Pro: $49 a month, with the first 14 days free. Free has every browser feature and no API key.

Mosaic is a desktop app

Email yourself the link and open it on your computer.
