Skip to main content
Track LinkedIn posts containing specific keywords with powerful filtering options. Monitor industry trends, job postings, or any topic of interest with customizable fetch frequencies.
Platform: LinkedIn. This endpoint creates LinkedIn watchlists only. To track the same keywords or prompt on Reddit, make a separate call to POST /api-reddit-watchlist (identical body shape). One watchlist = one platform; “LinkedIn and Reddit” always means two create calls. See Choose a watchlist type.
The endpoint accepts two body shapes. Pass either keywords or prompt, not both.
Start with Prompt mode. You send one sentence and OutX writes the keywords, the intent labels and the relevance objective. Keywords mode, documented first below, is the advanced path for callers that already know the exact strings to match. Before creating several watchlists, read Design your watchlists: one watchlist carries one signal.

Request Body (direct keywords mode)

string
Watchlist name. If not provided, a name will be auto-generated based on keywords.
array
required
Array of keywords to track. Can be simple strings or advanced keyword objects with filtering rules.Simple format:
Advanced format with filters:
string
Optional description for the watchlist
array
Custom intent labels OutX uses to classify matching posts. Each label is a name, a description (what the AI matches a post against), and an optional default flag marking it as a pre-applied feed filter (at most 2 can be true; if you set default on some labels but mark none true, the first is promoted). If omitted, OutX generates a label taxonomy in the background. See Intent labels & defaults and How intent labels are calculated.
string
One-sentence objective describing who or what you want to find and why (for example "Find companies actively hiring senior remote engineers so we can pitch our sourcing tool"). It seeds the relevance-scoring vector, so it is what makes the feed rank and filter like a prompt-built watchlist.Optional but strongly recommended in keywords mode. If you omit it, OutX writes one in the background from the name, description and keywords, which is a guess at what your keyword strings were for. The response’s generated.objective tells you when that happened.
number
default:"12"
Fetch frequency in hours. Allowed values: 1, 3, 6, 12, 24, 48, 72
string | null
Optional Slack incoming-webhook URL to receive notifications when new matching posts are found.
string
Optional retry key you choose, up to 128 characters. A second create carrying the same key within about two minutes returns the watchlist the first one made instead of a duplicate. Send one on every create. See Idempotency.

How intent labels are calculated

Full reference: Intent labels, enrichment & default feed filters, including what default: true/false means and how to change defaults later.
Labels (shown as Intents in the OutX app) are how OutX classifies the meaning of a matched post, not just whether it matched a keyword. Each label is a name plus a description, and the description is what the AI matches a post against. Labels are stored on the watchlist, not on individual posts. They are applied to posts during a background enrichment pass and then surface on each post in the Get posts response as tags (the matched label name) and tagDescriptions.
The same concept has two names in the API: labels on the watchlist, tags on a post. A post’s tag is the label it was classified into. A post with no confident match gets the tag "na".

How a post gets classified

Each newly collected post is enriched in two steps:
  1. Relevance scoring (deterministic). The post is scored against the watchlist using embedding similarity plus keyword matching, producing relevance_score (1-10). Low-relevance posts are tagged "na" and skip the next step.
  2. Label selection (AI). For relevant posts, a single model call picks the one label whose description best fits the post, or none. The chosen label is written to the post’s tags.
Because only the description is read by the classifier, a clear, specific description matters far more than the name.
There is no sentiment field on posts. OutX classifies posts into your intent labels (tags), not into positive/negative sentiment, and relevance_score measures relevance to the watchlist, not tone. If you need sentiment, derive it from the post content yourself, or model it as an intent label (for example a label described as “frustrated with or complaining about a competitor”).

Timing: labels are not instant

A post is not labeled the moment you create the watchlist. Two delays stack:
  1. Collection cadence. New posts only arrive on the watchlist’s fetchFreqInHours cycle (1, 3, 6, 12, 24, 48, 72; default 12h). Until the next scan runs, there are no new posts to classify.
  2. Enrichment. Every newly collected post starts unlabeled and is classified by a background job. Historical posts pulled in when the watchlist is first created are unlabeled the same way until that job processes them.
Labeled posts therefore appear after the next fetch cycle plus the time enrichment takes to work through its queue, not instantly. An agent polling Get posts right after creating a watchlist should treat empty tags as “not classified yet,” not “no match.”

Editing labels is forward-only

Each post is classified into a label exactly once, when it is first enriched. Adding or changing labels with Update keyword watchlist changes how future posts are classified but does not re-label posts that were already enriched, they keep the tags they had. To re-classify already-collected posts against new labels, those posts must be explicitly re-enriched (OutX re-runs classification over roughly the last 30 days); a plain label update does not do this on its own.

Advanced Keyword Filtering

Each keyword can have additional filtering rules:
string
required
The primary keyword to search for
array
Optional, despite the name. Context keywords used together with the primary keyword. How they combine is controlled by include_all_required. Omit it, or send an empty array, to match on the primary keyword alone. Only keyword is required on a keyword object.
array
None of these keywords should be present in the post (NOT logic)
boolean
default:"true"
Controls how required_keywords combine. true (default) means every required keyword must be present (AND logic). false means any one is enough (OR logic). OR usually matches far more posts and is what the AI prompt generator uses, so set include_all_required to false when a multi-term required list is matching almost nothing. Plain-string keyword entries always use the default (AND).
When you create a keyword watchlist, OutX backfills recent matching posts automatically in the background, so the watchlist is usually non-empty within minutes instead of waiting for the first live fetch cycle. The window is fixed: free teams get the last 7 days, up to 100 posts; paid teams get the last 7 days, up to 1,000 posts, plus days 7 to 30, up to 500 more. The same backfill runs again whenever you change the watchlist’s keywords or its prompt.

Idempotency

Two guards stop a retry from creating a second watchlist. Both run before the plan-watchlist check, so a retry that matches gets the existing watchlist back rather than a 402. A retry that does not match falls through to a normal create, plan check included, so 402 is still possible: the guards are best effort, and a lookup that misses simply creates. Send idempotency_key: any string up to 128 characters, unique per logical create. A UUID per create is the simplest choice. A second request with the same key, from the same team, within about two minutes is answered with the watchlist the first one made, whatever else the body says. The deduplicated answer is 201 with created: false and deduplicated: true. Treat it as success.
Best effort, not atomic. The duplicate lookup and the insert are separate steps, so two genuinely simultaneous identical creates can both go through. Retry one at a time rather than in parallel, and read created on the response instead of assuming.
A key that is not a string, or is longer than 128 characters, is rejected with 400 before anything is created.

Matching keyword set (keywords mode, no key needed)

Without a key, a keywords-mode create is also idempotent on the keyword set. If your team already has a keyword watchlist whose primary keywords match the request exactly (order-insensitive, lower-cased, trimmed), that watchlist is returned with:
  • HTTP status 200 OK (instead of 201 Created)
  • created: false
  • The existing watchlist’s fetchFreqInHours and labels. Your request’s values are ignored for the duplicate match.
This one has no time window: a matching watchlist created months ago still wins. In prompt mode, an unkeyed retry instead matches a watchlist created from the same prompt in the last couple of minutes.

Response Fields

string
Unique identifier for the watchlist
string
Watchlist name
string
URL-friendly slug for the watchlist
string
Always “keyword” for keyword watchlists
array
Array of tracked keywords
number
Fetch frequency in hours
boolean
true when a new watchlist was created, false when an existing watchlist was returned instead. See Idempotency.
boolean
Present and true only when a duplicate guard returned an existing watchlist. Absent on a normal create.
array
Array of keyword creation results
array
Intent labels persisted on the watchlist, as { key, description, default } objects. When you did not supply real labels, these are placeholders that are replaced by an AI-generated taxonomy a few seconds later (see message).
object
Keywords mode only. Two booleans, objective and labels, each true when you left that field out and OutX is writing it for you in the background. A generated label set gets at most two defaults, the same cap as a set you supply.generated.objective: true means the relevance target was inferred from your keyword strings rather than stated by you. Send objective on the next create to avoid that.
string
Present when OutX is generating a missing objective or label taxonomy in the background: "Watchlist created. An objective and intent labels are being generated in the background and will be available shortly."

Error Responses

Use Cases

Monitor hiring posts for specific roles and locations:
Watch for mentions of competitors:

Prompt mode

Skip the keyword brainstorming and let OutX generate keywords and intent labels for you. Send a single prompt field describing what you want to track in plain English. OutX creates the watchlist immediately and runs keyword and label generation in the background.

Request Body

string
required
Plain-English description of what to track. A URL is allowed inside a sentence, and OutX fetches that page’s title and description to improve keyword quality. A URL on its own is refused: the prompt needs at least three words besides the link, saying who should be posting and what makes a post worth seeing. A LinkedIn profile link needs eight, and is better served by a people watchlist.Examples:
  • "AI-native CRM tools and competitors like Salesforce, HubSpot"
  • "People looking for remote software engineering jobs"
  • "Mentions of our product Acme and common complaints"
string
Optional watchlist name. Auto-generated from the prompt if omitted.
number
default:"12"
Fetch frequency in hours. Allowed values: 1, 3, 6, 12, 24, 48, 72.
string
Optional retry key you choose, up to 128 characters. Answered before the prompt is even read, so a retry costs nothing and cannot be refused over an interpretation the first request was never held to. See Idempotency.
boolean
default:"false"
When true, refuse to create rather than infer. Any slot OutX had to fill in itself triggers the refusal: topic, audience and signals whenever the prompt leaves them empty, and competitors, use_case or excluded whenever OutX inferred them. The call returns 422 with missing listing exactly which ones, and nothing is created. Use it when a wrong watchlist is worse than no watchlist.
Prompt mode reads only these five fields. labels, objective, description and slack_webhook_url are ignored on a prompt-mode create. OutX writes the objective itself, from the prompt.Of the other three, only labels and slack_webhook_url can be set afterwards with a PUT. objective and description are accepted on a keywords-mode create only. Update accepts neither, so a prompt-built watchlist cannot be given a hand-written objective or description through the API.
Keywords and intent labels populate on the watchlist a few seconds after creation. Use Get Keyword Watchlist to fetch the latest state.

How OutX read your prompt

A prompt-mode create returns two extra fields so you can see what was understood before any post is collected.
object
The slots the prompt was read into: topic (what the posts are about), audience (who is posting), signals (what makes a post worth seeing), competitors (names to track literally), use_case (one of lead_generation_buying, lead_generation_broad, brand_monitoring, competitor_tracking, reputation_management, content_inspiration, market_research), excluded (post types kept out of the default feed), and refined_prompt (your prompt rewritten as one clear sentence). null when the reading could not run, in which case the watchlist is still built from the raw prompt.
array
The slot names OutX filled in by inference because the prompt did not state them. Empty when the prompt stated everything. Show refined_prompt and assumed to your user when the difference matters.

When a prompt is refused

The prompt is checked before anything is created, so a bad prompt costs you nothing. A 422 means no watchlist exists.
string
Present only when a single answer would make the prompt usable. Relay it to your user word for word, put their answer into the prompt, and retry. Guessing a topic on their behalf builds a confident watchlist about the wrong thing.
string
A rewritten prompt of the same shape that would pass. When question is absent, use this as the shape to copy.
array
Which slots are at fault. The vocabulary differs by refusal kind:
  • Prompt check (any prompt-mode call): topic, audience, signal. Either all three, or just topic.
  • strict refusal: the slots that would have been inferred, drawn from topic, audience, signals (plural here), competitors, use_case, excluded. detected.interpretation shows how the prompt was read.
Treat it as a list of strings, not a fixed enum.
Prompts refused this way include: one with no subject in it (“find me buyers”), an unfilled [PLACEHOLDER], a bare LinkedIn profile link (track a person with a people watchlist instead), a bare URL, a request for engagement on your own posts, keyboard mashing, and anything under 6 words or 30 characters.

Frequently Asked Questions

There is no hard per-watchlist keyword cap enforced by the API. What your plan caps is the number of watchlists and the posts collected per watchlist per week, so a very broad keyword set exhausts the weekly post quota faster. Check your plan limits with GET /api-team.
Make a second create call to POST /api-reddit-watchlist with the same keywords or prompt. LinkedIn and Reddit watchlists are separate resources with separate IDs and feeds; there is no single call that creates both.
Tracking begins immediately after creation. OutX backfills recent matching posts in the background, so the watchlist is usually non-empty within minutes. Ongoing collection then runs on the schedule you set with fetchFreqInHours, so each later batch arrives on the next fetch cycle.
When you reach the maximum number of watchlists allowed by your plan, the API will return an error when you try to create a new one. You can either delete an existing watchlist to free up a slot, or upgrade your plan for higher limits.