---
title: "Track a keyword"
method: POST
path: "/keywords"
tags: ["Social Listening"]
---

# Track a keyword

`POST /keywords`

Starts tracking a keyword for a workspace. Re-adding an already-tracked keyword is idempotent — it returns 200 with the existing row instead of creating a duplicate. The response contains the keyword object only (no sync state); poll `GET /keywords/{keywordId}/sync-status` until the sync completes, same contract as `POST /pages/{id}/sync` → `GET /pages/{id}/sync-status`.

## Request body

- object
  - `workspaceId` string, required
  - `keyword` string, required
  - `type` 'brand' | 'topic'

## Response `200`

Keyword was already tracked (idempotent re-add)

- object
  - `data` object, required
    - `keywordId` string, required
    - `text` string, required
    - `type` 'brand' | 'topic', required
    - `createdAt` string, date-time, required

## Other responses

- `201` — Keyword is now tracked
- `400` — Keyword limit reached, brand limit reached, or type conflict with an existing listener
- `401` — Unauthorized
- `403` — Token lacks the write scope, workspace is outside token scope, or workspace is a sample workspace
- `429` — Rate limit exceeded
- `500` — Internal server error

---

[API](https://skmtc.net/planable/apis/planable-public-api.md) · [All operations](https://skmtc.net/planable/apis/planable-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/planable/planable-public-api/revisions/e91a4f756dfe/schema)
