# Create a tag

Source: https://kirora.io/docs/api/reference/createTag

`POST /v1/tags`

Requires an API key with the `tags:write` scope. [About keys and scopes](https://kirora.io/docs/api/reference/authentication)

Works with integration, agent and partner keys.

A repeat after success is refused with 409 `ALREADY_EXISTS`: read the one the first created. [About idempotency](https://kirora.io/docs/api/reference/idempotency)

Creates a tag ahead of use. Naming a tag in `tags` on a campaign, journey, segment or template also creates it, so this is only needed to prepare a set of tags. Names are unique within the workspace ignoring case: "black friday" is taken by "Black Friday" (409 `ALREADY_EXISTS`). Agent keys may manage tags: a label sends nothing.

## Header parameters

- `Kirora-Workspace` (string, optional, pattern `^[A-Za-z0-9._:-]{1,128}$`) — Partner keys only: the child workspace to act in, by the external id the partner gave it. Without it, a partner key acts in its own workspace. Any other key that sends it is refused with 403, and an unknown workspace is 404.
- `Idempotency-Key` (string, optional, 8–255 characters) — Makes a retry safe: a repeat with the same key and body within 24 hours gets the first response again, with `Idempotency-Replay: true`. The same key with another request is 409 `IDEMPOTENCY_KEY_REUSED`; while the first is still running, 409 `IDEMPOTENCY_KEY_IN_USE`; after an `unsafe` first request failed or never returned, 409 `IDEMPOTENCY_KEY_OUTCOME_UNKNOWN`. Use a new key, such as a UUID, for each new request.

## Request body

- `name` (string, required, 1–64 characters) — Unique within the workspace, ignoring case.

## Returns

Returns `201 Created` with a `Tag` in `data`. It can also return `409 Conflict`, `413 Payload Too Large` or `415 Unsupported Media Type`; see the statuses below. Otherwise returns an error; [Errors](https://kirora.io/docs/api/reference/errors) lists every code and which to retry.

- `id` (string, required, uuid)
- `name` (string, required)
- `usage` (object, required) — How many items of each kind carry the tag.
  - `campaigns` (integer, required, min 0)
  - `journeys` (integer, required, min 0)
  - `segments` (integer, required, min 0)
  - `templates` (integer, required, min 0)
- `createdAt` (string, required, date-time)
- `updatedAt` (string, required, date-time)

Statuses:

- `201 Created`: The new tag.
- `409 Conflict`: The request conflicts with current state — a duplicate unique value, or a resource whose status does not allow this operation.
- `413 Payload Too Large`: The body is larger than this operation accepts (`PAYLOAD_TOO_LARGE`).
- `415 Unsupported Media Type`: The body is not JSON, or not the upload the operation takes (`UNSUPPORTED_MEDIA_TYPE`).

Headers on `201 Created`:

- `Idempotency-Replay` (string, optional, one of `true`) — `true` when this is the stored response to an earlier request with the same key.

## Example: Prepare a tag before tagging anything

```bash
curl -X POST https://api.kirora.io/v1/tags \
  -H "Authorization: Bearer $KIRORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Black Friday"
  }'
```

Response `201`:

```json
{
  "data": {
    "id": "0192f3e0-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
    "name": "Black Friday",
    "usage": {
      "campaigns": 0,
      "journeys": 0,
      "segments": 0,
      "templates": 0
    },
    "createdAt": "2026-10-01T09:30:00.000Z",
    "updatedAt": "2026-10-01T09:30:00.000Z"
  }
}
```
