# impartire API — Reference: Asset tags

Every path is under `https://impartire.com/api/v1`. The machine-readable contract is https://impartire.com/api/v1/openapi.json (OpenAPI 3.1).

#### GET /api/v1/assets/{id}/tags

List the tags on an asset

Every version of an asset shows the same tags; the asset's ETag moves when its tags change. At most 500, ordered by the tag's normalized name; no cursor.

Scopes: `assets:read`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).

Response 200 — `TagLinkList`

- `data` (array of TagLink, required) — Ordered by the tag's normalized name. At most 500.
  - `id` (string (uuid), required) — The tag's id — what DELETE …/tags/{tag_id} and `{ id }` on POST …/tags take.
  - `name` (string, required) — The tag as first typed. Tags are matched by a normalized form: case, extra spaces and invisible characters are ignored.
  - `scope` ("org" | "team", required) — `org`: the whole org's. `team`: private to one team (an OAuth token sees it only when its person is in the team or an org admin).
  - `team` (object or null, required) — The owning team, for a team tag; null for an org tag.
    - `id` (string (uuid), required)
    - `name` (string, required)
  - `usage_count` (integer, required) — How many assets and projects carry the tag, across the org.
  - `source` ("user" | "generated", required) — `user`: a person or an API credential added it. `generated`: applied from a generated summary.
  - `added_at` (string (date-time), required)
- `next_cursor` (string or null, required) — Always null: the list is returned whole (at most 500).

Other responses:

- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope — the key lacks a required scope.
- 404 (Problem) — not-found.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.

#### POST /api/v1/assets/{id}/tags

Add tags to an asset

Each item is `{ name }` — the org's tag of that name, created as an org tag when there is none — or `{ id }` of an existing tag (the only way to add a team tag). A tag already on the asset stays as it was, so the call is safe to repeat: no Idempotency-Key, no If-Match. Answers the asset's whole tag list after. An OAuth token's person needs edit on the asset.

Scopes: `assets:write`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).

Request body — `AddTagsRequest`

- `tags` (array of object or object, required) — 1–50 tags, each `{ name }` or `{ id }`.
  - `name` (string, required) — A tag name. The org's tag of that name is used, or created as an org tag if there is none.

Response 200 — `TagLinkList`

- `data` (array of TagLink, required) — Ordered by the tag's normalized name. At most 500.
  - `id` (string (uuid), required) — The tag's id — what DELETE …/tags/{tag_id} and `{ id }` on POST …/tags take.
  - `name` (string, required) — The tag as first typed. Tags are matched by a normalized form: case, extra spaces and invisible characters are ignored.
  - `scope` ("org" | "team", required) — `org`: the whole org's. `team`: private to one team (an OAuth token sees it only when its person is in the team or an org admin).
  - `team` (object or null, required) — The owning team, for a team tag; null for an org tag.
    - `id` (string (uuid), required)
    - `name` (string, required)
  - `usage_count` (integer, required) — How many assets and projects carry the tag, across the org.
  - `source` ("user" | "generated", required) — `user`: a person or an API credential added it. `generated`: applied from a generated summary.
  - `added_at` (string (date-time), required)
- `next_cursor` (string or null, required) — Always null: the list is returned whole (at most 500).

Other responses:

- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope, or insufficient-permission — an OAuth token's person may see the asset but lacks edit on the asset.
- 404 (Problem) — not-found.
- 422 (Problem) — validation (`tags`: 1–50 items, each `{ name }` or `{ id }`; a name that is empty or over 64 characters), or unknown-tag.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.

#### DELETE /api/v1/assets/{id}/tags/{tag_id}

Remove a tag from an asset

Takes the tag off the asset; the tag stays in the org's list. 404 when the asset does not carry it, so a second DELETE is a 404.

Scopes: `assets:write`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).
- `tag_id` (path, string (uuid), required) — The tag's id, from GET …/tags.

Other responses:

- 204 — Removed.
- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope, or insufficient-permission — an OAuth token's person lacks edit on the asset.
- 404 (Problem) — not-found.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.
