Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Labels, Tags & Organization

Labels are colored markers you attach to tickets for visual categorization (e.g. bug, feature, urgent). Tags are arbitrary key-value pairs you attach to any entity (projects, tickets, users, teams, time entries) for filtering and reporting. This guide covers creating, assigning, searching, and filtering with both.

1. Prerequisites

You need a running Alloy server and a registered user. Set these shell variables for the examples below:

BASE_URL="http://localhost:3000"

Register a user and capture the token:

curl -s -X POST "$BASE_URL/api/v1/auth/register" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "guide-lt@alloy.dev",
    "password": "guide-lt-pass1",
    "display_name": "LT Guide User"
  }' | jq .
{
  "user_id": "...",
  "email": "guide-lt@alloy.dev",
  "display_name": "LT Guide User",
  "access_token": "..."
}

Save the token and user ID:

TOKEN="<access_token from above>"
USER_ID="<user_id from above>"

Create an organization:

curl -s -X POST "$BASE_URL/api/v1/orgs" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "name": "LT Guide Org",
    "slug": "guide-lt-org"
  }' | jq .
{
  "id": "...",
  "name": "LT Guide Org",
  "slug": "guide-lt-org"
}
ORG_ID="<id from above>"

Create a project and a ticket for the examples that follow:

curl -s -X POST "$BASE_URL/api/v1/projects" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d "{
    \"org_id\": \"$ORG_ID\",
    \"key\": \"LTAG\",
    \"name\": \"Labels Tags Demo\"
  }" | jq .
{
  "id": "...",
  "org_id": "...",
  "key": "LTAG",
  "name": "Labels Tags Demo",
  "ticket_counter": 0
}
PROJECT_ID="<id from above>"
curl -s -X POST "$BASE_URL/api/v1/projects/$PROJECT_ID/tickets" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d "{
    \"title\": \"Tag demo ticket\",
    \"priority\": \"Medium\",
    \"reporter_id\": \"$USER_ID\"
  }" | jq .
{
  "id": "...",
  "project_id": "...",
  "ticket_number": 1,
  "title": "Tag demo ticket",
  "status": "Backlog",
  "priority": "Medium",
  "reporter_id": "...",
  "created_at": "...",
  "updated_at": "..."
}
TICKET_ID="<id from above>"

2. Create Labels

Labels belong to an organization and have a name and hex color. Create a few labels to categorize tickets:

curl -s -X POST "$BASE_URL/api/v1/orgs/$ORG_ID/labels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "bug", "color": "#FF0000"}' | jq .
{
  "id": "...",
  "org_id": "...",
  "name": "bug",
  "color": "#FF0000",
  "created_at": "...",
  "updated_at": "..."
}

Create a second label:

curl -s -X POST "$BASE_URL/api/v1/orgs/$ORG_ID/labels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "feature", "color": "#00FF00"}' | jq .
{
  "id": "...",
  "org_id": "...",
  "name": "feature",
  "color": "#00FF00",
  "created_at": "...",
  "updated_at": "..."
}

CLI shortcut: alloy label create --org $ORG_ID --name bug --color "#FF0000"

3. List & Get Labels

List all labels in your organization:

curl -s "$BASE_URL/api/v1/orgs/$ORG_ID/labels" \
  -H "Authorization: Bearer $TOKEN" | jq .
{
  "items": [
    {
      "id": "...",
      "org_id": "...",
      "name": "...",
      "color": "...",
      "created_at": "...",
      "updated_at": "..."
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Fetch a single label by ID:

curl -s "$BASE_URL/api/v1/labels/$LABEL_ID" \
  -H "Authorization: Bearer $TOKEN" | jq .
{
  "id": "...",
  "org_id": "...",
  "name": "...",
  "color": "...",
  "created_at": "...",
  "updated_at": "..."
}

4. Update & Delete Labels

Rename a label or change its color with a PATCH:

curl -s -X PATCH "$BASE_URL/api/v1/labels/$LABEL_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "critical-bug", "color": "#CC0000"}' | jq .
{
  "id": "...",
  "org_id": "...",
  "name": "critical-bug",
  "color": "#CC0000",
  "created_at": "...",
  "updated_at": "..."
}

To delete a label that is not in use, send a DELETE request. If tickets reference the label, use ?cascade=true to remove all associations first (or ?cascade=true&dry_run=true to preview the impact).

5. Assign Labels to Tickets

Add a label to a ticket:

curl -s -X POST "$BASE_URL/api/v1/tickets/$TICKET_ID/labels/$LABEL_ID" \
  -H "Authorization: Bearer $TOKEN" | jq .
[
  {
    "id": "...",
    "org_id": "...",
    "name": "...",
    "color": "...",
    "created_at": "...",
    "updated_at": "..."
  }
]

List all labels on a ticket:

curl -s "$BASE_URL/api/v1/tickets/$TICKET_ID/labels" \
  -H "Authorization: Bearer $TOKEN" | jq .
[
  {
    "id": "...",
    "org_id": "...",
    "name": "...",
    "color": "...",
    "created_at": "...",
    "updated_at": "..."
  }
]

To replace all labels on a ticket at once, POST a label_ids array:

curl -s "$BASE_URL/api/v1/tickets/$TICKET_ID/labels" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"label_ids\": [\"$LABEL_ID\"]}" | jq .
[
  {
    "id": "...",
    "org_id": "...",
    "name": "...",
    "color": "...",
    "created_at": "...",
    "updated_at": "..."
  }
]

To remove a single label from a ticket, send a DELETE:

curl -s -X DELETE "$BASE_URL/api/v1/tickets/$TICKET_ID/labels/$LABEL_ID" \
  -H "Authorization: Bearer $TOKEN"

This returns 204 No Content.

CLI shortcut: alloy ticket label add $TICKET_ID $LABEL_ID

6. Set Tags on Entities

Tags are key-value pairs that attach to any entity type: project, ticket, user, team, or time_entry. Use PUT to set or upsert tags — if a key already exists, its value is updated.

Tag a project:

curl -s -X PUT "$BASE_URL/api/v1/orgs/$ORG_ID/project/$PROJECT_ID/tags" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": [
      {"key": "department", "value": "engineering"},
      {"key": "environment", "value": "staging"}
    ]
  }' | jq .
[
  {
    "id": "...",
    "org_id": "...",
    "entity_type": "project",
    "entity_id": "...",
    "key": "department",
    "value": "engineering",
    "created_at": "...",
    "updated_at": "..."
  },
  {
    "id": "...",
    "org_id": "...",
    "entity_type": "project",
    "entity_id": "...",
    "key": "environment",
    "value": "staging",
    "created_at": "...",
    "updated_at": "..."
  }
]

Retrieve all tags on an entity:

curl -s "$BASE_URL/api/v1/orgs/$ORG_ID/project/$PROJECT_ID/tags" \
  -H "Authorization: Bearer $TOKEN" | jq .
[
  {
    "id": "...",
    "org_id": "...",
    "entity_type": "project",
    "entity_id": "...",
    "key": "...",
    "value": "...",
    "created_at": "...",
    "updated_at": "..."
  }
]

Delete a single tag by key:

curl -s -X DELETE "$BASE_URL/api/v1/orgs/$ORG_ID/project/$PROJECT_ID/tags/environment" \
  -H "Authorization: Bearer $TOKEN"

This returns 204 No Content.

Supported entity types: project, ticket, user, team, time_entry

7. Search by Tags

Find all entities with a matching tag key-value pair using the search endpoint. Results are paginated.

curl -s "$BASE_URL/api/v1/orgs/$ORG_ID/tags/search?key=department&value=engineering" \
  -H "Authorization: Bearer $TOKEN" | jq .
{
  "items": [
    {
      "id": "...",
      "org_id": "...",
      "entity_type": "project",
      "entity_id": "...",
      "key": "department",
      "value": "engineering",
      "created_at": "...",
      "updated_at": "..."
    }
  ],
  "next_cursor": null,
  "has_more": false
}

This returns all tagged entities across types — projects, tickets, users, teams, and time entries. Use the entity_type and entity_id fields in each result to look up the full entity.

8. Filter Reports by Tags

Capitalization reports support tag-based filtering via the tag query parameter. Use comma-separated key:value pairs to filter — multiple tags combine with AND logic.

For example, to generate a report scoped to a department:

GET /api/v1/reports/capitalization?period=2026-03&tag=department:engineering

Combine multiple tags:

GET /api/v1/reports/capitalization?period=2026-03&tag=department:engineering,environment:production

See the API Reference — Capitalization Reports for the full set of query parameters and response format.


Next: Teams, Roles & Permissions covers managing who can do what within your organization.