Skip to main content
Intent labels are the classification taxonomy of a keyword or Reddit watchlist. Keywords decide which posts are collected; intent labels decide what each collected post means (for example “buying intent” vs “competitor mention” vs “hiring”). This page is the canonical reference for how labels work across the API. Intent labels exist only on keyword (LinkedIn) and Reddit watchlists. People and company watchlists do not have them.

The label object

Labels are stored as an array on the watchlist. Each label has three fields:
Naming across the API. On input (POST/PUT labels), use name for the label identifier; key is accepted as an alias so a label object returned by GET can be sent back unchanged. On output (GET watchlist), labels always use key. On posts (GET /api-posts), the assigned label appears as tags (the key) plus tagDescriptions (key and description pairs). “Label” on the watchlist and “tag” on a post are the same concept.

Lifecycle: how a post gets its label

  1. Watchlist creation. Labels come from one of two places:
    • You provide them in the labels array of the create call.
    • OutX generates them. In prompt mode, or when you create with bare keywords and no usable labels, OutX generates a label taxonomy (plus an objective) in the background. The create response returns immediately; labels appear on the watchlist a few seconds later (fetch them with GET).
  2. Collection. On each fetch cycle (fetchFreqInHours), new posts matching the keywords are collected. A freshly collected post has no label yet (tags is empty).
  3. Enrichment (background). Each new post is processed once:
    • It is scored for relevance against the watchlist’s objective embedding, producing relevance_score (1 to 10).
    • For relevant posts, an AI call picks the single label whose description best fits the post. That label’s key is written to the post’s tags.
    • A post with no confident match (or too low relevance) gets the literal tag "na".
  4. Reading. GET /api-posts returns each post’s tags and tagDescriptions. Filter the feed by label with the labels query parameter.
Classification is forward-only. A post is classified exactly once, when first enriched. Changing labels via PUT affects how future posts are classified; already-enriched posts keep their old tags. Re-classifying historical posts requires an explicit re-enrichment by OutX (contact support), a label update alone does not trigger it.
Empty tags means “not classified yet”, not “no match.” Enrichment is asynchronous. An agent polling /api-posts right after creating a watchlist should expect posts with empty tags for a while. "na" (not empty) is the “no match” signal.

Default labels: the pre-applied feed filter

default: true marks a label as one of the watchlist’s default feed filters. In the OutX app, the feed opens with the default labels pre-applied, so users see the highest-intent bucket first instead of the whole firehose. The rules:
  • At most 2 labels can have default: true. If you send more, the extras are silently capped to false (first two win, in array order).
  • Never zero. If you send a labels array where at least one label carries an explicit default boolean but none is true, the first label is automatically promoted to default: true.
  • If you omit default from every label in the array, no default flags are written (legacy behavior) and the app falls back to showing all posts.
The API feed does not auto-apply defaults. GET /api-posts returns all posts unless you pass the labels parameter. default controls the product UI’s initial filter and tells you which buckets the watchlist owner considers primary. To reproduce the default feed via API, read the default labels and pass them explicitly (recipe below).

Reading which labels are default

GET /api-<type>-watchlist?id=... returns the labels with their flags:
Labels on watchlists created before the default flag existed may omit the field entirely; treat a missing default as false.

Recipe: read the feed filtered to default labels only

To fetch unclassified-bucket posts, filter with labels=no labels (the API maps it to the stored "na" tag).

Changing which labels are default

Send the full labels array on PUT with the default booleans you want. PUT replaces the whole label set, so always start from the current GET output and modify it; sending a partial array drops the labels you omit.
The same labels array (including default) is accepted on create (POST) for both /api-keyword-watchlist and /api-reddit-watchlist.
Keeping the same key and description strings when toggling default means already-classified posts keep matching their tags. Renaming a key orphans the old tag on historical posts (they keep the old string in tags).

Timing summary

Two delays stack before labeled posts appear:
  1. Collection cadence: new posts arrive on the fetchFreqInHours cycle (LinkedIn keyword watchlists also backfill recent matching posts automatically at creation).
  2. Enrichment queue: each collected post is scored and classified in the background.
Poll GET /api-posts and treat empty tags as pending, "na" as classified-no-match.

No sentiment field

OutX classifies posts into your intent labels, not into positive/negative sentiment, and relevance_score measures topical relevance, not tone. If you need sentiment, model it as an intent label (for example a label described as “frustrated with or complaining about a competitor”) or derive it from post content yourself.

Create Keyword Watchlist

Set labels at creation time

Update Keyword Watchlist

Replace labels or toggle defaults

Get Posts

Filter the feed by labels

Choose a Watchlist Type

LinkedIn vs Reddit watchlists