Skip to main content
Most monitoring starts from a name you already own. That works once people are saying it. Before then — a product nobody has heard of, a name you picked last week — the feed is empty and the tool looks broken. This guide builds the other kind of keyword: one that starts from what people say when they have the problem you solve, and reads back only the mentions worth answering. Nothing here is a separate product. It is POST /v1/keywords with different terms, and GET /v1/mentions with two filters.

1. Search for the sentence, not the name

A brand keyword looks for one token. A discovery keyword looks for the phrases people type when they are stuck:
terms are OR’d into one upstream call, so several phrasings of the same complaint cost one poll, not three. A topic keyword sent without a match is created with match: "word": an item is kept only when it carries one of the phrases as written. That is what keeps a phrase keyword readable, because most platforms answer a phrase with whatever they think is near it. When people type your phrases too many different ways and the keyword stays quiet, send "match": "contains" to widen it. "match": "platform", stated explicitly, keeps the platform’s own matching.
Write the phrases in the words your customers use, not the words you use. “Brand monitoring” is your category; “I keep missing when people mention us” is their problem.

2. Poll the places people describe problems in prose

Five sources carry that kind of sentence. Enable them together:
Each enabled Source is one slot and one charge per poll. See Credits.

3. Switch the readings on

A phrase keyword catches everyone who used the phrase, and most of them are not prospects: someone answering, someone quoting, someone complaining about a different tool. Two readings sort them, and they are what step 4 filters on.
sentimentEnabled reads every mention as positive, neutral, negative, question or mixed. aiEnabled also writes the intent — what the item is trying to do: purchase_intent, comparison, question, complaint, praise or other. Both cost credits per classified item. Without them, step 4 has nothing to filter on. A third reading tells a prospect from a bystander: an agent step asked of every mention. Give it a boolean problem_fit field and it becomes what the opportunity filter of step 4 reads:
It is not added for you on the API: a step costs credits per item, and a call is never billed for a step it did not ask for. A keyword added as a Topic in the dashboard carries this one from the start. subjectRole costs nothing. It says what this keyword is about (here a problem rather than a product), it sets the default match of step 1, and it is what a reply draft reads to decide whose voice it writes in. Leave it out and the keyword is own, which is right for a brand keyword and wrong for this one: a draft would answer as if the pain phrase were your company’s name.

4. Read back only what needs you

GET /v1/mentions filters on both readings. Each is repeatable, and repeated values are OR’d:
That reads: someone with a problem or a question, who is unhappy about it. Or ask for the opportunities directly:
An opportunity is a mention of a topic or competitor keyword that is highly relevant to it (relevance: high) and whose author is someone to answer. On a keyword whose step has a boolean problem_fit, that is problem_fit: true under the step it carries now; on any other, an intent of purchase_intent, comparison or question. An own keyword has none. The same parameter works on GET /v1/keywords/{id}/results, and the dashboard’s Feed offers it as Opportunities, at the head of the Intent filter. Repeated values of one key are OR’d; different keys are AND’d. So ?source=reddit&source=hackernews&sentiment=negative&intent=complaint reads: on Reddit or Hacker News, negative, and a complaint. source, sentiment and intent are all repeatable. unread is the wire spelling of “not yet classified” — a real filter value, not an absence. It is how you find what your readings have not caught up with.
Filtering on sentiment, intent, engagement_min or engagement reads the polled stream only. Items kept from a one-off Explore run carry no readings and no counters, so they cannot satisfy those filters and are left out rather than shown misleadingly.

Cutting the mentions nobody reacted to

engagement_min keeps mentions with at least that many interactions — likes, replies, reposts, comments or score, whichever the Source reports. It is the noise gate for a busy Source: on a typical month of X mentions, roughly seven in ten have no interactions at all, so ?engagement_min=1 alone removes most of what you would otherwise page through. Three things it does not do, each of which will otherwise surprise you:
  • It never counts views. A view is not an interaction, and on the Sources that report one it is an order of magnitude bigger than every other counter — including it would make this a filter on reach.
  • It leaves out mentions with no counters at all, rather than treating them as zero. RSS items and AI answers report no audience, and mentions recorded before 4 September 2026 predate the field. None of them were measured, so none can satisfy a threshold. ?engagement_min=0 is therefore narrower than no filter: it asks for everything that was counted.
  • The numbers are captured when we collect a mention, and never refreshed. A post caught two minutes after it went up is measured with the counters it had then. So a threshold reads against your most recent mentions, which are the ones with the least time to have earned anything.
A number that means one thing on one Source means another elsewhere: five points on Hacker News is a story that landed, five likes on X is nothing. That is what engagement below is for.

Asking a different question of each Source

engagement_min thresholds one number for everything, and the sum it thresholds is lossy: a post with a hundred replies and no likes clears engagement_min=100 exactly as a post with a hundred likes does, and those are not the same mentions. It was liked and it was argued with is the distinction a sum erases. engagement is a rule, and it is repeatable:
  • Metrics are likes, replies, reposts, comments, score and views, plus total for the same interaction sum engagement_min reads. engagement_min=10 is exactly engagement=*:total>=10.
  • Operators are >=, >, =, < and <=. The number is whole and may be negative — Reddit and Lemmy net downvotes out, so ?engagement=reddit:score<0 is a real question: the mentions that were argued with.
  • * stands for any Source no named rule already covers. Pair it with total — ?engagement=*:total>=25 is “at least 25 interactions, wherever it was said”, which is engagement_min with an operator of your choosing. A named counter under * is legal but rarely what you mean: *:likes>=100 drops every Source that does not count likes, by the rule below.
Two rules about the scope, and both are the kind you discover by noticing rows missing:
  • A Source no rule names passes. ?engagement=x:likes>=100 narrows X and leaves Hacker News exactly as it was. Without that, every rule would also be a Source filter in disguise — and ?source= already exists for that. A named rule overrides * for its own Source, and several rules on one Source are ANDed.
  • A metric that was never counted satisfies nothing — < included. This is the engagement_min rule above, one level down and sharper: YouTube reports no likes at all, so ?engagement=youtube:likes<10 returns none of your YouTube mentions rather than all of them. Only a metric the Source actually reports can be filtered on.
Send engagement or engagement_min, never both: they are two spellings of one filter, and a request carrying both is a 400. Every mention comes back with both readings on it, so you can sort further without a second call:

5. Qualify each one with your own question

The readings say what an item is. To ask whether it is your problem, give the keyword an agent step (one instruction and a schema, applied to every item it catches):
The answers ride on each mention under agent, spelled with your own field names:
current_workaround is the one with commercial value beyond triage: what someone names as their current answer is what your reply has to be better than. See AI for the schema’s field types and what an agent pass costs.

6. Get told instead of polling

Do not poll /v1/mentions on a timer. A keyword delivers what it catches to a webhook, and every mention arrives with its readings already on it, so the filter that reads well in step 4 becomes a condition in your own handler.

What this does not do

It finds people describing a problem. It does not find customers, and it does not tell you they want to buy — a problem_fit of true is a reading of one post, not a qualified lead. Treat the output as a list of conversations worth joining, and expect to discard some of it.