Skip to main content

Overview

Tags let you organize contacts into groups. Each tag belongs to a workspace and can have a name, color, and emoji. Contacts can have multiple tags, and you can filter your contact list by one or more tags at once. The relationship between contacts and tags is many-to-many, managed through a contact_tags junction table. Tag assignment is idempotent — adding a tag that’s already assigned is a no-op.

Creating Tags

Create a tag via the UI or the API:
// POST /api/tags
{
  "name": "VIP",
  "color": "blue",
  "emoji": "⭐"
}
  • name is required (1–100 characters)
  • color and emoji are optional
Tags are scoped to the workspace — different workspaces can have tags with the same name without conflict.

Updating & Deleting Tags

  • UpdatePUT /api/tags/:id accepts partial updates (name, color, emoji)
  • DeleteDELETE /api/tags/:id permanently removes the tag and all its contact associations (via cascade)

Assigning Tags to Contacts

Tags are assigned and removed through dedicated endpoints:
POST   /api/tags/:tagId/contacts/:contactId   → Add tag to contact
DELETE /api/tags/:tagId/contacts/:contactId   → Remove tag from contact
Adding a tag uses onConflictDoNothing — if the contact already has that tag, the request succeeds silently. This makes the operation safe to retry without side effects. Both the tag and the contact must exist and belong to the same workspace, otherwise the API returns a 404.

Multi-Tag Filtering

When listing contacts, you can filter by multiple tags at once by passing a comma-separated list of tag IDs:
GET /api/contacts?tag_ids=uuid-1,uuid-2,uuid-3
The filter uses an ANY match — a contact appears in the results if it has at least one of the specified tags. The query joins contacts with contact_tags using inArray(contactTags.tag_id, tagIds). To avoid double-counting contacts that have multiple matching tags, the total count uses COUNT(DISTINCT contacts.id) instead of a plain COUNT(*).

Tags in Exports

When creating an export, you can optionally pass tagIds to export only contacts that match those tags. See the Exports guide for details.

Data Model

ColumnTypeDescription
idUUIDPrimary key
workspace_idUUIDWorkspace scope
nameVARCHAR(100)Tag display name
colorVARCHAR(20)Optional color identifier
emojiVARCHAR(10)Optional emoji
The contact_tags junction table has a composite unique constraint on (contact_id, tag_id) to prevent duplicate assignments.