PPactDocs
CRM

Tag detail

Everything a single tag is attached to — filter by entity type, bulk-detach, and edit the tag — backed by the polymorphic tag_links join.

Tag detail

The tag detail view at /tags/{id} lists every entity a single tag is attached to, with per-entity-type filtering, bulk detach, and a quick edit affordance. It is backed by the /v1/tags API (api/routes/tags.py) and two tenant-scoped tables: tags (the catalog) and tag_links (one row per attachment).

Live surface

Tag CRUD, attach/detach, and the links listing are all real, enforced endpoints. Tags are a genuine cross-entity primitive, not a mock.

The data model

A tag is a small catalog row — name, slug, color, description — unique per tenant on slug. Attachments live in tag_links, whose entity_id is a VARCHAR(64) so the one join table handles both integer-PK and string-PK entities. The uniqueness constraint uq_tag_links_attach on (tenant_id, tag_id, entity_type, entity_id) makes attaching idempotent — re-attaching the same entity returns the existing link with already_attached: true rather than duplicating it.

What the detail view shows

GET /v1/tags/{id}/links returns the attachments, newest first, with a total count and pagination (limit / offset). Pass entity_type to filter to a single kind. The view renders each link with the right icon and a deep link into that record — accounts, contacts, opportunities, sequences, and campaigns among the recognized types.

bash
# Every entity this tag touches
curl -s "$PACT/v1/tags/42/links?limit=100" \
  -H "Authorization: Bearer $TOKEN"

# Just the contacts
curl -s "$PACT/v1/tags/42/links?entity_type=contact" \
  -H "Authorization: Bearer $TOKEN"

Attaching and detaching

  1. 1

    Attach an entity

    POST /v1/tags/{id}/attach with { "entity_type": "...", "entity_id": "..." }. Idempotent: a duplicate returns the existing link flagged already_attached.

  2. 2

    Detach individually or in bulk

    DELETE /v1/tags/{id}/attach with the same body removes one link. The detail view supports bulk-detach across the filtered set.

  3. 3

    Edit the tag itself

    PATCH /v1/tags/{id} updates name, color, or description. The catalog row is shared by every attachment, so an edit recolors the tag everywhere at once.

Deleting a tag

DELETE /v1/tags/{id} removes the tag and all of its tag_links in one transaction — deletion cascades to the attachments, so a deleted tag leaves no dangling links. Every mutation is tenant-scoped: tenant_id is derived from the auth context on every route, never from the request body.