Skip to main content

Tags

Apps can be tagged for organization and filtering. Tags are managed through the TagEntity association.

GET /api/apps/{id}/tags

Get all tags assigned to an app.

Authentication: Required

Permissions Required: None (any user who can read the app)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID

Response:

Returns a HAL collection of TagEntity records with embedded Tag details.

{
"_links": {
"self": { "href": "/api/apps/analytics:sales-dashboard/tags" }
},
"_embedded": {
"inf:tag-entity": [
{
"_links": {
"self": { "href": "/api/apps/analytics:sales-dashboard/tags/tag-uuid-1" },
"inf:tag": { "href": "/api/tags/tag-uuid-1" }
},
"id": "te-uuid-1",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"tagId": "tag-uuid-1",
"_embedded": {
"inf:tag": {
"id": "tag-uuid-1",
"name": "Sales",
"color": "blue",
"createdAt": "2023-01-15T10:00:00.000Z"
}
}
},
{
"_links": {
"self": { "href": "/api/apps/analytics:sales-dashboard/tags/tag-uuid-2" },
"inf:tag": { "href": "/api/tags/tag-uuid-2" }
},
"id": "te-uuid-2",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"tagId": "tag-uuid-2",
"_embedded": {
"inf:tag": {
"id": "tag-uuid-2",
"name": "Dashboard",
"color": "green",
"createdAt": "2023-01-15T10:05:00.000Z"
}
}
}
]
},
"items": [...]
}

Key Fields:

FieldDescription
appIdApp UUID
tagIdTag UUID
_embedded.inf:tagFull tag details (name, color, etc.)

Error Responses:

  • 404 Not Found - App doesn't exist or user lacks access

GET /api/apps/{id}/tags/{tagId}

Get a specific tag assignment.

Authentication: Required

Permissions Required: None (any user who can read the app)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID
tagIdstringTag UUID

Response:

{
"_links": {
"self": { "href": "/api/apps/analytics:sales-dashboard/tags/tag-uuid-1" },
"inf:app": { "href": "/api/apps/analytics:sales-dashboard" },
"inf:tag": { "href": "/api/tags/tag-uuid-1" }
},
"id": "te-uuid-1",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"tagId": "tag-uuid-1",
"createdAt": "2024-02-10T10:00:00.000Z",
"updatedAt": "2024-02-10T10:00:00.000Z"
}

Error Responses:

  • 404 Not Found - App, tag, or assignment doesn't exist

PUT /api/apps/{id}/tags/{tagId}

Assign a tag to an app (create a TagEntity).

Authentication: Required

Permissions Required: Member+ role (assignTags permission)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID
tagIdstringTag UUID

Payload:

No payload required (or empty object).

Response:

Returns the created/existing TagEntity with status 200 OK or 201 Created.

{
"id": "te-uuid-1",
"appId": "d4f8a2b1-1234-5678-90ab-cdef12345678",
"tagId": "tag-uuid-1",
"createdAt": "2024-02-13T10:30:00.000Z",
"updatedAt": "2024-02-13T10:30:00.000Z"
}

Upsert Behavior:

  • If the tag is already assigned, returns the existing TagEntity
  • If not assigned, creates a new TagEntity
  • Idempotent operation

Error Responses:

  • 404 Not Found - App or tag doesn't exist, or user lacks access
  • 403 Forbidden - User lacks assignTags permission

DELETE /api/apps/{id}/tags/{tagId}

Remove a tag assignment from an app.

Authentication: Required

Permissions Required: Member+ role (assignTags permission)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID
tagIdstringTag UUID

Response:

Returns 204 No Content on success.

Error Responses:

  • 404 Not Found - App, tag, or assignment doesn't exist
  • 403 Forbidden - User lacks assignTags permission

Common Tag Operations

Assign Multiple Tags

const tagIds = ['tag-uuid-1', 'tag-uuid-2', 'tag-uuid-3'];

for (const tagId of tagIds) {
await PUT(`/api/apps/analytics:sales-dashboard/tags/${tagId}`);
}

Get App's Tags

const response = await GET('/api/apps/analytics:sales-dashboard/tags');

const tagNames = response.items.map(item => item._embedded['inf:tag'].name);
console.log('Tags:', tagNames.join(', '));

Remove All Tags

// Get current tags
const response = await GET('/api/apps/analytics:sales-dashboard/tags');

// Remove each one
for (const item of response.items) {
await DELETE(`/api/apps/analytics:sales-dashboard/tags/${item.tagId}`);
}

Replace Tags

const newTagIds = ['tag-uuid-4', 'tag-uuid-5'];

// Get current tags
const current = await GET('/api/apps/analytics:sales-dashboard/tags');

// Remove tags not in new set
for (const item of current.items) {
if (!newTagIds.includes(item.tagId)) {
await DELETE(`/api/apps/analytics:sales-dashboard/tags/${item.tagId}`);
}
}

// Add new tags
for (const tagId of newTagIds) {
await PUT(`/api/apps/analytics:sales-dashboard/tags/${tagId}`);
}

Check if App Has Tag

try {
await GET('/api/apps/analytics:sales-dashboard/tags/tag-uuid-1');
console.log('App has this tag');
} catch (e) {
if (e.statusCode === 404) {
console.log('App does not have this tag');
}
}

Tag Permissions

The assignTags permission requires Member+ role (same as write permission). This means:

  • Members can view tags but not assign/remove them
  • Member+ and above can modify tag assignments
  • Superusers can always modify tags

Integration with App List

Tags are included in the /api/apps-list response:

{
"id": "d4f8a2b1-...",
"name": "Sales Dashboard",
"tags": ["tag-uuid-1", "tag-uuid-2"],
...
}

And in the single app response (GET /api/apps/{id}):

{
"id": "d4f8a2b1-...",
"name": "Sales Dashboard",
"tags": ["tag-uuid-1", "tag-uuid-2"],
...
}

This allows clients to filter and organize apps by tags without making additional requests.