---
title: "Keyword groups"
description: "Group keywords by customer, campaign or product, track the same term in more than one group, and read what each group cost."
canonical: https://docs.mentio.dev/guides/groups
markdown: https://docs.mentio.dev/guides/groups.mdx
---

# Keyword groups

Group keywords by customer, campaign or product, track the same term in more than one group, and read what each group cost.

A group is how a workspace sorts its keywords: one per customer, campaign or product. Use groups when one workspace serves several of your own customers.

## How groups work [#how-groups-work]

Every keyword belongs to exactly one group. A term is unique per group, not per workspace, so two groups may track "bloom" as two keywords, each matched, capped and billed on its own.

Every workspace has a **default group**, created with it. A keyword created without a `groupId` lands there. The default group can be renamed but never deleted.

Groups are for running one workspace on behalf of several customers who want the same term with different rules, caps and bills.

A workspace tracking its own brand needs none of this: the dashboard shows groups only once a second one exists.

## Create a group and put keywords in it [#create-a-group-and-put-keywords-in-it]

* `name` is unique per workspace.
* `externalId` is optional and unique too: your own id for the group, a customer id say. Find the group again with `GET /v1/groups?externalId=` instead of storing ours.

```bash
curl -X POST https://api.mentio.dev/v1/groups \
  -H "Authorization: Bearer $MENTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Bloom Coffee", "externalId": "cust_8231" }'
```

```json
{
  "id": "grp_7f3a...",
  "name": "Bloom Coffee",
  "externalId": "cust_8231",
  "isDefault": false,
  "stats": { "keywords": 0, "active": 0 },
  "createdAt": "2026-09-24T10:00:00.000Z",
  "updatedAt": "2026-09-24T10:00:00.000Z"
}
```

Then create the keyword with its `groupId`:

```bash
curl -X POST https://api.mentio.dev/v1/keywords \
  -H "Authorization: Bearer $MENTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "term": "bloom", "kind": "brand", "groupId": "grp_7f3a...", "cap": { "mentions": 500 } }'
```

* A second `bloom` in the same group is a `409 duplicate_keyword`; a `bloom` in another group is a new keyword.
* `PATCH /v1/keywords/{id}` with `groupId` moves a keyword between groups, with the same 409 when the target already tracks the term.

## A company description per group [#a-company-description-per-group]

The classifier judges every mention against "the company": by default the workspace's company profile. When you run one workspace for several businesses, that profile is yours, not theirs.

A group can carry its own description in `context`: who the business is, what it sells, for whom, what is not it. A keyword's `context` (a 300-character instruction) cannot stand in for it.

```bash
curl -X PATCH https://api.mentio.dev/v1/groups/grp_7f3a... \
  -H "Authorization: Bearer $MENTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "context": "Bloom Coffee roasts specialty coffee in Copenhagen and sells beans and subscriptions online. Not the Bloom fintech app, not the flower shop." }'
```

New mentions are judged with the new description at once; old ones are not rescored.

How the description applies:

* It replaces the whole workspace profile for every keyword in the group: description, relevance guidelines, competitor list and own accounts. A rule that should hold for the group ("ignore job posts") goes in the group's text.
* Null means the workspace profile.
* The default group takes no description: it is the workspace itself, and its company is the profile.

A second keyword on the same post reuses a sibling's verdict only when that sibling was judged as the same company. Mentio records which on the match: the workspace profile, or the group's description.

So moving a keyword, changing or clearing a description, or renaming a group all do the right thing without rescoring. Editing the workspace profile changes nothing about reuse.

## Where the group shows [#where-the-group-shows]

* Every keyword carries `group` (`id`, `name`, `externalId`, `isDefault`). `GET /v1/keywords?groupId=` lists one or more groups' keywords (comma-separated).
* Every mention carries `keyword.group`, so a webhook payload says which customer's keyword matched.
* `GET /v1/mentions?groupIds=` (comma-separated, any-of) narrows the list to groups, and `notGroupIds` leaves groups out.
* The CSV export carries `group` and `group_external_id` columns.
* An alert rule's filter takes `groupIds`: one rule per customer, delivering to that customer's channel, whatever its keywords are on the day.
* The analytics reports name the group on every keyword row.
* In digests and alert emails a keyword outside the default group reads as `bloom (Bloom Coffee)`.

## People and segments by group [#people-and-segments-by-group]

People (`/v1/people`) and segments (`/v1/segments`) cover the whole workspace by default. When each group is a different customer, that lets one customer read and change another's notes.

Every People and Segments endpoint takes one optional query parameter, `groupId`, on reads and writes alike. Without it, every call behaves as before.

```bash
curl "https://api.mentio.dev/v1/people?groupId=grp_7f3a...&sort=reach" \
  -H "Authorization: Bearer $MENTIO_API_KEY"

curl -X PATCH "https://api.mentio.dev/v1/people/aut_91c2...?groupId=grp_7f3a..." \
  -H "Authorization: Bearer $MENTIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tags": ["lead"], "stage": "contacted" }'
```

### Who is listed [#who-is-listed]

* Only the people who mentioned that group's keywords.
* `stats` (mentions, relevant, sentiment, first and last seen) count the group's mentions alone.
* A person the group never matched is a 404 there, whatever the rest of the workspace knows about them.

### What a group keeps to itself [#what-a-group-keeps-to-itself]

What a group reads and writes about a person is its own: tags, notes, mute, the outreach owner and stage, merges (`/merge`, `/split`), activities and segments.

* Nothing the workspace wrote shows in a group.
* Nothing a group wrote shows in another group, or in a call without `groupId`.
* The same segment name can exist in each group.
* `GET /v1/people/export.csv?groupId=` is the group's list with the group's annotations.
* Deleting a group deletes what it wrote about people.

### Segments belong to their scope [#segments-belong-to-their-scope]

* A segment carries `groupId` (null for a workspace segment).
* Its `count` is computed over the group's people.
* `segmentId` on the people list must name a segment of the same scope; a segment of another scope is a 404.

### Mutes by group [#mutes-by-group]

`"muted": true` in a `PATCH` sent with `groupId` hides the person, and the accounts that group merged into them, from that group's keywords: its feed, its alerts and its digests.

* Their mentions of another group's keywords are untouched. The person reads `muted: false` there and in the workspace.
* A mute set without `groupId` still hides them everywhere.
* The `muted` filter of the people list reads the scope's own value.
* On `/v1/mentions`, `includeMuted=true` shows what either mute hides.

### Mentions show each group's work [#mentions-show-each-groups-work]

`/v1/mentions`, alerts and digests have no `groupId` scope. A caller reading the whole workspace, or a rule without `groupIds`, sees each mention with its own group's tags. It does not see the mentions that mention's group muted.

Narrow with `groupIds` to read one customer's mentions.

* `author.tags` on a mention is the workspace's tags, then the tags the mention's own group (its keyword's) gave that person, each once.
* The `tags` and `notTags` filters of `/v1/mentions` and of alert rules read the same list, so a rule with `groupIds` and `tags: ["lead"]` fires on that customer's leads.
* One group's tags never show on, or filter, another group's mentions.
* `personId` on `/v1/mentions` still follows the workspace's merges.

### Moving a keyword moves its people [#moving-a-keyword-moves-its-people]

A keyword moved to another group takes the people who mentioned it, and their history, to that group.

What the old group wrote about them stays stored there, and shows again if they mention one of its keywords.

### Errors and safety [#errors-and-safety]

* An unknown `groupId` is a 404 (`Group not found`).
* A misspelled one (`group_id`, `groupIds`) or one sent in the JSON body is a 400, never the whole workspace. The scope is the `groupId` query parameter and nothing else.
* The MCP tools for people and segments take the same `groupId`.

`groupId` is a filter your backend passes, not an access control. An API key acts on the whole workspace, so a key that can read one group can read them all.

Keep the key on your server and choose the `groupId` there, from your own session, never from a value the customer's browser sends.

## What a group cost [#what-a-group-cost]

`GET /v1/usage/breakdown?by=group` is the bill per group, at list price: the keyword-days charged for its keywords, the mentions they matched and billed, and the sum.

* Keyword-days count under the group the keyword was in on the day they were charged, so moving or deleting a keyword never moves money already spent.
* A group deleted during the window keeps its row, marked `group.removed`.

```bash
curl "https://api.mentio.dev/v1/usage/breakdown?by=group&month=2026-09" \
  -H "Authorization: Bearer $MENTIO_API_KEY"
```

## Delete a group [#delete-a-group]

`DELETE /v1/groups/{id}` deletes the group and every keyword in it, each the way `DELETE /v1/keywords/{id}` does:

* Its keywords' mentions go with them.
* Alert rules that named them are adjusted.
* What the group wrote about people (tags, notes, merges, activities, segments) is deleted.
* Charges already made stay on the usage record.

It answers 204 like every delete. Read the group first if you want to know how many keywords go (`stats.keywords`).

The default group cannot be deleted: move or delete its keywords instead.

## Related [#related]

* [Create a group](/api/groups/create-group): the endpoint reference.
* [People](/guides/people): tags, notes, merges and outreach.
* [Billing](/billing): the usage breakdown and mention caps.
* [Choosing keywords](/guides/keywords): what a keyword matches.
