Skip to content

Tags API

You can create, read, update, and delete tags programmatically, read how a tag is used, and move, remove, or merge it across its assets.

Tip

For complete API documentation, including request/response schemas, visit the API docs.

All endpoints use the base URL of your Qualytics deployment (e.g., https://your-instance.qualytics.io/api) and require a Personal API Token. Every endpoint requires the Member role. Creating, editing, and deleting a global tag requires the Admin role, and a team's tag also the Editor team permission on that team. Merging a tag requires the Admin role. See Tag Permissions for the full matrix.

Tags are applied from the asset

Putting a tag on an asset, or taking it off one asset, is done through that asset's own endpoint, by sending its full list of tag names. See, for example, the Datastore Tags API. The endpoints on this page manage the tags themselves and act on many assets at once.

Name or ID

The older endpoints address a tag by its name in the path, such as /global-tags/PII. The tag page endpoints address it by its numeric ID, such as /global-tags/42/summary. Encode a name with spaces or special characters in the URL.


Error Responses

Status Code Description
401 Unauthorized Missing or invalid API token.
403 Forbidden The user does not have the required role or team permission, or the endpoint needs the Data Catalog module.
404 Not Found No tag you can see has the specified name or ID, or the team does not exist.
409 Conflict A tag with that name already exists, or the tag's assets are being updated by another change. Try again in a moment.
422 Unprocessable Entity Invalid request body, such as an invalid name or color, a weight outside -10 to 10, a move or merge onto the same tag or an external tag, or a team tag applied outside its team's datastores.
Error response examples

409 Conflict (name taken):

{ "detail": "global tag name: 'PII' already exists" }

422 Unprocessable Entity (external tags in a move, remove, or merge):

{ "detail": "External tags cannot be moved, removed or merged, or used as a target" }

List Tags

Returns a paginated list of the tags you can see: global and external tags, plus the tags of your teams. Each tag comes with its asset count and quality score.

Endpoint: GET /global-tags

Permission: Member role or above

Query Parameter Type Description
name string Match a piece of the tag name, ignoring case.
type list of strings global, external, or both (the default).
category list of strings Only tags in these categories.
scope list global for global tags (external ones included), or a team ID for that team's tags. Several values combine with OR.
filters string (JSON) Narrows the list by category or scope, written as a JSON object. See Filtering Lists.
sort_name, sort_created, sort_weight, sort_color, sort_category, sort_asset_count asc / desc Sort by name, creation date, weight, color, category, or number of tagged assets.
Example request and response

Request:

curl -X GET "https://your-instance.qualytics.io/api/global-tags?category=Sensitivity&sort_weight=desc" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (abbreviated):

{
  "items": [
    {
      "id": 12,
      "type": "global",
      "name": "PII",
      "color": "#E53935",
      "description": "Fields that hold personal data.",
      "category": "Sensitivity",
      "weight_modifier": 8,
      "team": null,
      "asset_count": 214,
      "quality_score": { "total": 87.0 }
    }
  ],
  "total": 1,
  "page": 1,
  "size": 50
}

Filtering Lists

GET /api/global-tags accepts a filters parameter: a JSON object with one entry per filter, saying how that filter's values should match.

curl -G "https://your-instance.qualytics.io/api/global-tags" \
  --data-urlencode 'filters={"scope":{"in":["global"]},"category":{"empty":false}}' \
  -H "Authorization: Bearer YOUR_TOKEN"

This returns the global tags that have a category.

Key Returns
in The items that match at least one of the values.
not_in The items that match none of the values.
all_of The items that match every value, on filters an item can have several of, such as tags.
empty The items with no value (true) or at least one (false), on filters an item can lack.
  • Different filters combine with AND, and so do keys on the same filter.
  • empty can't be combined with other keys on the same filter.
  • A filter sent both as its own parameter and inside filters returns a 422. Put all of that filter's conditions in filters.
  • in, not_in and all_of each take between 1 and 20 values.
  • A filter or key the endpoint doesn't accept returns a 422 that names it. The API docs list what each endpoint accepts.

List Categories

Returns every category in use, as a list of strings.

Endpoint: GET /global-tags/categories

Permission: Member role or above


Get a Tag

Returns one tag by name.

Endpoint: GET /global-tags/{name}

Permission: Member role or above

Example response
{
  "id": 31,
  "type": "global",
  "name": "Q3 Close",
  "color": "#1E88E5",
  "description": "Tables the finance team reconciles each quarter.",
  "category": "Finance",
  "weight_modifier": 5,
  "team": { "id": 4, "name": "Finance", "display_label": "Finance" }
}

An external tag also carries the integration it was imported from.


Create a Tag

Endpoint: POST /global-tags

Permission: Admin role for a global tag. For a team tag, the Editor team permission on that team, other than the Public team.

Field Type Required Description
type string Yes global.
name string Yes Unique across the workspace. From 2 to 255 characters, with at least one letter. Only letters A-Z, digits, spaces, and _, -, . are allowed. Leading and trailing spaces are removed.
color string No A hex color code, such as #FF2000.
description string No What the tag means, in Markdown.
category string No The tag's category.
weight_modifier integer No From -10 to 10. Defaults to 1.
team_id integer No The team that owns the tag. Leave it out for a global tag.
Example request
curl -X POST "https://your-instance.qualytics.io/api/global-tags" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "global",
    "name": "Q3 Close",
    "color": "#1E88E5",
    "category": "Finance",
    "weight_modifier": 5,
    "team_id": 4
  }'

Tags Created From Other Endpoints

When you save a flow, check, check template, table, file, field, anomaly, or datastore through the API, or ask AgentQ to apply tags, a tag name that doesn't exist yet creates a new global tag. Only Admins can create tags this way, and the name follows the same rules as above:

  • A refused name fails the request with 422 Unprocessable Entity and Can't create tag '<name>'. <reason>, and the asset is not saved. AgentQ applies no tags in that case and tells you why.
  • Spaces at the start and end of a new name are refused instead of removed, except on datastores, which trim them before creating the tag.
  • Existing tags whose names predate these rules keep working on assets.

Update a Tag

Two endpoints update a tag. PUT addresses it by name and replaces the name, description, and category with what you send. PATCH addresses it by ID and changes only the fields you send.

Endpoints: PUT /global-tags/{name} and PATCH /global-tags/{id}

Permission: Same as creating the tag. Changing team_id requires the Admin role.

The body takes the same fields as Create a Tag, with type set to the tag's current type. A type cannot be changed.

  • Scope: Send team_id to restrict the tag to a team, or null to make it global. Leave it out to keep the current scope. Restricting the tag removes it from every asset outside the team's datastores, and making it global again does not put it back. See Changing a Tag's Scope.
  • External tags: Send "type": "external" with category and weight_modifier only. Their name, description, and color come from the data catalog.
Example request (change the weight)
curl -X PATCH "https://your-instance.qualytics.io/api/global-tags/31" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "type": "global", "weight_modifier": 8 }'

Delete a Tag

Deletes the tag and removes it from every asset that carries it, existing anomalies included. This cannot be undone. To keep the assets tagged, merge the tag instead.

Endpoints: DELETE /global-tags/{name} and POST /global-tags/{id}/delete

Permission: Same as creating the tag.


Read How a Tag Is Used

These endpoints return what the tag's page shows.

Endpoint Returns Requires Data Catalog
GET /global-tags/{id}/summary The number of assets carrying the tag, by type and by datastore, the number of Flows, how many assets are in datastores you can't access (hidden_count), and when and where the tag was last applied.
GET /global-tags/{id}/quality-score The tag's current quality score, across the tables and files that carry it.
GET /global-tags/{id}/quality-scores The score history. granularity picks the interval, day by default.
GET /global-tags/{id}/activity The timeline: changes to the tag, assets tagged and untagged, merges, scans, Flow runs, and comments. Pages through with size (up to 100) and the cursor from the previous page.
GET /global-tags/{id}/activity/{entry_id}/assets The assets one timeline entry touched, as they were then.
GET /global-tags/{id}/assets The assets carrying the tag, paginated.

The assets endpoint takes these query parameters:

Query Parameter Type Description
asset_type list of strings datastore, container, field, check, template, anomaly, flow, or operation.
datastore list of integers Only assets in these datastores.
container list of integers Only assets in these tables or files.
check_status list of strings Active or Draft, for checks.
anomaly_impact_level list of strings The impact levels of anomalies.
table_type list of strings table, view, file, or computed.
search string Match the asset's name or identifier.
sort string created (default) or name.
direction string desc (default) or asc.
page, size integer Page number, and page size up to 100.

Each asset in the response says whether you can edit it (editable), which decides whether a move or remove can reach it.


Explore the Tag Map

These endpoints return what the Map tab draws: the tagged assets as nodes, grouped by datastore, and the edges that connect them. Anomalies on the map are open ones only. All four require the Data Catalog module and the Member role or above, and take a JSON body.

Endpoint Returns
POST /global-tags/{id}/graph The first view of the map: the datastores and their first tables, the check templates and Flows that belong to no datastore (standalone), how many assets are in datastores you can't access (hidden_count), and where each branch continues.
POST /global-tags/{id}/graph/children One more page of a branch: the tables or operations of a datastore, or the fields, checks, or anomalies of a table.
POST /global-tags/{id}/graph/search The assets that match a search, grouped by type.
POST /global-tags/{id}/graph/locate One table, field, check, or anomaly with the path that leads to it, to center the map on it.

Every request takes a scope, which holds the same filters as the assets endpoint (datastore, container, search, check_status, anomaly_impact_level, and table_type) plus layers: any of fields, checks (checks and check templates), anomalies, and automation (Flows and operations), all four by default. On the first endpoint, these fields sit at the top level of the body, next to datastore_offset and standalone_offset, which page through datastores and standalone assets.

Endpoint Field Description
graph/children node_type datastore or container.
graph/children node_id The ID of that datastore or table.
graph/children relation containers or operations under a datastore. fields, checks, or anomalies under a table.
graph/children offset, size Where the page starts, and its size: up to 20 tables, or up to 12 of anything else (12 by default).
graph/children search Match the name or ID of the items in the branch.
graph/children check With anomalies, only the anomalies this check raised.
graph/search search The name or ID to match, 1 to 200 characters. Required.
graph/search kind Only one type: datastore, container, field, check, anomaly, operation, flow, or template.
graph/search offset, size Where the page starts, and its size, up to 20 (5 by default).
graph/locate asset_type container, field, check, or anomaly. Required.
graph/locate asset_id The asset's ID. Required.

Each node says whether it carries the tag (tagged) and, in stats, how many open anomalies that carry the tag it reaches. Within a branch, the nodes with the most open anomalies come first.

Example request
curl -X POST "https://your-instance.qualytics.io/api/global-tags/12/graph/children" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": { "layers": ["checks", "anomalies"] },
    "node_type": "container",
    "node_id": 3051,
    "relation": "checks"
  }'

Move, Remove, and Merge

These actions change many assets at once. Move and remove reach only the assets you can edit. Moving or removing the tag on a datastore, a table or file, a field, or a check template also moves or removes it on the assets it reaches, such as the checks of a field or of a template. External tags cannot be moved, removed, or merged, and cannot be the target.

All three require the Data Catalog module, and each returns { "success": true }.

Preview the Change

Returns what an action would change, without changing anything: the number of assets by type and by datastore, the Flows and other references that would switch, the assets that already carry the target tag, and the assets the action would skip with the reason.

Endpoint: POST /global-tags/{id}/impact

Permission: Member role or above. A merge preview requires the Admin role.

Field Type Description
action string move, remove, or merge.
target_id integer The tag that replaces it. Required for move and merge.
assets list The assets to act on, each as {"asset_type": ..., "asset_id": ...}, up to 1,000. Leave it out for every asset carrying the tag.

POST /global-tags/{id}/impact/assets takes the same body, plus paging and filters, and lists the assets the action would change.

Move a Tag

Takes the tag off the assets and puts target_id on them instead. Both tags stay.

Endpoint: POST /global-tags/{id}/move

Permission: Member role or above, on the assets you can edit.

Example request
curl -X POST "https://your-instance.qualytics.io/api/global-tags/12/move" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "target_id": 18,
    "assets": [
      { "asset_type": "container", "asset_id": 3051 },
      { "asset_type": "check", "asset_id": 88412 }
    ]
  }'

Remove a Tag

Takes the tag off the assets. The tag stays in the library.

Endpoint: POST /global-tags/{id}/remove

Permission: Member role or above, on the assets you can edit.

The body takes assets, as in Preview the Change. Leave it out to remove the tag from every asset you can edit.

Merge a Tag

Moves everything that uses the tag (assets, Flows, schedules, and saved filters) to target_id, then deletes the tag. This cannot be undone.

Endpoint: POST /global-tags/{id}/merge

Permission: Admin role

Example request
curl -X POST "https://your-instance.qualytics.io/api/global-tags/27/merge" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "target_id": 12 }'