# Get tags

> GET /v3/kb/tags · Knowledge base API

Source: https://developer.kustomer.com/api/knowledge-base/get-tags

```http
GET https://{orgname}.api.kustomerapp.com/v3/kb/tags
Authorization: Bearer <API key>
```

## Authorization

Requires any one of these roles: `org.permission.kb.read`; or legacy `org.user.content.kb.read`, `org.user.kb.read`, `org.admin.content.kb.read`, `org.admin.kb.read`. The API key or user must hold at least one of them. Legacy roles predate permission sets and still work.

Returns all Knowledge Base article tags.

## About Knowledge base tags

Knowledge base tags are labels you attach to articles, such as "billing" or "mobile app", to group related articles across categories. They are separate from the tags used on conversations.

Categories give each article a place in the help center's tree. Tags cut across that tree: one tag can link articles from many categories, and the help center can list every article with a tag on a tag page. A tag is only a name, and articles refer to it by ID.

#### Names

`name` is 1 to 64 characters and must be unique in the org, ignoring case. Kustomer rejects "Billing" if "billing" already exists. Because articles store tag IDs, renaming a tag with `PATCH` updates it on every article at once. This reference has no endpoint for deleting a tag. To find tags, filter the list with `name`, which matches the start of the name and ignores case, so `name=ret` finds "Returns" and "Retail".

#### Tagging articles

Send tag IDs, not names, in `tags`. Each article version has its own `tags`, so tags you set on a draft go live when you publish it. Set them with `PUT /v1/kb/articles/{id}/versions/{lang}/draft`, or send them when you create the article or a version. The article also has a `tags` list, which `PUT /v1/kb/articles/{id}` sets. If any ID doesn't match an existing tag, Kustomer rejects the draft update. Create tags first, then attach them.

#### Which endpoint to use

| To | Call |
| --- | --- |
| List tags, or find them by name prefix | [`GET /v3/kb/tags`](https://developer.kustomer.com/api/knowledge-base/get-tags) |
| Read one tag | [`GET /v3/kb/tags/{id}`](https://developer.kustomer.com/api/knowledge-base/get-tags-by-id) |
| Create a tag | [`POST /v3/kb/tags`](https://developer.kustomer.com/api/knowledge-base/create-tag) |
| Rename a tag | [`PATCH /v3/kb/tags/{id}`](https://developer.kustomer.com/api/knowledge-base/update-tag-by-id) |

To tag articles, use the [article version endpoints](https://developer.kustomer.com/api/knowledge-base#articles-versioning-and-languages). Reads need a knowledge base read role, and writes need `org.admin.kb.write` or the matching permission.

Related: [Knowledge base articles](https://developer.kustomer.com/api/knowledge-base#articles), [Knowledge base categories](https://developer.kustomer.com/api/knowledge-base#categories), [Conversation tags](https://developer.kustomer.com/api/core-resources#conversations-tags)

### Recipes

#### 1. Tag an article by name

Turn the tag names from your own system into knowledge base tag IDs, creating any that don't exist, and put them on an article's next published version.

**Step 1.** [`GET /v3/kb/tags`](https://developer.kustomer.com/api/knowledge-base/get-tags.md). Look the name up with `name`, which matches the start of the name and ignores case, so `name=billing` also returns "Billing issues". Keep the result whose name matches exactly, ignoring case.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/tags?name=billing" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v3/kb/tags --query name=billing --all \
  | jq -r 'select(.data.attributes.name | ascii_downcase == "billing") | .data.id'
```

**Step 2.** [`POST /v3/kb/tags`](https://developer.kustomer.com/api/knowledge-base/create-tag.md). If nothing matched, create the tag. Names must be unique ignoring case, so if another process created it a moment ago, the request is rejected; look it up again instead of retrying.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v3/kb/tags" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"name": "billing"}'
```

```bash title="kusty"
kusty api POST /v3/kb/tags --field name=billing --fields id
```

**Step 3.** [`PUT /v1/kb/articles/{id}/versions/{lang}/draft`](https://developer.kustomer.com/api/knowledge-base/update-a-draft-version.md). Send the tag IDs as the draft's `tags`, at most 20. The list replaces the draft's tags, so include the ones it already has. If any ID doesn't match a tag, the update is rejected. Tags on a draft go live when you publish it, with `publishedAt` in this request or later.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/kb/articles/$ARTICLE_ID/versions/en_us/draft" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"tags\": [\"$BILLING_TAG_ID\", \"$REFUNDS_TAG_ID\"]}"
```

```bash title="kusty"
kusty api PUT /v1/kb/articles/$ARTICLE_ID/versions/en_us/draft \
  --field tags:="[\"$BILLING_TAG_ID\", \"$REFUNDS_TAG_ID\"]"
```

> The article needs a draft in that language. If it only has a live version, start a draft with [`POST …/versions/{lang}`](https://developer.kustomer.com/api/knowledge-base/create-a-version), sending `tags` there.

#### 2. Count how many articles use each tag

Report tag usage across the knowledge base, for example to find unused or near-duplicate tags before you tidy them up.

**Step 1.** [`GET /v3/kb/tags`](https://developer.kustomer.com/api/knowledge-base/get-tags.md). Page through every tag and save the ID and name.

```bash title="cURL"
curl "https://api.kustomerapp.com/v3/kb/tags?page=1&pageSize=100" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v3/kb/tags --all --output jsonl > tags.jsonl
```

**Step 2.** [`GET /p/v3/kb/articles`](https://developer.kustomer.com/api/knowledge-base/get-articles-public.md). Tags live on article versions, so read the live versions. The public list returns one published, public version per article in the `lang` you ask for, each with its `tags` as tag IDs. Call your org host; no API key is needed.

```bash title="cURL"
curl "https://$ORG.api.kustomerapp.com/p/v3/kb/articles?lang=en_us&page=1&pageSize=100"
```

```bash title="kusty"
kusty api GET /p/v3/kb/articles --base-url "https://$ORG.api.kustomerapp.com" \
  --query lang=en_us --all --output jsonl > articles.jsonl
```

**Step 3.** Count live articles per tag ID and join the names. Tags with a count of `0` aren't on any live public article in that language.

```bash title="kusty"
jq -rn --slurpfile t tags.jsonl --slurpfile a articles.jsonl '
  ([$a[].data.attributes.tags[]?] | group_by(.) | map({(.[0]): length}) | add // {}) as $n
  | $t[] | .data | [.attributes.name, ($n[.id] // 0)] | @tsv' | sort -t$'\t' -k2 -n
```

> Internal articles and drafts don't appear on the public endpoint, so a tag with a count of `0` may still be on one of them. This reference has no endpoint for deleting a tag. To merge near-duplicates, move articles to the tag you keep by updating their drafts and publishing; a [rename](https://developer.kustomer.com/api/knowledge-base/update-tag-by-id) that would collide with another tag's name, ignoring case, is rejected.

### Example object

A real record from [`GET /v3/kb/tags/{id}`](https://developer.kustomer.com/api/knowledge-base/get-tags-by-id.md):

```json
{
  "type": "kb-tag",
  "id": "5e823ecbdcb5bf00581ea15a",
  "attributes": {
    "name": "99",
    "createdAt": "2020-03-30T18:47:39.996Z",
    "updatedAt": "2020-03-30T18:47:39.996Z",
    "modifiedAt": "2020-03-30T18:47:39.996Z"
  },
  "relationships": {
    "org": {
      "links": {
        "self": "/v1/orgs/5e15fa33623f88001a8e0bb5"
      },
      "data": {
        "type": "org",
        "id": "5e15fa33623f88001a8e0bb5"
      }
    },
    "createdBy": {
      "links": {
        "self": "/v1/users/5e15fa45623f88001a8e0bbb"
      },
      "data": {
        "type": "user",
        "id": "5e15fa45623f88001a8e0bbb"
      }
    },
    "modifiedBy": {
      "links": {
        "self": "/v1/users/5e15fa45623f88001a8e0bbb"
      },
      "data": {
        "type": "user",
        "id": "5e15fa45623f88001a8e0bbb"
      }
    }
  },
  "links": {
    "self": "/v1/kb/tags/5e823ecbdcb5bf00581ea15a"
  }
}
```

Fields:

- `attributes.name` (string): The tag's label, 1 to 64 characters: letters (accented ones too), digits, spaces and `_ / < > - .`, not starting with a space. It must be unique in the org, ignoring case. Articles store the tag's ID, so renaming it with `PATCH` renames it on every article.

### Relationships

- Referenced by **Knowledge base articles** via `relationships.tags` (list): The knowledge base tags on an article, stored as tag IDs in the article's `tags` and in each version's `tags`. Renaming a tag changes it on every article that has it.

### Permissions

Fewest roles for a read-only integration: `org.permission.kb.read`. For every endpoint: `org.permission.kb.read`, `org.permission.kb.create`, `org.permission.kb.update`.

## Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | integer | no | Page number of results to return. |
| `pageSize` | integer | no | Number of results to return per page. |
| `name` | string | no | Prefix filter for tag names. |

## Responses

### 200

OK

- `meta` (object, required)
  - `pageSize` (integer, required)
  - `page` (integer, required)
- `links` (object, required)
  - `self` (string, required)
  - `first` (string, required)
  - `prev` (string, required, nullable)
  - `next` (string, required, nullable)
- `data` (array<object>, required)
  - `type` (string, required)
  - `id` (string, required)
  - `attributes` (object, required)
    - `name` (string, required)
    - `createdAt` (string, required)
    - `updatedAt` (string, required)
    - `modifiedAt` (string, required)
  - `relationships` (object, required)
    - `org` (object, required)
    - `createdBy` (object, required)
    - `modifiedBy` (object, required)
  - `links` (object, required)
    - `self` (string, required)

```json
{
  "meta": {
    "pageSize": 100,
    "page": 1
  },
  "links": {
    "self": "/v3/kb/tags?page=1&pageSize=100",
    "first": "/v3/kb/tags?page=1&pageSize=100",
    "prev": null,
    "next": null
  },
  "data": [
    {
      "type": "kb-tag",
      "id": "5e823ecbdcb5bf00581ea15a",
      "attributes": {
        "name": "99",
        "createdAt": "2020-03-30T18:47:39.996Z",
        "updatedAt": "2020-03-30T18:47:39.996Z",
        "modifiedAt": "2020-03-30T18:47:39.996Z"
      },
      "relationships": {
        "org": {
          "links": {
            "self": "/v1/orgs/5e15fa33623f88001a8e0bb5"
          },
          "data": {
            "type": "org",
            "id": "5e15fa33623f88001a8e0bb5"
          }
        },
        "createdBy": {
          "links": {
            "self": "/v1/users/5e15fa45623f88001a8e0bbb"
          },
          "data": {
            "type": "user",
            "id": "5e15fa45623f88001a8e0bbb"
          }
        },
        "modifiedBy": {
          "links": {
            "self": "/v1/users/5e15fa45623f88001a8e0bbb"
          },
          "data": {
            "type": "user",
            "id": "5e15fa45623f88001a8e0bbb"
          }
        }
      },
      "links": {
        "self": "/v1/kb/tags/5e823ecbdcb5bf00581ea15a"
      }
    }
  ]
}
```

### 400

Bad Request

### 401

Unauthorized

### 403

Forbidden

## Example request

```bash
curl --request GET \
  --url 'https://api.kustomerapp.com/v3/kb/tags' \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```
