Tags

Create tags, list them with live counts, and apply or remove one from up to a thousand contacts at once, by handle or by a saved segment.

Updated ·3 min read
GET/v1/tags

Tags are the same ad-hoc labels the dashboard's Signups table applies, first-class, renameable, colored, shared with segments (a tag condition filters on them) and with the "Add tag" / "Has a tag" automation steps. Nothing about tagging is API-specific.

Scopes#

Operation Scope
List tags contacts:read
Create, apply, remove contacts:write

List tags#

GET /v1/tags

Newest first, cursor-paginated (pagination). Each tag carries contacts_count, an index-backed count of how many contacts currently hold it, cheap even on a large audience because it never scans the contacts table itself.

Parameter Type Description
project string Required. A prj_ handle.
limit integer 1 to 100, default 25
starting_after string Page forward from this tag id
ending_before string Page backward

Create a tag#

POST /v1/tags

Idempotent by name within the project: creating a tag that already exists by that name returns the existing one (200) instead of a duplicate, so you can call this before every apply without a prior lookup. A brand new tag answers 201.

Parameter Type Required Description
project string Yes A prj_ handle.
name string Yes Up to 60 characters.
color string No A hex color, up to 32 characters.

Apply or remove a tag#

POST   /v1/tags/{tag}/contacts
DELETE /v1/tags/{tag}/contacts

{tag} is the tag_… handle from a list or create call. Both verbs take the identical body: an explicit list of contact handles, or a saved segment. Send exactly one of contacts / segment, never both, and never neither: either failure is a 422.

Parameter Type Description
contacts array of string con_… handles or uuids, 1 to 1000. Mutually exclusive with segment.
segment string A seg_… handle. Every contact it currently matches is affected, unless limit narrows it.
limit integer With segment only, 1 to 1000. Affects the oldest matching contacts first, by signup date.

Both responses are a tag_apply_result: the tag (with its refreshed contacts_count), matched (how many contacts the request resolved to before applying anything), and attached (on the add call) or detached (on the remove call), how many rows actually changed. A contact that already carried the tag (or never did, on remove) is left alone and does not count toward that number.

Nothing else happens: no webhook, no automation, no email. Contacts held past the workspace's plan limit are silently excluded from both paths, the same as every other bulk action in the product.

Next#

Common questions

What scope does tagging need?

contacts:read to list tags, contacts:write to create one or apply/remove it. A tag is audience metadata, not a resource with its own blast radius, so it does not carry a scope of its own.

Does tagging send email or fire an automation?

No. Tagging carries no side effects today, over the dashboard or the API: no webhook, no automation trigger, no email.

How do I "tag the next 20 people who don't have this tag yet"?

Build a segment with a tag condition (operator: not_in, the tag's id) plus whatever else you want, save or preview it, then call POST /tags/{tag}/contacts with segment and limit: 20. The oldest 20 matches, by signup date, get tagged.

Can applying a tag touch contacts held past my plan's limit?

No. Held contacts are excluded from both the explicit-handle and the segment path, exactly like every other bulk action in the product.

Was this page helpful?
curl https://api.getlaunchlist.com/v1/tags/tag_9mvd4rq2ph7k/contacts \\
  -H "Authorization: Bearer llk_live_8xKq3Rp9Wm2Nz7Vt6yL1cG5dH0jA4sE8uNqB2fXk" \\
  -H "Content-Type: application/json" \\
  -d '{
    "segment": "seg_7qk2mn4pr8vx",
    "limit": 20
  }'
{
  "object": "tag_apply_result",
  "tag": {
    "object": "tag",
    "id": "tag_9mvd4rq2ph7k",
    "project": "prj_7Qk2mN4pR8",
    "name": "high-intent",
    "color": "#22c563",
    "contacts_count": 41,
    "created_at": "2026-08-02T09:12:04+00:00",
    "url": "/v1/tags/tag_9mvd4rq2ph7k"
  },
  "matched": 20,
  "attached": 18
}