$ cli-blog docs

Tags

Create localized topic labels for post discovery and editorial grouping.

Tags add flexible topic labels to posts. Use their shared IDs for assignments, and use localized variants for topic-page names, slugs, descriptions, and SEO fields.

Choose a surface

The API, Node SDK, and CLI manage the same tag concepts. Compare all Cli Blog tools.

ActionHTTP APINode SDKCLIDescription
ListGET /v1/tagsblog.tags.list() or .paginate()cli-blog tags listPage through localized tags
CreatePOST /v1/tagsblog.tags.create()cli-blog tags createCreate a tag or localized variant
RetrieveGET /v1/tags/{id}blog.tags.get()cli-blog tags getGet a tag by shared ID or localized slug
UpdatePOST /v1/tags/{id}blog.tags.update()cli-blog tags updateChange localized tag fields
DeleteDELETE /v1/tags/{id}blog.tags.delete()cli-blog tags deleteDelete a localized tag

Public and private keys can list and retrieve tags. Create, update, and delete actions require a private key with tag permission.

Use the REST API

Call the resource from any technology that can send HTTP requests. Use a public key for allowed delivery reads and a private key for content changes.

GET or POST https://api.cli-blog.com/v1/tags
Choose an API key

Use the CLI

Use the CLI for local work, continuous integration, and JSON automation. Configure a narrowly scoped key before running content-changing commands.

cli-blog tags list --locale en-US --json
Read the CLI guide

Use the Node SDK

Use the Node SDK in Node.js 20+ servers, scripts, continuous integration, and trusted agent environments. Its methods map to the same resource actions.

await blog.tags.list({ locale: "en-US" })
Read the Node SDK guide

Use the agent skill

Give the agent the Cli Blog skill and a result-focused instruction. The skill helps it choose the API, CLI, or SDK and keeps publishing behind an approval gate.

Find the Release notes tag in en-US. Create it if missing, then return its stable tag ID.
Install the agent skill

Create a tag

Create a tag before assigning its shared ID through a post's tag_ids field:

curl "https://api.cli-blog.com/v1/tags" \
  --header "x-api-key: $CLI_BLOG_PRIVATE_API_KEY" \
  --header "content-type: application/json" \
  --data '{
    "name": "Release notes",
    "slug": "release-notes",
    "locale": "en-US",
    "description": "Product, platform, and integration updates.",
    "robots_index": true
  }'

The response returns the shared concept ID:

{
  "id": "term_tag_3c09f1",
  "object": "taxonomy_term",
  "organization_id": "org_demo_acme",
  "taxonomy_type": "tag",
  "parent_taxonomy_term_id": null,
  "locale": "en-US",
  "name": "Release notes",
  "slug": "release-notes",
  "description": "Product, platform, and integration updates.",
  "seo_title": null,
  "seo_description": null,
  "canonical_url": null,
  "focus_keyphrase": null,
  "seo_keywords": [],
  "robots_index": true,
  "robots_follow": true,
  "open_graph_title": null,
  "open_graph_description": null,
  "open_graph_media_asset_id": null,
  "twitter_title": null,
  "twitter_description": null,
  "twitter_media_asset_id": null,
  "schema_type": "CollectionPage",
  "metadata": {},
  "created_at": "2026-07-11T17:15:00.000Z",
  "updated_at": "2026-07-11T17:15:00.000Z"
}

The SDK and CLI create the same resource:

import { CliBlog } from "@cli-blog/node";

const blog = new CliBlog({
  apiKey: process.env.CLI_BLOG_PRIVATE_API_KEY!,
  apiUrl: "https://api.cli-blog.com",
});

const tag = await blog.tags.create({
  name: "Release notes",
  locale: "en-US",
  description: "Product, platform, and integration updates.",
});
cli-blog tags create \
  --name "Release notes" \
  --locale en-US \
  --description "Product, platform, and integration updates." \
  --json

List and retrieve tags

Cursor pagination is the preferred list mode. Set limit up to 100, then pass next_cursor as after. Use numbered pagination only when a tag manager requires exact totals. See Pagination.

Omit locale to use the organization's primary locale. Cli Blog does not fall back to another locale in V1. Add include=translations when the current view needs every localized variant.

const firstPage = await blog.tags.list({
  locale: "en-US",
  include: "translations",
  limit: 50,
});

const tag = await blog.tags.get("release-notes", {
  locale: "en-US",
  include: "translations",
});
cli-blog tags list --locale en-US --include translations --limit 50 --json
cli-blog tags get release-notes --locale en-US --json

Add a translation

Pass an existing shared tag ID as translation_of_id. Posts keep the same tag_ids assignment across translations.

await blog.tags.create({
  name: "Notas de lanzamiento",
  slug: "notas-de-lanzamiento",
  locale: "es-MX",
  translation_of_id: "term_tag_3c09f1",
  description: "Actualizaciones del producto, la plataforma y las integraciones.",
});

Update and delete a tag

Pass locale when an ID or slug has localized variants. Tags do not accept parent_taxonomy_term_id; use Categories for hierarchy.

await blog.tags.update(
  "term_tag_3c09f1",
  { description: "Release notes for the product, API, SDK, and CLI." },
  { locale: "en-US" },
);

await blog.tags.delete("term_tag_3c09f1", { locale: "en-US" });
cli-blog tags update term_tag_3c09f1 \
  --locale en-US \
  --description "Release notes for the product, API, SDK, and CLI." \
  --json

cli-blog tags delete term_tag_3c09f1 --locale en-US --yes

Review post assignments before deleting a tag.

Tag fields

Field familyFields and description
Identityid, object, organization_id, and taxonomy_type identify the shared concept
Localizationlocale, name, slug, description, and optional translations describe localized variants
Search and socialSearch, canonical, robots, Open Graph, X/Twitter, keyword, and schema_type fields describe the topic archive
Integration datametadata stores integration-defined JSON up to 32 KB when serialized
Timestampscreated_at and updated_at report ISO timestamps

Common errors

StatusCauseResolution
400Unsupported locale, category-only parent field, or mixed pagination modesCheck the error param and remove unsupported fields
401Missing or invalid API keySend the organization key in x-api-key
403Public key used for a write or private key lacks permissionUse a scoped private key
404Shared ID or slug does not exist in the requested localeConfirm the locale and identifier
409Slug already exists in that localeChoose a unique locale-scoped slug

Complete API operations

The operation reference lists every path, locale control, include, request field, response field, and error schema. Use Try it to open the request runner.

List tags

Key type: Public or private key

List localized tags. Cursor pagination is the default; page and per_page opt into exact numbered pagination and cannot be combined with after or limit. Omitted locale uses the organization primary/default locale; v1 does not fall back across locales.

Authorization

ApiKeyAuth
x-api-key<token>

Organization API key. Each key selects exactly one organization; do not send an organization ID separately. Public keys use the cli_blog_pk_ prefix and are intended for published-content delivery reads. Private keys use the cli_blog_sk_ prefix, belong only in trusted environments, and are required for write, publish, delete, and editorial-state workflows when their scopes allow it.

In: header

Query Parameters

after?string

Opaque cursor returned by the previous tag list page.

limit?|

Maximum tags to return. Defaults to 20. The maximum accepted value is 100.

page?|

One-based exact page number. Supplying page selects numbered pagination and cannot be combined with after or limit.

per_page?|

Items per numbered page. Requires page, defaults to 20, and cannot be combined with after or limit.

locale?string

BCP 47 locale tag to list, for example en-US or es-MX. Categories and tags are shared concepts with localized variants; omitted locale uses organization defaults.

include?array<string>

Optional related data to include. Use translations to see available localized variants.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/tags"
{  "object": "list",  "has_more": true,  "next_cursor": "string",  "page": 0,  "per_page": 0,  "total_items": 0,  "total_pages": 0,  "data": [    {      "id": "string",      "object": "taxonomy_term",      "organization_id": "string",      "taxonomy_type": "string",      "parent_taxonomy_term_id": "string",      "locale": "string",      "name": "string",      "slug": "string",      "description": "string",      "seo_title": "string",      "seo_description": "string",      "canonical_url": "string",      "focus_keyphrase": "string",      "seo_keywords": [        "string"      ],      "robots_index": true,      "robots_follow": true,      "open_graph_title": "string",      "open_graph_description": "string",      "open_graph_media_asset_id": "string",      "twitter_title": "string",      "twitter_description": "string",      "twitter_media_asset_id": "string",      "schema_type": "string",      "metadata": null,      "created_at": "string",      "updated_at": "string",      "translations": [        {          "id": "string",          "locale": "string",          "name": "string",          "slug": "string"        }      ]    }  ]}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}

Create a tag

Key type: Private key

Send a JSON body to create a localized tag. Its stable shared ID can be assigned to posts across locales. Omit locale to use the organization primary/default locale.

Authorization

ApiKeyAuth
x-api-key<token>

Organization API key. Each key selects exactly one organization; do not send an organization ID separately. Public keys use the cli_blog_pk_ prefix and are intended for published-content delivery reads. Private keys use the cli_blog_sk_ prefix, belong only in trusted environments, and are required for write, publish, delete, and editorial-state workflows when their scopes allow it.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/tags" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "id": "string",  "object": "taxonomy_term",  "organization_id": "string",  "taxonomy_type": "string",  "parent_taxonomy_term_id": "string",  "locale": "string",  "name": "string",  "slug": "string",  "description": "string",  "seo_title": "string",  "seo_description": "string",  "canonical_url": "string",  "focus_keyphrase": "string",  "seo_keywords": [    "string"  ],  "robots_index": true,  "robots_follow": true,  "open_graph_title": "string",  "open_graph_description": "string",  "open_graph_media_asset_id": "string",  "twitter_title": "string",  "twitter_description": "string",  "twitter_media_asset_id": "string",  "schema_type": "string",  "metadata": null,  "created_at": "string",  "updated_at": "string",  "translations": [    {      "id": "string",      "locale": "string",      "name": "string",      "slug": "string"    }  ]}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}

Retrieve a tag

Key type: Public or private key

Retrieve a tag by its stable shared ID or locale-scoped slug. Omitted locale uses the organization primary/default locale; v1 does not automatically fall back to another locale.

Authorization

ApiKeyAuth
x-api-key<token>

Organization API key. Each key selects exactly one organization; do not send an organization ID separately. Public keys use the cli_blog_pk_ prefix and are intended for published-content delivery reads. Private keys use the cli_blog_sk_ prefix, belong only in trusted environments, and are required for write, publish, delete, and editorial-state workflows when their scopes allow it.

In: header

Path Parameters

id*string

Shared tag concept ID or locale-scoped slug.

Query Parameters

locale?string

BCP 47 locale tag used for tag slug lookup.

include?array<string>

Optional related data to include. Use translations to see available localized variants.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/tags/string"
{  "id": "string",  "object": "taxonomy_term",  "organization_id": "string",  "taxonomy_type": "string",  "parent_taxonomy_term_id": "string",  "locale": "string",  "name": "string",  "slug": "string",  "description": "string",  "seo_title": "string",  "seo_description": "string",  "canonical_url": "string",  "focus_keyphrase": "string",  "seo_keywords": [    "string"  ],  "robots_index": true,  "robots_follow": true,  "open_graph_title": "string",  "open_graph_description": "string",  "open_graph_media_asset_id": "string",  "twitter_title": "string",  "twitter_description": "string",  "twitter_media_asset_id": "string",  "schema_type": "string",  "metadata": null,  "created_at": "string",  "updated_at": "string",  "translations": [    {      "id": "string",      "locale": "string",      "name": "string",      "slug": "string"    }  ]}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}

Update a tag

Key type: Private key

Send a JSON body to update a localized tag.

Authorization

ApiKeyAuth
x-api-key<token>

Organization API key. Each key selects exactly one organization; do not send an organization ID separately. Public keys use the cli_blog_pk_ prefix and are intended for published-content delivery reads. Private keys use the cli_blog_sk_ prefix, belong only in trusted environments, and are required for write, publish, delete, and editorial-state workflows when their scopes allow it.

In: header

Path Parameters

id*string

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/tags/string" \  -H "Content-Type: application/json" \  -d '{}'
{  "id": "string",  "object": "taxonomy_term",  "organization_id": "string",  "taxonomy_type": "string",  "parent_taxonomy_term_id": "string",  "locale": "string",  "name": "string",  "slug": "string",  "description": "string",  "seo_title": "string",  "seo_description": "string",  "canonical_url": "string",  "focus_keyphrase": "string",  "seo_keywords": [    "string"  ],  "robots_index": true,  "robots_follow": true,  "open_graph_title": "string",  "open_graph_description": "string",  "open_graph_media_asset_id": "string",  "twitter_title": "string",  "twitter_description": "string",  "twitter_media_asset_id": "string",  "schema_type": "string",  "metadata": null,  "created_at": "string",  "updated_at": "string",  "translations": [    {      "id": "string",      "locale": "string",      "name": "string",      "slug": "string"    }  ]}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}

Delete a tag

Key type: Private key

Delete a localized tag.

Authorization

ApiKeyAuth
x-api-key<token>

Organization API key. Each key selects exactly one organization; do not send an organization ID separately. Public keys use the cli_blog_pk_ prefix and are intended for published-content delivery reads. Private keys use the cli_blog_sk_ prefix, belong only in trusted environments, and are required for write, publish, delete, and editorial-state workflows when their scopes allow it.

In: header

Path Parameters

id*string

Query Parameters

locale?string

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X DELETE "https://example.com/v1/tags/string"
{  "deleted": true,  "id": "string"}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}
{  "error": {    "code": "invalid_request",    "message": "string",    "param": "string"  }}

On this page