User Tags
Create free-form labels to segment and filter users via the stemp API.
User Tags
User tags are free-form labels you can attach to users for segmentation, targeting, and filtering. Tags let you organize your user base into meaningful groups — such as "vip", "student", or "berlin-location" — and then query across those groups using boolean logic.
Required scopes: user_tag:read for read operations, user_tag:write for create/update/delete operations.
Tag Management
Create a Tag
curl -X POST https://api.stemp.app/api/v1/user-tags \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP",
"description": "High-value customers with premium benefits",
"color": "#FFD700"
}'| Field | Required | Description |
|---|---|---|
name | Yes | Tag display name (max 100 characters) |
description | No | Human-readable description (max 500 characters) |
color | No | Hex color code for UI display (e.g. #FFD700) |
A URL-safe slug is automatically generated from the name (e.g. "VIP" becomes vip). The slug is unique per organization and used in all subsequent API calls.
Response (201 Created):
{
"id": "utag_abc123",
"object": "UserTag",
"name": "VIP",
"slug": "vip",
"description": "High-value customers with premium benefits",
"color": "#FFD700",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-15T10:00:00Z"
}List All Tags
curl https://api.stemp.app/api/v1/user-tags \
-H "Authorization: Bearer <token>"Response (200 OK):
[
{
"id": "utag_abc123",
"object": "UserTag",
"name": "VIP",
"slug": "vip",
"description": "High-value customers with premium benefits",
"color": "#FFD700",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-15T10:00:00Z"
},
{
"id": "utag_def456",
"object": "UserTag",
"name": "Student",
"slug": "student",
"description": "Verified student discount recipients",
"color": "#4A90D9",
"createdAt": "2026-01-16T09:00:00Z",
"updatedAt": "2026-01-16T09:00:00Z"
}
]Get a Tag by Slug
curl https://api.stemp.app/api/v1/user-tags/vip \
-H "Authorization: Bearer <token>"Response (200 OK):
{
"id": "utag_abc123",
"object": "UserTag",
"name": "VIP",
"slug": "vip",
"description": "High-value customers with premium benefits",
"color": "#FFD700",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-15T10:00:00Z"
}Update a Tag
Use PUT to update tag properties. All fields are optional — only provided fields are changed.
curl -X PUT https://api.stemp.app/api/v1/user-tags/vip \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP Gold",
"description": "Top-tier loyalty members",
"color": "#DAA520"
}'Response (200 OK):
{
"id": "utag_abc123",
"object": "UserTag",
"name": "VIP Gold",
"slug": "vip",
"description": "Top-tier loyalty members",
"color": "#DAA520",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-20T14:30:00Z"
}Note that the slug does not change when you rename a tag.
Delete a Tag
curl -X DELETE https://api.stemp.app/api/v1/user-tags/vip \
-H "Authorization: Bearer <token>"Response: 204 No Content
Deleting a tag automatically removes it from all users that had it assigned. This also triggers a user_tag.unassigned webhook event for each affected user.
Tag Assignments
Tags are assigned to users by referencing the tag slug and the user ID.
List Tags for a User
curl https://api.stemp.app/api/v1/users/usr_xyz789/tags \
-H "Authorization: Bearer <token>"Response (200 OK):
[
{
"id": "utag_abc123",
"object": "UserTag",
"name": "VIP",
"slug": "vip",
"description": "High-value customers with premium benefits",
"color": "#FFD700",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-15T10:00:00Z"
},
{
"id": "utag_ghi789",
"object": "UserTag",
"name": "Berlin Location",
"slug": "berlin-location",
"description": null,
"color": "#E74C3C",
"createdAt": "2026-02-01T08:00:00Z",
"updatedAt": "2026-02-01T08:00:00Z"
}
]Assign a Tag to a User
curl -X POST https://api.stemp.app/api/v1/users/usr_xyz789/tags/vip \
-H "Authorization: Bearer <token>"Response (201 Created):
{
"id": "utag_asn_abc123",
"object": "UserTagAssignment",
"userTag": {
"id": "utag_abc123",
"object": "UserTag",
"name": "VIP",
"slug": "vip",
"description": "High-value customers with premium benefits",
"color": "#FFD700",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-15T10:00:00Z"
},
"createdAt": "2026-01-20T12:00:00Z",
"updatedAt": "2026-01-20T12:00:00Z"
}Assigning a tag that is already assigned to the user returns a 409 Conflict error.
Unassign a Tag from a User
curl -X DELETE https://api.stemp.app/api/v1/users/usr_xyz789/tags/vip \
-H "Authorization: Bearer <token>"Response: 204 No Content
List Users by Tag
Retrieve all users that have a specific tag assigned:
curl https://api.stemp.app/api/v1/user-tags/vip/users \
-H "Authorization: Bearer <token>"Response (200 OK):
[
{
"id": "usr_xyz789",
"object": "user",
"email": "jane@example.com",
"name": "Jane Doe",
"phone": "+491701234567",
"externalId": "cust_123",
"metadata": {},
"createdAt": "2026-01-15T10:30:00Z",
"updatedAt": "2026-01-15T10:30:00Z"
},
{
"id": "usr_abc456",
"object": "user",
"email": "max@example.com",
"name": "Max Mustermann",
"phone": null,
"externalId": "cust_456",
"metadata": {},
"createdAt": "2026-01-10T08:00:00Z",
"updatedAt": "2026-01-12T14:00:00Z"
}
]Segmentation Queries
The query endpoint lets you find users matching complex tag-based filters using boolean logic. This is useful for building audiences, running campaigns, or exporting segments.
Query Users by Tags
curl -X POST https://api.stemp.app/api/v1/user-tags/query \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"operator": "AND",
"conditions": [
{ "slug": "vip" },
{ "slug": "berlin-location" }
]
},
"page": 0,
"size": 20
}'Required scope: user_tag:read
Filter Structure
A filter is a recursive structure with an operator and either conditions (leaf-level tag matches) or nested filters (for combining groups).
| Field | Type | Description |
|---|---|---|
operator | AND | OR | NOT | Boolean operator to apply |
conditions | TagCondition[] | List of tag slugs to match |
filters | TagFilter[] | Nested sub-filters for complex logic |
A TagCondition has a single field:
| Field | Type | Description |
|---|---|---|
slug | string | The tag slug to match against |
Pagination
| Parameter | Default | Description |
|---|---|---|
page | 0 | Page number (0-based) |
size | 20 | Items per page (min: 1, max: 100) |
Response (200 OK):
{
"content": [
{
"id": "usr_xyz789",
"object": "user",
"email": "jane@example.com",
"name": "Jane Doe",
"phone": "+491701234567",
"externalId": "cust_123",
"metadata": {},
"createdAt": "2026-01-15T10:30:00Z",
"updatedAt": "2026-01-15T10:30:00Z"
}
],
"totalElements": 1,
"totalPages": 1,
"size": 20,
"number": 0,
"first": true,
"last": true,
"empty": false
}Operators
AND — users must have all specified tags:
{
"filter": {
"operator": "AND",
"conditions": [
{ "slug": "vip" },
{ "slug": "berlin-location" }
]
}
}Returns users that are tagged with both "vip" and "berlin-location".
OR — users must have at least one of the specified tags:
{
"filter": {
"operator": "OR",
"conditions": [
{ "slug": "student" },
{ "slug": "early-bird" }
]
}
}Returns users tagged with "student" or "early-bird" (or both).
NOT — exclude users with the specified tags:
{
"filter": {
"operator": "NOT",
"conditions": [
{ "slug": "churned" }
]
}
}Returns users that do not have the "churned" tag.
Nested Filters
Combine operators to build complex queries. Use the filters field to nest sub-filters:
{
"filter": {
"operator": "AND",
"filters": [
{
"operator": "OR",
"conditions": [
{ "slug": "vip" },
{ "slug": "loyal-customer" }
]
},
{
"operator": "NOT",
"conditions": [
{ "slug": "churned" }
]
},
{
"operator": "OR",
"conditions": [
{ "slug": "berlin-location" },
{ "slug": "munich-location" }
]
}
]
},
"page": 0,
"size": 50
}This query reads as: users who are (VIP or loyal-customer) and not churned and located in (Berlin or Munich).
Endpoint Summary
| Method | Path | Scope | Description |
|---|---|---|---|
POST | /v1/user-tags | user_tag:write | Create a tag |
GET | /v1/user-tags | user_tag:read | List all tags |
GET | /v1/user-tags/{slug} | user_tag:read | Get a tag by slug |
PUT | /v1/user-tags/{slug} | user_tag:write | Update a tag |
DELETE | /v1/user-tags/{slug} | user_tag:write | Delete a tag |
GET | /v1/users/{userId}/tags | user_tag:read | List tags for a user |
POST | /v1/users/{userId}/tags/{tagSlug} | user_tag:write | Assign tag to user |
DELETE | /v1/users/{userId}/tags/{tagSlug} | user_tag:write | Unassign tag from user |
GET | /v1/user-tags/{slug}/users | user_tag:read | List users with a tag |
POST | /v1/user-tags/query | user_tag:read | Query users by tag filters |