stemp Logostemp Developer

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"
  }'
FieldRequiredDescription
nameYesTag display name (max 100 characters)
descriptionNoHuman-readable description (max 500 characters)
colorNoHex 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).

FieldTypeDescription
operatorAND | OR | NOTBoolean operator to apply
conditionsTagCondition[]List of tag slugs to match
filtersTagFilter[]Nested sub-filters for complex logic

A TagCondition has a single field:

FieldTypeDescription
slugstringThe tag slug to match against

Pagination

ParameterDefaultDescription
page0Page number (0-based)
size20Items 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

MethodPathScopeDescription
POST/v1/user-tagsuser_tag:writeCreate a tag
GET/v1/user-tagsuser_tag:readList all tags
GET/v1/user-tags/{slug}user_tag:readGet a tag by slug
PUT/v1/user-tags/{slug}user_tag:writeUpdate a tag
DELETE/v1/user-tags/{slug}user_tag:writeDelete a tag
GET/v1/users/{userId}/tagsuser_tag:readList tags for a user
POST/v1/users/{userId}/tags/{tagSlug}user_tag:writeAssign tag to user
DELETE/v1/users/{userId}/tags/{tagSlug}user_tag:writeUnassign tag from user
GET/v1/user-tags/{slug}/usersuser_tag:readList users with a tag
POST/v1/user-tags/queryuser_tag:readQuery users by tag filters