{"openapi":"3.0.0","info":{"title":"Rumoro API","version":"0.0.1","description":"Keyword and brand mention tracking across dev platforms."},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key minted via POST /v1/api-keys (format ref_...)"}},"schemas":{"GroupRef":{"type":"object","properties":{"id":{"type":"string","description":"Group id (grp_...)."},"name":{"type":"string","description":"The group's name."},"externalId":{"type":"string","nullable":true,"description":"Your own id for the group, or null."},"isDefault":{"type":"boolean","description":"The workspace's default group, where a keyword lands when no group is named."}},"required":["id","name","externalId","isDefault"],"description":"The group the keyword belongs to."},"ReviewSource":{"type":"object","properties":{"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."},"id":{"type":"string","description":"The id on the platform: app id, package name, Trustpilot domain, Google Place ID or cid."},"url":{"type":"string","description":"The review page: the store listing, the Trustpilot page or the Google Maps place."},"countries":{"type":"array","items":{"type":"string"},"description":"Storefronts read, lowercase two-letter codes; empty on Trustpilot and Google Maps."},"language":{"type":"string","nullable":true,"description":"Google Play's review language; null elsewhere."},"connectedAt":{"type":"string","description":"When this keyword started collecting the page's reviews."}},"required":["platform","id","url","countries","language","connectedAt"]},"Keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string"},"kind":{"type":"string","enum":["brand","competitor","topic"]},"muted":{"type":"boolean","description":"Not polled or matched. Paused by you, by the wallet (see pausedForBalance) or by the noise brake (see pausedForNoise). A keyword at its mention cap is not muted (see pausedForCap)."},"pausedForBalance":{"type":"boolean","description":"Muted by the wallet for lack of balance; a top-up resumes it, unmuting by hand needs balance too."},"pausedForNoise":{"type":"boolean","description":"Muted by the noise brake: on a workspace running on its welcome credit, at least 20 of its matches were scored and under 30% were relevant. A change of its required or excluded terms, platforms or context resumes it (when the balance covers another day), and so does unmuting; a top-up does not."},"pausedForCap":{"type":"boolean","description":"At its monthly mention cap: not matched until the first of next month (UTC) or until the cap is raised. Not muted: it keeps its place and its daily keyword charge."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"Matched mentions allowed per calendar month (UTC). Every match counts, relevant or not, the look-back a new keyword gets included, because every match bills."},"welcome":{"type":"boolean","description":"Set by Rumoro, not you: a workspace on its welcome credit collects at most 200 mentions a keyword a month. The first top-up removes it."},"own":{"type":"integer","nullable":true,"description":"Your own cap. With welcome true, the cap the keyword gets back at the first top-up (null for none); otherwise the same as mentions. Sending mentions: 200 back while welcome is true changes nothing."}},"required":["mentions","welcome","own"],"description":"The monthly mention cap, or null for none."},"group":{"$ref":"#/components/schemas/GroupRef"},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Platforms the term is searched on; null means every platform, [] none (the keyword only collects reviews)."},"reviewSources":{"type":"array","items":{"$ref":"#/components/schemas/ReviewSource"},"description":"Where this keyword collects reviews from (App Store and Google Play apps, Trustpilot pages, Google Maps places); empty for none."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"A sentence the classifier reads for this keyword only, on top of the company profile or the group's own description (at most 300 characters): what the term means here, what to ignore. \"Arc is our browser; ignore the geometry word.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"The post must ALSO contain these terms, any one of them or all of them per requiredMode. Empty: no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any: at least one required term must appear. all: every one must."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"A post containing any of these is dropped. A `*` at the start or the end of an entry is a wildcard (beta.* matches beta.0.1; *bot matches nightlybot)."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Posts by these authors are dropped: profile or post links, @handles, u/names, Bluesky DIDs or display names, stored in canonical form like an alert's muted list."},"caseSensitive":{"type":"boolean","description":"true: the term must appear in the case it was typed (RAG, never rag). Default false."}},"required":["requiredTerms","requiredMode","excludedTerms","excludedAuthors","caseSensitive"],"description":"Matching rules applied before a mention is stored; a rejected post is never billed."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"Every match ever, relevant or not: the number billing counts."},"relevant":{"type":"integer","minimum":0,"description":"Matches scored at or above the relevance threshold."},"last7d":{"type":"integer","minimum":0,"description":"Matches published in the last 7 days."},"thisMonth":{"type":"integer","minimum":0,"description":"Matches recorded this calendar month (UTC), the count a cap compares against."},"lastMentionAt":{"type":"string","nullable":true,"description":"Newest matched post; null until the first one."},"feedback":{"type":"object","properties":{"relevant":{"type":"integer","minimum":0,"description":"Mentions a person marked relevant."},"notRelevant":{"type":"integer","minimum":0,"description":"Mentions a person marked not relevant: the noise the classifier let through."}},"required":["relevant","notRelevant"],"description":"Your verdicts on this keyword's mentions (PATCH /v1/mentions/{id} relevant)."},"noise":{"type":"object","properties":{"scored":{"type":"integer","minimum":0,"description":"Matches of the last 14 days (by match time) the classifier has scored."},"relevant":{"type":"integer","minimum":0,"description":"Of those, the ones scored relevant."},"noisy":{"type":"boolean","description":"At least 20 scored matches in the last 14 days and under 30% of them relevant: tighten the keyword with required terms, excluded terms or context. Every match bills, relevant or not."}},"required":["scored","relevant","noisy"],"description":"Relevance over the last 14 days of scored matches, so a keyword tightened today stops being flagged within two weeks."},"health":{"type":"string","enum":["healthy","noisy","quiet","capped","paused","new"],"description":"The keyword's health over the same 14 days as `noise`, by the rule GET /v1/keywords/{id}/health applies to its own window: paused (muted), capped (at its mention cap), noisy (20 or more scored matches, under 30% relevant), new (under 7 days old and not noisy, or changed in the last 7 days with under 20 scored matches since), quiet (7 days or older, nothing relevant), else healthy. Judged on the matches since the keyword's last change to its matching rules, platforms or context (or its unmute) when that is inside the 14 days, so a keyword tightened today is not flagged on the noise the change removed; `noise` itself keeps the whole 14 days. Always 14 days, while the endpoint reads 30 by default, so the two can differ for the same keyword. The health endpoint says why and what to change."},"cost":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Days this month the keyword was charged for: unmuted at the daily tick. A keyword created today reads 0 until tomorrow's tick."},"keywordCents":{"type":"integer","description":"Those days at the keyword rate ($5 a month, 500/30 cents a day), rounded once on the total."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed this month, counted when they were scored (the clock the ledger settles by), so it can trail thisMonth by the matches still being scored and never counts one that failed to score."},"mentionCents":{"type":"integer","description":"Those matches at $0.008 each, rounded once on the total."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents: what this keyword has cost this month, in USD cents."}},"required":["keywordDays","keywordCents","billableMentions","mentionCents","totalCents"],"description":"What this keyword has cost this calendar month (UTC) at list price: exactly its row in GET /v1/usage/breakdown?month=<this month> (same tables, same rounding). The wallet's ledger, which settles once a day, is what can differ from these list-price numbers, and only by cumulative rounding."}},"required":["mentions","relevant","last7d","thisMonth","lastMentionAt","feedback","noise","health","cost"],"description":"Computed over this workspace's matches."},"polling":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"lastPolledAt":{"type":"string","nullable":true,"description":"Newest poll of this platform for the term; null until the first one."},"emptyPolls":{"type":"integer","description":"Consecutive polls that found nothing new; the scheduler slows down as it grows."}},"required":["platform","lastPolledAt","emptyPolls"]},"description":"Poll health per platform polled on a schedule. Live feeds (Bluesky) have no entry."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","term","kind","muted","pausedForBalance","pausedForNoise","pausedForCap","cap","group","platforms","reviewSources","context","matching","stats","polling","createdAt"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized","forbidden","read_only_key","validation_error","not_found","invalid_cursor","payload_too_large","rate_limited","duplicate_keyword","insufficient_balance","keyword_limit_reached","billing_not_configured","order_not_credited","schedule_required","unknown_channel","not_a_digest","hourly_email_unsupported","slack_not_connected","slack_not_configured","telegram_not_configured","email_not_configured","invalid_assignee","classification_pending","invalid_member","already_member","last_owner","duplicate_segment","filter_too_complex","duplicate_view","duplicate_group","default_group","default_group_context","group_changed","invalid_signature","webhook_not_configured","invalid_token","protected_user","upstream_unavailable","internal_error"],"description":"Stable machine-readable code; branch on this, never on the message. Codes are additive: a client should treat one it does not know as a generic failure of the same status."},"message":{"type":"string","description":"Human-readable detail; may change between releases."},"requestId":{"type":"string","description":"The id of this request (also the X-Request-Id response header); quote it to support."},"retryAfterSeconds":{"type":"integer","description":"For rate_limited and other retryable errors: how long to wait before retrying (mirrors the Retry-After header)."}},"required":["code","message"],"description":"The error."}},"required":["error"]},"KeywordSuggestion":{"type":"object","properties":{"type":{"type":"string","enum":["excluded_terms","excluded_authors","required_terms","platforms","context"],"description":"excluded_terms and excluded_authors add to the matching rules; required_terms sets them; platforms drops the platforms that are almost all noise; context rewrites the sentence the classifier reads."},"values":{"type":"array","items":{"type":"string"},"description":"What it adds (terms, authors), drops (platforms) or writes (the context)."},"why":{"type":"string","description":"The reason and the measured effect, in plain words."},"patch":{"type":"object","properties":{"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"Reclassify it as brand, competitor or topic."},"muted":{"type":"boolean","description":"A muted keyword stops polling and matching; its mentions stay."},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Replaces the platform list; null means every platform, [] none (reviews only, when the keyword has reviewSources)."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"A sentence the classifier reads for this keyword only, on top of the company profile or the group's own description (at most 300 characters): what the term means here, what to ignore. \"Arc is our browser; ignore the geometry word.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"The post must ALSO contain these terms, any one of them or all of them per requiredMode. Empty: no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any: at least one required term must appear. all: every one must."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"A post containing any of these is dropped. A `*` at the start or the end of an entry is a wildcard (beta.* matches beta.0.1; *bot matches nightlybot)."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Posts by these authors are dropped: profile or post links, @handles, u/names, Bluesky DIDs or display names, stored in canonical form like an alert's muted list."},"caseSensitive":{"type":"boolean","description":"true: the term must appear in the case it was typed (RAG, never rag). Default false."}},"description":"Omitted fields are untouched; an empty list clears one."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"Matched mentions allowed per calendar month (UTC). Every match counts, relevant or not, the look-back a new keyword gets included, because every match bills."}},"required":["mentions"],"description":"Replaces the monthly mention cap; null removes it. A cap above this month's count resumes a capped keyword at once, one at or under it pauses it."},"groupId":{"type":"string","minLength":1,"description":"Moves the keyword to this group (grp_...). A 409 when that group already tracks the term."},"reviewSources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"The review page's link: an App Store or Google Play app (https://apps.apple.com/us/app/notion/id1232780281, https://play.google.com/store/apps/details?id=notion.id), a Trustpilot page (https://www.trustpilot.com/review/notion.so) or a Google Maps place (its full link, or a maps.app.goo.gl share link). Or give platform and id."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."},"id":{"type":"string","minLength":1,"maxLength":200,"description":"The id on the platform: the digits after \"id\" on the App Store, the package name on Google Play, the company's domain on Trustpilot (notion.so), a Place ID (ChIJ...) on Google Maps."},"countries":{"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"},"minItems":1,"maxItems":20,"description":"App Store and Google Play only: storefronts to read, two-letter codes, at most 20. Default: the one in the link, else us. Each is one more poll a day; the same review seen in two storefronts is one mention. Trustpilot and Google Maps have one page for everyone and take none."},"language":{"type":"string","minLength":2,"maxLength":10,"description":"Google Play only: the language of the reviews to read (en, es, de, pt-BR); Google Play answers one language at a time. Default: the link's hl, else en."}},"description":"A review page whose reviews become this keyword's mentions: its link, or the platform and the id."},"maxItems":10,"description":"Replaces the list of apps whose reviews this keyword collects; [] disconnects them all (their reviews stay). An app or country added here gets the free 30-day look-back; one already listed keeps its place."}},"description":"The body to send to PATCH /v1/keywords/{id} as is to apply it. A list holds the whole new list, current entries kept."},"effect":{"type":"object","nullable":true,"properties":{"noiseRemoved":{"type":"integer","minimum":0,"description":"Noise matches of the window (since stats.judgedSince when set) the change would have removed (estimated from the sample unless exact)."},"relevantRemoved":{"type":"integer","minimum":0,"description":"Relevant matches of the window it would have removed."},"centsSaved":{"type":"integer","description":"What the removed matches cost at the mention rate: what the change would have saved over the window."},"sample":{"type":"object","properties":{"noiseRemoved":{"type":"integer","minimum":0,"description":"Sampled noise posts the change rejects."},"noise":{"type":"integer","minimum":0,"description":"Noise posts sampled."},"relevantRemoved":{"type":"integer","minimum":0,"description":"Sampled relevant posts the change rejects."},"relevant":{"type":"integer","minimum":0,"description":"Relevant posts sampled."}},"required":["noiseRemoved","noise","relevantRemoved","relevant"],"description":"The measurement behind the estimate: the matcher's own rules run over the sampled posts."},"exact":{"type":"boolean","description":"The sample was the whole window, so the counts are measured, not estimated."}},"required":["noiseRemoved","relevantRemoved","centsSaved","sample","exact"],"description":"What the change would have done over the window, measured with the matcher's own rules. Null for a context, which changes scores, not matches."},"source":{"type":"string","enum":["rules","ai"],"description":"rules: computed from the window's posts. ai: written by a language model (ai=true)."}},"required":["type","values","why","patch","effect","source"]},"KeywordHealth":{"type":"object","properties":{"keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The term as typed."},"group":{"$ref":"#/components/schemas/GroupRef"}},"required":["id","term","group"],"description":"The keyword the report is about."},"window":{"type":"object","properties":{"from":{"type":"string","description":"First day, YYYY-MM-DD, inclusive, UTC."},"to":{"type":"string","description":"Last day, inclusive: today."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."}},"required":["from","to","days"],"description":"The window the report reads, by match time, in UTC days."},"status":{"type":"string","enum":["healthy","noisy","quiet","capped","paused","new"],"description":"healthy: nothing to fix. noisy: 20 or more scored matches in the window and under 30% of them relevant. quiet: 7 days or older with no relevant match in the window. capped: at its monthly mention cap. paused: muted (by you, the wallet or the noise brake). new: under 7 days old and not noisy yet, or changed in the last 7 days with under 20 scored matches since the change. When the keyword's matching rules, platforms or context changed (or it was unmuted) inside the window, the status reads only the matches since then (stats.judgedSince)."},"reasons":{"type":"array","items":{"type":"string"},"description":"Why, in plain words; the first line explains the status."},"stats":{"type":"object","properties":{"matches":{"type":"integer","minimum":0,"description":"Matches recorded in the window, relevant or not."},"relevant":{"type":"integer","minimum":0,"description":"Scored at or above the relevance line (40)."},"filtered":{"type":"integer","minimum":0,"description":"Scored under the line: the noise. Billed like any match."},"unscored":{"type":"integer","minimum":0,"description":"Not scored yet, or failed to score (never billed)."},"noiseShare":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"filtered / (relevant + filtered); null with nothing scored."},"workspaceShare":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"This keyword's share of the workspace's matches in the window; null when the workspace matched nothing."},"judgedSince":{"type":"string","nullable":true,"description":"When the keyword last changed its matching rules, platforms or context (or was unmuted), when that is inside the window: the status, the reasons, noiseTerms, noiseAuthors and suggestions read only the matches since then, while these numbers keep the whole window. Null: everything reads the whole window."},"byPlatform":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"matches":{"type":"integer","minimum":0,"description":"Matches on this platform in the window."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored at or above the relevance line (40)."},"filtered":{"type":"integer","minimum":0,"description":"Of those, scored under the line: the noise."},"noiseShare":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"filtered / (relevant + filtered); null with nothing scored."}},"required":["platform","matches","relevant","filtered","noiseShare"]},"description":"One row per platform it matched on, most matches first."},"weekly":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","description":"First day of the 7, YYYY-MM-DD (counted from the window's first day)."},"matches":{"type":"integer","minimum":0,"description":"Matches in those 7 days."},"relevant":{"type":"integer","minimum":0,"description":"Of those, relevant."}},"required":["from","matches","relevant"]},"description":"The trend, one row per 7 days of the window, oldest first; the last row may be shorter."},"cost":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Days in the window the keyword was charged for."},"keywordCents":{"type":"integer","description":"Those days at the keyword rate."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed in the window, by the time they were scored."},"mentionCents":{"type":"integer","description":"Those matches at the mention rate."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents: its row in GET /v1/usage/breakdown for the same range."}},"required":["keywordDays","keywordCents","billableMentions","mentionCents","totalCents"],"description":"What the keyword cost over the window at list price."}},"required":["matches","relevant","filtered","unscored","noiseShare","workspaceShare","judgedSince","byPlatform","weekly","cost"],"description":"Computed over the keyword's matches in the window."},"sample":{"type":"object","properties":{"noise":{"type":"integer","minimum":0,"description":"Noise posts read (the newest of the window, or since stats.judgedSince, at most 200), on platforms matched by text. None under 20 scored matches since a change."},"relevant":{"type":"integer","minimum":0,"description":"Relevant posts read, likewise."}},"required":["noise","relevant"],"description":"The posts behind noiseTerms, noiseAuthors and the effects, after the keyword's current rules (a post an older rule let in is not counted). Review platforms are matched by app, not by text, and are left out."},"noiseTerms":{"type":"array","items":{"type":"object","properties":{"term":{"type":"string","description":"A word or two-word phrase."},"noisePosts":{"type":"integer","minimum":0,"description":"Sampled noise posts that carry it."},"relevantPosts":{"type":"integer","minimum":0,"description":"Sampled relevant posts that carry it."},"lift":{"type":"number","nullable":true,"description":"How many times more common it is in noise than in relevant posts (smoothed); null with no relevant post to compare."}},"required":["term","noisePosts","relevantPosts","lift"]},"description":"Up to 10 words or phrases over-represented in the noise against the relevant posts, strongest first. The keyword's own words are left out."},"noiseAuthors":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The author as the platform shows them."},"entry":{"type":"string","description":"What matching.excludedAuthors would store for them."},"noisePosts":{"type":"integer","minimum":0,"description":"Sampled noise posts by them."}},"required":["name","entry","noisePosts"]},"description":"Authors with 3 or more noise posts in the sample and no relevant one."},"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/KeywordSuggestion"},"description":"Changes that would cut the noise, each ready for PATCH /v1/keywords/{id}. Empty when nothing is worth changing, or under 20 scored matches since the last change (a reason says so)."},"ai":{"type":"object","properties":{"requested":{"type":"boolean","description":"ai=true was asked."},"status":{"type":"string","enum":["off","generated","cached","unavailable","rate_limited"],"description":"off: not asked. generated: written now. cached: written earlier today for the same keyword, window and settings. unavailable: the model failed, answered nothing usable or is not configured. rate_limited: the workspace's 20 model calls this hour are spent."}},"required":["requested","status"],"description":"The optional language model half of the report."},"generatedAt":{"type":"string","description":"When the report was computed; it is cached for 5 minutes, and a change to the keyword starts a fresh one."}},"required":["keyword","window","status","reasons","stats","sample","noiseTerms","noiseAuthors","suggestions","ai","generatedAt"]},"WorkspaceFilters":{"type":"object","properties":{"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":200,"description":"A post containing any of these is dropped, whatever keyword matched it. Same phrase rule as a keyword; a `*` at an end is a wildcard. \"hiring, job, careers\" is the classic list."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":200,"description":"Posts by these authors are dropped everywhere: your own accounts, employees, known spammers. Profile or post links, @handles, u/names, Bluesky DIDs or display names, stored in canonical form."},"excludedRepos":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"GitHub repositories whose issues, pull requests and comments are dropped, as owner/name or a github.com link (facebook/react, https://github.com/facebook/react)."},"subreddits":{"type":"object","properties":{"only":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"When non-empty, ONLY Reddit posts from these subreddits pass and `excluded` is ignored. r/name or name."},"excluded":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Reddit posts from these subreddits are dropped. r/name or name."}},"required":["only","excluded"],"description":"Reddit only."},"updatedAt":{"type":"string","nullable":true,"description":"Last edit; null until the first."}},"required":["excludedTerms","excludedAuthors","excludedRepos","subreddits","updatedAt"],"description":"Workspace-wide matching rules; a rejected post is never billed."},"Mention":{"type":"object","properties":{"id":{"type":"string","description":"Mention id (mm_...): one post matched to one of your keywords. A post matching two keywords has two ids."},"status":{"type":"string","enum":["open","ignored","done"],"description":"open: nobody handled it yet. ignored: hidden from the feed and channels by you. done: handled."},"relevant":{"type":"boolean","description":"The classifier scored it at or above the delivery threshold (40)."},"delivered":{"type":"boolean","description":"Reached at least one of your channels."},"priority":{"type":"number","description":"Attention score, one decimal, computed at read time: relevance halved, author reach on a follower ladder (unknown reach counts 8), the strongest intent (buy intent 20 down to praise 5), minus 2 per day of age floored at 20."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"group":{"$ref":"#/components/schemas/GroupRef"}},"required":["id","term","group"],"description":"The keyword this post matched, and the group it is in."},"post":{"type":"object","properties":{"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"url":{"type":"string","description":"Permalink of the post."},"text":{"type":"string","description":"Title and body, truncated to 8 KB at ingest."},"title":{"type":"string","nullable":true,"description":"The post's own title where the platform has one: a Hacker News story, a Reddit thread, a GitHub issue or pull request, a Stack Overflow question, a DEV article, a YouTube video, a news article, a titled review. Null for platforms without titles (X, Bluesky, LinkedIn) and for posts ingested before October 2026."},"imageUrl":{"type":"string","nullable":true,"description":"A preview image of the post, when the platform sent one with it: a YouTube thumbnail, a DEV cover, a news article's sharing image, a Bluesky link card or image. Null otherwise."},"links":{"type":"array","items":{"type":"string"},"description":"Links the post carries, in the order written, at most 20. Empty for a post with none, and for posts ingested before September 2026."},"publishedAt":{"type":"string","description":"When the post was published."},"engagement":{"type":"object","nullable":true,"properties":{"likes":{"type":"integer","nullable":true,"minimum":0},"reposts":{"type":"integer","nullable":true,"minimum":0},"replies":{"type":"integer","nullable":true,"minimum":0},"quotes":{"type":"integer","nullable":true,"minimum":0},"views":{"type":"integer","nullable":true,"minimum":0},"bookmarks":{"type":"integer","nullable":true,"minimum":0}},"required":["likes","reposts","replies","quotes","views","bookmarks"],"description":"Engagement counts as the platform reported them when the post was ingested, usually minutes after it was written; a count the platform does not have is null. Null as a whole for platforms that report none and for posts ingested before September 2026. X carries all six."},"replyTo":{"type":"object","nullable":true,"properties":{"author":{"type":"string","nullable":true,"description":"Parent post author as the platform names them."},"url":{"type":"string","nullable":true,"description":"Parent post URL."},"text":{"type":"string","nullable":true,"description":"Parent post text, when the platform gave it."}},"required":["author","url","text"],"description":"The post this one replies to (X, Bluesky); null for top-level posts."}},"required":["platform","url","text","title","imageUrl","links","publishedAt","engagement","replyTo"]},"author":{"type":"object","nullable":true,"properties":{"id":{"type":"string","nullable":true,"description":"Person id (aut_...) for GET /v1/people/{id}; null when the account is not in the audience yet."},"name":{"type":"string","nullable":true,"description":"Display name as the platform reports it."},"handle":{"type":"string","nullable":true,"description":"Platform handle derived from the profile URL, formatted as the platform shows it (@name, u/name); null where the platform has none."},"url":{"type":"string","nullable":true,"description":"Profile URL."},"avatarUrl":{"type":"string","nullable":true,"description":"Profile picture; null where the platform has none."},"followers":{"type":"integer","nullable":true,"description":"Follower count as of their newest post; null where the platform has none."},"tags":{"type":"array","items":{"type":"string"},"description":"Your workspace tags on this person."}},"required":["id","name","handle","url","avatarUrl","followers","tags"],"description":"Who posted it; null when the platform gave no author at all."},"review":{"type":"object","nullable":true,"properties":{"rating":{"type":"integer","minimum":1,"maximum":5,"description":"Stars the reviewer gave."},"ratingMax":{"type":"integer","description":"The top of the scale: 5 on both stores."},"title":{"type":"string","nullable":true,"description":"The review's headline; null where the store has none (Google Play)."},"version":{"type":"string","nullable":true,"description":"The app version the reviewer ran, when the store says."},"country":{"type":"string","nullable":true,"description":"The storefront it was read in (App Store, Google Play) or the reviewer's country (Trustpilot), a lowercase two-letter code; null where the platform gives none."},"verified":{"type":"boolean","nullable":true,"description":"The platform marks the review as verified (Trustpilot); null where the platform has no such mark."},"response":{"type":"string","nullable":true,"description":"The developer's reply as it stood when the review was collected; null for none."},"responseAt":{"type":"string","nullable":true,"description":"When the developer replied."},"app":{"type":"object","properties":{"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."},"id":{"type":"string","description":"The store's app id."},"url":{"type":"string","description":"The app's store listing."}},"required":["platform","id","url"],"description":"The app reviewed."}},"required":["rating","ratingMax","title","version","country","verified","response","responseAt","app"],"description":"An app store review's facts; null for every other post. Its sentiment comes from the stars (4 and 5 positive, 3 neutral, 1 and 2 negative) and it always counts as relevant, since you chose the app."},"classification":{"type":"object","nullable":true,"properties":{"relevance":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"0 to 100; null only when classification failed."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"intents":{"type":"array","items":{"type":"string"},"description":"Intent and topic tags: buy_intent, question, complaint, praise, comparison, churn_intent (leaving or replacing the keyword), bug_report, pricing, hiring, event, promotional, testimonial (a customer vouching for it from their own use), industry_insight (analysis or data about the field), launch (a product or feature launch announcement), feedback (a suggestion or request about it)."},"automated":{"type":"boolean","description":"The post reads as machine-made: a bot or app account, a scheduled or templated post, an obvious AI-written summary. A label only: automated mentions stay in the feed, are delivered as usual and are billed like any other match. false while unjudged."},"language":{"type":"string","nullable":true,"description":"The language the post is written in, as an ISO 639-1 code (en, es, de); null when unknown or classified before languages were recorded."},"confidence":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"How sure the classifier is of its relevance verdict, 0 to 1. null when the verdict came without one: the fallback model judged, or the row was scored before confidence was recorded."},"uncertain":{"type":"boolean","description":"The verdict deserves a human look: confidence under 0.4, or the model that wrote the note disagreed with the verdict. A flag for reviewers; it never hides a mention."},"note":{"type":"string","nullable":true,"description":"One sentence from the classifier explaining the score."},"failed":{"type":"boolean","description":"true when the model could not score this post; it stays in the feed and is not billed."},"feedback":{"type":"object","nullable":true,"properties":{"relevant":{"type":"boolean","nullable":true,"description":"Your verdict on relevance, or null when you only corrected the sentiment."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"Your corrected sentiment, or null when you only judged relevance."},"at":{"type":"string","description":"When the last verdict was given."},"original":{"type":"object","properties":{"relevance":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"What the classifier scored before your verdict; null if it had not scored it."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"The sentiment the classifier gave before your correction."}},"required":["relevance","sentiment"],"description":"The classifier values your feedback replaced."}},"required":["relevant","sentiment","at","original"],"description":"A person's correction of the verdict, or null. A relevance verdict sets `relevance` to 100 or 0 and `relevant` with it; a corrected sentiment replaces `sentiment`. Every list, filter, digest and report reads the corrected values."}},"required":["relevance","sentiment","intents","automated","language","confidence","uncertain","note","failed","feedback"],"description":"The classifier verdict, as corrected by your feedback; null while the post is still queued for classification."},"triage":{"type":"object","properties":{"assignee":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"Workspace member this mention is assigned to; null when unassigned."},"snoozedUntil":{"type":"string","nullable":true,"description":"Until when the mention stays out of the feed; null when not snoozed."},"note":{"type":"string","nullable":true,"description":"Internal note; null when none."}},"required":["assignee","snoozedUntil","note"]},"createdAt":{"type":"string","description":"When the match was recorded; the default feed order."}},"required":["id","status","relevant","delivered","priority","keyword","post","author","review","classification","triage","createdAt"]},"Person":{"type":"object","properties":{"id":{"type":"string","description":"Person id (aut_...): the canonical account. An account merged into someone resolves to that person."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform of the canonical account; `accounts` lists every account."},"name":{"type":"string","nullable":true,"description":"Display name as of their newest post; null when the platform has none."},"handle":{"type":"string","nullable":true,"description":"Platform handle of the canonical account, formatted as the platform shows it."},"url":{"type":"string","nullable":true,"description":"Profile URL of the canonical account."},"avatarUrl":{"type":"string","nullable":true},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The account id (aut_...); the canonical one equals the person id."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"name":{"type":"string","nullable":true,"description":"Display name as the platform reports it."},"handle":{"type":"string","nullable":true,"description":"Platform handle derived from the profile URL, formatted as the platform shows it."},"url":{"type":"string","nullable":true,"description":"Profile URL."}},"required":["id","platform","name","handle","url"]},"description":"Every account this workspace treats as this person, the canonical one first."},"reach":{"type":"object","properties":{"followers":{"type":"integer","nullable":true},"following":{"type":"integer","nullable":true},"posts":{"type":"integer","nullable":true}},"required":["followers","following","posts"],"description":"Platform counts as of their newest post; null where the platform has no such number."},"profile":{"type":"object","nullable":true,"properties":{"bio":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"email":{"type":"string","nullable":true,"description":"Only when the person made it public on the platform."},"links":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","minLength":1},"url":{"type":"string","format":"uri"}},"required":["provider","url"]},"description":"Other accounts the person lists on their profile."},"fetchedAt":{"type":"string","description":"When the profile was read."}},"required":["bio","company","location","website","email","links","fetchedAt"],"description":"Public profile facts; null until looked up."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"Every match of theirs for this workspace, relevant or not."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored relevant."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"neutral":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0}},"required":["positive","neutral","negative"]},"firstSeenAt":{"type":"string","description":"Their oldest matched post."},"lastSeenAt":{"type":"string","description":"Their newest matched post."}},"required":["mentions","relevant","sentiment","firstSeenAt","lastSeenAt"],"description":"Computed over this workspace's matches."},"annotations":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"notes":{"type":"string"},"muted":{"type":"boolean","description":"Their posts stay out of the feed and every channel; ingest and billing are untouched."}},"required":["tags","notes","muted"],"description":"What this workspace wrote about the person."},"outreach":{"type":"object","properties":{"owner":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"User id of the workspace member."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"The teammate who owns the contact; null when nobody does, or the owner left the workspace."},"stage":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"lastContactedAt":{"type":"string","nullable":true,"description":"The newest logged activity; null when nobody logged a contact."}},"required":["owner","stage","lastContactedAt"],"description":"Where your workspace stands with the person. The first logged activity claims an unowned person for whoever reached out and moves not_contacted to contacted."}},"required":["id","platform","name","handle","url","avatarUrl","accounts","reach","profile","stats","annotations","outreach"]},"PersonActivity":{"type":"object","properties":{"id":{"type":"string","description":"Activity id (act_...)."},"personId":{"type":"string","description":"The person it belongs to (aut_...)."},"channel":{"type":"string","enum":["email","x","linkedin","bluesky","reddit","github","call","meeting","other"],"description":"How they were reached: email, x, linkedin, bluesky, reddit, github, call, meeting or other."},"note":{"type":"string","description":"What was sent or said, briefly; empty when nothing was written."},"member":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"User id of the workspace member."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"Who reached out; null when an API key logged it without naming a member, or that member left the workspace."},"occurredAt":{"type":"string","description":"When the contact happened."},"createdAt":{"type":"string","description":"When it was logged."}},"required":["id","personId","channel","note","member","occurredAt","createdAt"]},"Segment":{"type":"object","properties":{"id":{"type":"string","description":"Segment id (seg_...)."},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People carrying any of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"At least this many followers. Unknown reach never matches."},"maxFollowers":{"type":"integer","minimum":0,"description":"At most this many followers. Unknown reach never matches."},"minMentions":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"At least one mention carrying any of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Nobody carrying any of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Nobody whose mentions carry any of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"At least one mention linking to any of these hosts, the host itself or a subdomain of it."},"muted":{"type":"boolean","description":"true: only muted people; false: only unmuted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages."},"automated":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); \"none\" matches people nobody owns."}}},"count":{"type":"integer","minimum":0,"description":"People in the segment right now; it is evaluated on every read."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"updatedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","name","description","filter","count","createdAt","updatedAt"]},"FilterGroup":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Substring in the post text or the author's name."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of any of these keywords."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of these keywords."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of keywords in these groups."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status: open, ignored, done."},"relevant":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Only mentions scored at least this."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments; an unscored mention still passes."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never mentions carrying these tags."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made; false: only the rest."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1)."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages; an unknown language still passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never authors tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers; unknown reach never passes."},"maxFollowers":{"type":"integer","minimum":0,"description":"Only authors with at most this many followers; unknown reach never passes."},"isReply":{"type":"boolean","description":"true: only replies and comments; false: only top-level posts."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings; every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings; posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."}},"additionalProperties":false,"description":"A group of conditions, all of which must hold: the vocabulary of a view filter, without anyOf."},"View":{"type":"object","properties":{"id":{"type":"string","description":"View id (vw_...)."},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Substring in the post text or the author's name."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of any of these keywords."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of these keywords."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of keywords in these groups."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status: open, ignored, done."},"relevant":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Only mentions scored at least this."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments; an unscored mention still passes."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never mentions carrying these tags."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made; false: only the rest."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1)."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages; an unknown language still passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never authors tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers; unknown reach never passes."},"maxFollowers":{"type":"integer","minimum":0,"description":"Only authors with at most this many followers; unknown reach never passes."},"isReply":{"type":"boolean","description":"true: only replies and comments; false: only top-level posts."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings; every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings; posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}}},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"updatedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","name","description","filter","createdAt","updatedAt"]},"MentionSpikeEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"The attention item (att_...): GET /v1/attention lists it, POST /v1/attention/{id}/dismiss puts it away."},"url":{"type":"string","description":"Where to look in the dashboard."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"name":{"type":"string","description":"The keyword as Rumoro names it: the term, or \"term (Group)\" outside the default group."},"groupId":{"type":"string","description":"Its group (grp_...)."}},"required":["id","term","kind","name","groupId"],"description":"The keyword the item is about."},"window":{"type":"object","properties":{"from":{"type":"string","description":"Start, inclusive."},"to":{"type":"string","description":"End, exclusive."}},"required":["from","to"],"description":"The stretch of time the counts cover, by match time."},"matches":{"type":"integer","minimum":0,"description":"Fresh matches in the hour: posts published at most 6 hours before they matched. Look-backs and free reviews never count."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored relevant so far."},"baseline":{"type":"object","properties":{"meanPerHour":{"type":"number","minimum":0,"description":"Fresh matches per hour over the baseline."},"stddevPerHour":{"type":"number","minimum":0,"description":"Their standard deviation."},"hours":{"type":"integer","minimum":0,"description":"Hours in the baseline: the week before the window, or since the keyword started listening."}},"required":["meanPerHour","stddevPerHour","hours"],"description":"What the keyword usually gets."}},"required":["attentionId","url","keyword","window","matches","relevant","baseline"]},"NegativeSpikeEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"The attention item (att_...): GET /v1/attention lists it, POST /v1/attention/{id}/dismiss puts it away."},"url":{"type":"string","description":"Where to look in the dashboard."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"name":{"type":"string","description":"The keyword as Rumoro names it: the term, or \"term (Group)\" outside the default group."},"groupId":{"type":"string","description":"Its group (grp_...)."}},"required":["id","term","kind","name","groupId"],"description":"The keyword the item is about."},"window":{"type":"object","properties":{"from":{"type":"string","description":"Start, inclusive."},"to":{"type":"string","description":"End, exclusive."}},"required":["from","to"],"description":"The stretch of time the counts cover, by match time."},"negative":{"type":"integer","minimum":0,"description":"Relevant matches scored negative in the window."},"relevant":{"type":"integer","minimum":0,"description":"Relevant matches in the window."},"share":{"type":"number","minimum":0,"maximum":1,"description":"negative / relevant."},"baseline":{"type":"object","properties":{"negative":{"type":"integer","minimum":0,"description":"Negative relevant matches in the 7 days before the window."},"relevant":{"type":"integer","minimum":0,"description":"Relevant matches in those 7 days."},"share":{"type":"number","minimum":0,"maximum":1,"description":"The usual negative share, smoothed so a quiet week still has one."}},"required":["negative","relevant","share"],"description":"What the keyword usually reads."}},"required":["attentionId","url","keyword","window","negative","relevant","share","baseline"]},"KeywordNoisyEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"The attention item (att_...): GET /v1/attention lists it, POST /v1/attention/{id}/dismiss puts it away."},"url":{"type":"string","description":"Where to look in the dashboard."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"name":{"type":"string","description":"The keyword as Rumoro names it: the term, or \"term (Group)\" outside the default group."},"groupId":{"type":"string","description":"Its group (grp_...)."}},"required":["id","term","kind","name","groupId"],"description":"The keyword the item is about."},"windowDays":{"type":"integer","minimum":0,"description":"The window the noise is measured over, in days (since the keyword's last change when that is inside it)."},"scored":{"type":"integer","minimum":0,"description":"Matches the classifier scored in that window."},"relevant":{"type":"integer","minimum":0,"description":"Of those, relevant."},"noiseShare":{"type":"number","minimum":0,"maximum":1,"description":"The share scored under the relevance line. Every match bills, relevant or not."}},"required":["attentionId","url","keyword","windowDays","scored","relevant","noiseShare"]},"ChannelFailingEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"The attention item (att_...): GET /v1/attention lists it, POST /v1/attention/{id}/dismiss puts it away."},"url":{"type":"string","description":"Where to look in the dashboard."},"channel":{"type":"object","properties":{"id":{"type":"string","description":"Channel id (dest_...)."},"kind":{"type":"string","enum":["slack","email","webhook","telegram"],"description":"slack, email, webhook or telegram."},"label":{"type":"string","description":"The channel's label."}},"required":["id","kind","label"],"description":"The channel whose sends fail."},"failures":{"type":"integer","minimum":0,"description":"Failed sends in a row within the last 24 hours."},"lastError":{"type":"string","nullable":true,"description":"The newest failure, as the transport reported it."},"since":{"type":"string","description":"The oldest of those failures."}},"required":["attentionId","url","channel","failures","lastError","since"]},"AttentionItem":{"type":"object","properties":{"id":{"type":"string","description":"Attention item id (att_...)."},"kind":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike: far more mentions in the last hour than the keyword usually gets. sentiment.negative_spike: the negative share of the last 24 hours jumped. keyword.noisy: most scored matches are noise. channel.failing: the channel's last sends all failed."},"status":{"type":"string","enum":["open","resolved","dismissed"],"description":"open: the condition holds. resolved: it no longer does. dismissed: a person put it away; it does not come back for the same episode."},"subject":{"type":"object","properties":{"type":{"type":"string","enum":["keyword","channel"],"description":"keyword or channel."},"id":{"type":"string","description":"The keyword (kw_...) or the channel (dest_...)."}},"required":["type","id"],"description":"What the item is about."},"title":{"type":"string","description":"One line for a person: what happened."},"openedAt":{"type":"string","description":"When the condition was first seen."},"resolvedAt":{"type":"string","nullable":true,"description":"When it no longer held; null while it does."},"dismissedAt":{"type":"string","nullable":true,"description":"When a person dismissed it; null if nobody did."},"data":{"anyOf":[{"$ref":"#/components/schemas/MentionSpikeEventData"},{"$ref":"#/components/schemas/NegativeSpikeEventData"},{"$ref":"#/components/schemas/KeywordNoisyEventData"},{"$ref":"#/components/schemas/ChannelFailingEventData"}],"description":"The facts as they stood when it opened: the same object the account event of the same name carries as `data`."}},"required":["id","kind","status","subject","title","openedAt","resolvedAt","dismissedAt","data"]},"Group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"type":"object","properties":{"context":{"type":"string","nullable":true,"description":"The group's own company description for the classifier, or null for the workspace profile."},"stats":{"type":"object","properties":{"keywords":{"type":"integer","minimum":0,"description":"Keywords in the group, muted ones included."},"active":{"type":"integer","minimum":0,"description":"Keywords in the group that are tracking (not muted)."}},"required":["keywords","active"],"description":"Computed over the group's keywords."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"updatedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["context","stats","createdAt","updatedAt"]}],"description":"The group the keyword belongs to."},"Company":{"type":"object","properties":{"name":{"type":"string","description":"Brand or company name, as the classifier should call it."},"description":{"type":"string","description":"What the company does, one paragraph."},"useCases":{"type":"array","items":{"type":"string"},"description":"What people use the product for."},"accounts":{"type":"object","properties":{"x":{"type":"string","nullable":true,"description":"X handle without the @."},"linkedin":{"type":"string","nullable":true,"description":"LinkedIn page slug or URL."}},"required":["x","linkedin"],"description":"Your own accounts, so your own posts are recognized."},"website":{"type":"string","nullable":true,"description":"The company website, as set up during onboarding."},"competitors":{"type":"array","items":{"type":"string"},"description":"Competitors by name, so the classifier reads a rival's mention as such; usually the same names as your competitor keywords."},"guidelines":{"type":"string","nullable":true,"description":"Free-text rules for the classifier: what counts as relevant for you and what never does (\"posts about our API, never job listings\"). The second biggest lever after the description."},"context":{"type":"string","description":"The text the classifier reads. Composed from the fields above unless you override it."}},"required":["name","description","useCases","accounts","website","competitors","guidelines","context"]},"Whoami":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string","description":"Workspace id (org_...)."},"name":{"type":"string","description":"The workspace name, as the dashboard shows it."}},"required":["id","name"],"description":"The workspace this credential acts on."},"auth":{"type":"object","properties":{"kind":{"type":"string","enum":["api_key","oauth","session"],"description":"How the request authenticated: an API key, an OAuth access token (MCP sign-in), or the dashboard session."},"scope":{"type":"string","enum":["read","write"],"description":"What the credential may do: read (GET only) or write."},"apiKeyId":{"type":"string","nullable":true,"description":"The key id (key_...) when authenticated with an API key; null otherwise."},"expiresAt":{"type":"string","nullable":true,"description":"When an API key stops working; null for a key that never expires, an OAuth token or a session."}},"required":["kind","scope","apiKeyId","expiresAt"],"description":"The credential."},"user":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"User id, what assigneeId and ownerId take."},"email":{"type":"string","description":"The account's email address."},"name":{"type":"string","nullable":true,"description":"The name on the account; null when they never set one."}},"required":["id","email","name"],"description":"The person behind an OAuth token or a session; null for an API key, which has no person behind it."}},"required":["workspace","auth","user"]},"Member":{"type":"object","properties":{"id":{"type":"string","description":"Membership id (mem_...), what DELETE /v1/members/{id} takes."},"userId":{"type":"string","description":"The person's user id, what assigneeId and ownerId take."},"email":{"type":"string","description":"The account's email address."},"name":{"type":"string","nullable":true,"description":"The name on the account; null when they never set one."},"role":{"type":"string","enum":["owner","admin","member"],"description":"owner: everything, billing included. admin: manages the team. member: works the feed."},"joinedAt":{"type":"string","description":"When the membership was created."}},"required":["id","userId","email","name","role","joinedAt"]},"Invitation":{"type":"object","properties":{"id":{"type":"string","description":"Invitation id (inv_...)."},"email":{"type":"string","description":"The invited address, lowercased."},"role":{"type":"string","enum":["owner","admin","member"],"description":"The role they join with."},"invitedBy":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true}},"required":["id","email","name"],"description":"Who sent it; an API key invites on behalf of the oldest owner."},"expiresAt":{"type":"string","description":"Invitations last 48 hours; an expired one is no longer listed."},"createdAt":{"type":"string","description":"When the invitation was sent."}},"required":["id","email","role","invitedBy","expiresAt","createdAt"]},"UsageSummary":{"type":"object","properties":{"balance":{"type":"object","properties":{"cents":{"type":"integer","description":"Ledger balance: every credit minus every settled debit."},"pendingCents":{"type":"integer","description":"Mentions matched since the last daily settlement, priced but not yet debited."},"effectiveCents":{"type":"integer","description":"cents minus pendingCents: what the stop rule and the keyword gate look at."},"currency":{"type":"string","enum":["USD"]}},"required":["cents","pendingCents","effectiveCents","currency"],"description":"The prepaid wallet."},"burn":{"type":"object","properties":{"perDayCents":{"type":"integer","description":"Average daily debit over the last 7 days (or since the workspace was created)."},"daysLeft":{"type":"integer","nullable":true,"minimum":0,"description":"effectiveCents divided by perDayCents; null when nothing is burning."}},"required":["perDayCents","daysLeft"],"description":"How fast the balance goes."},"keywords":{"type":"object","properties":{"active":{"type":"integer","minimum":0,"description":"Unmuted keywords, the ones charged daily."},"paused":{"type":"integer","minimum":0,"description":"Keywords the wallet paused for lack of balance; a top-up resumes them."},"capped":{"type":"integer","minimum":0,"description":"Unmuted keywords at their monthly mention cap: still charged daily, not matched until the month turns or the cap is raised."},"limit":{"type":"integer","minimum":0,"description":"How many keywords the workspace may run right now: the self-serve ceiling when the balance covers one more keyword-day, else 0."},"dayCents":{"type":"integer","description":"What one more day of the active keywords costs."}},"required":["active","paused","capped","limit","dayCents"],"description":"Keywords against the wallet."},"mentions":{"type":"object","properties":{"today":{"type":"integer","minimum":0,"description":"Matches recorded today (UTC), relevant or not: every one bills."},"last30d":{"type":"integer","minimum":0,"description":"Matches recorded in the last 30 days."}},"required":["today","last30d"],"description":"Matched mentions, the other thing that bills."},"stopped":{"type":"boolean","description":"The wallet paused tracking; a top-up that covers a day of every keyword resumes it."},"lowBalance":{"type":"boolean","description":"Running, and the effective balance is at or under 20 percent of the last credit."},"lastTopUpAt":{"type":"string","nullable":true,"description":"Newest paid top-up; null before the first."}},"required":["balance","burn","keywords","mentions","stopped","lowBalance","lastTopUpAt"]},"UsageBreakdown":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","description":"First day, YYYY-MM-DD, inclusive, UTC."},"to":{"type":"string","description":"Last day, inclusive: today for a trailing window or the running month."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."},"keywordDaysFrom":{"type":"string","nullable":true,"description":"The first day of the window with a recorded keyword count, or null when there is none. Earlier days carry keywordDays: null."}},"required":["from","to","days","keywordDaysFrom"],"description":"The window the report covers, in UTC days."},"by":{"type":"string","enum":["day","platform","keyword","group"],"description":"The dimension the rows are grouped by."},"currency":{"type":"string","enum":["USD"],"description":"Every amount is in USD cents."},"totals":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Keyword-days metered in the window."},"keywordCents":{"type":"integer","description":"The keyword-days at the keyword rate ($5 a month, 500/30 cents a day), rounded once on the total."},"matchedMentions":{"type":"integer","minimum":0,"description":"Matches recorded in the window, relevant or not."},"billableMentions":{"type":"integer","minimum":0,"description":"Of the matches billed in the window (every scored match, relevant or not), the ones in this group."},"mentionCents":{"type":"integer","description":"The billed mentions at $0.008 each, rounded once on the total."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents."},"unclassifiedMentions":{"type":"integer","minimum":0,"description":"Matched but never scored (classification failed): never charged."},"ledgerDebitCents":{"type":"integer","description":"What the ledger has debited so far for the days of the window, each debit by the day it settled. Mentions settle the morning after their day, so a window ending today lags totalCents by today's mentions (and yesterday's before the tick at 00:05 UTC); a closed month differs from totalCents only by cumulative rounding."},"unattributedBillable":{"type":"integer","minimum":0,"description":"Billed mentions whose match row is gone (deleted keyword), so no platform or keyword row can claim them. Charged all the same."}},"required":["keywordDays","keywordCents","matchedMentions","billableMentions","mentionCents","totalCents","unclassifiedMentions","ledgerDebitCents","unattributedBillable"],"description":"The whole window as one line, the same for every dimension."},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The row's key: the UTC day (YYYY-MM-DD) for by=day, the platform for by=platform, the keyword id for by=keyword, the group id for by=group."},"label":{"type":"string","description":"Readable name: the keyword term or the group name, otherwise the key."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"Keyword id (kw_...); a deleted keyword keeps its id here."},"term":{"type":"string","description":"The term as it was last metered, or as the keyword reads now."},"removed":{"type":"boolean","description":"The keyword has since been deleted. Its charges stay on the record; its mentions went with it, so its mention counts read 0."}},"required":["id","term","removed"],"description":"by=keyword only; null otherwise."},"group":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"Group id, or \"none\" for keyword-days metered before groups existed whose keyword is gone."},"name":{"type":"string","description":"The group's name as it reads now, or \"Deleted group\" / \"No group\"."},"removed":{"type":"boolean","description":"The group has since been deleted."}},"required":["id","name","removed"],"description":"by=group only; null otherwise."},"keywordDays":{"type":"integer","nullable":true,"minimum":0,"description":"Keyword-days metered in this group: the days the daily tick charged for. Null for by=platform (a keyword-day belongs to no platform) and for a day before the first recorded tick (unknown, not zero); a keyword row counts only the days on record, so before window.keywordDaysFrom it is a floor, not a zero."},"keywordCents":{"type":"integer","description":"The keyword-days at the keyword rate ($5 a month, 500/30 cents a day), rounded once on the total."},"matchedMentions":{"type":"integer","minimum":0,"description":"Matches recorded in the window, relevant or not."},"billableMentions":{"type":"integer","minimum":0,"description":"Of the matches billed in the window (every scored match, relevant or not), the ones in this group."},"mentionCents":{"type":"integer","description":"The billed mentions at $0.008 each, rounded once on the total."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents."}},"required":["key","label","keyword","group","keywordDays","keywordCents","matchedMentions","billableMentions","mentionCents","totalCents"]},"description":"by=day: chronological. by=platform and by=keyword: most expensive first, then most matched, deleted keywords included."},"total":{"type":"integer","minimum":0,"description":"Rows in the dimension before `limit` and `offset`."}},"required":["window","by","currency","totals","data","total"]},"Wallet":{"type":"object","properties":{"balanceCents":{"type":"integer","description":"Ledger balance: every credit minus every settled debit."},"pendingCents":{"type":"integer","description":"Mentions matched since the last daily settlement, priced but not yet debited."},"effectiveBalanceCents":{"type":"integer","description":"balanceCents minus pendingCents: what the stop sweep and the keyword gate look at."},"burnPerDayCents":{"type":"integer","description":"Average daily debit over the last 7 days (or since the workspace was created)."},"daysLeft":{"type":"integer","nullable":true,"minimum":0,"description":"effectiveBalanceCents divided by burnPerDayCents; null when nothing is burning."},"stopped":{"type":"boolean","description":"The wallet paused tracking; a top-up that covers a day of every keyword resumes it."},"lowBalance":{"type":"boolean","description":"Running, and the effective balance is at or under 20 percent of the last credit: the same rule as the low-balance email."},"activeKeywords":{"type":"integer","minimum":0,"description":"Unmuted keywords."},"autoMutedKeywords":{"type":"integer","minimum":0,"description":"Keywords the wallet paused; a top-up resumes them."},"nextDayCents":{"type":"integer","description":"What one more day of the running keywords costs; tracking stops when the effective balance drops under it."},"resumeCostCents":{"type":"integer","description":"What one day of every keyword (running and paused) costs; a stopped workspace resumes once the effective balance covers it."},"signupCredit":{"type":"object","nullable":true,"properties":{"amountCents":{"type":"integer","description":"Integer USD cents."},"grantedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["amountCents","grantedAt"],"description":"The welcome credit this workspace received, or null (a second workspace of the same user gets none)."},"lastTopUpAt":{"type":"string","nullable":true,"description":"Newest paid top-up; null before the first."},"billingConfigured":{"type":"boolean","description":"False when this deployment has no Polar credentials: the top-up button is hidden."},"minTopUpCents":{"type":"integer","description":"Smallest top-up the checkout accepts."},"maxTopUpCents":{"type":"integer","description":"Largest single top-up."},"defaultTopUpCents":{"type":"integer","description":"Amount prefilled in the checkout."},"currency":{"type":"string","enum":["USD"],"description":"Every amount on this page is in USD cents."},"autoRecharge":{"type":"object","properties":{"available":{"type":"boolean","description":"This deployment can charge saved cards; false hides the setting."},"enabled":{"type":"boolean","description":"Charge the saved card automatically when the balance runs low."},"thresholdCents":{"type":"integer","description":"Charge when the effective balance drops under this."},"amountCents":{"type":"integer","description":"How much to add per automatic charge (same bounds as a manual top-up)."},"lastRunAt":{"type":"string","nullable":true,"description":"Newest successful automatic charge."},"lastError":{"type":"string","nullable":true,"description":"Why the last automatic charge failed; null after a success."}},"required":["available","enabled","thresholdCents","amountCents","lastRunAt","lastError"]}},"required":["balanceCents","pendingCents","effectiveBalanceCents","burnPerDayCents","daysLeft","stopped","lowBalance","activeKeywords","autoMutedKeywords","nextDayCents","resumeCostCents","signupCredit","lastTopUpAt","billingConfigured","minTopUpCents","maxTopUpCents","defaultTopUpCents","currency","autoRecharge"]},"LedgerList":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Ledger entry id (led_...)."},"kind":{"type":"string","enum":["signup_credit","topup","refund","debit_keyword_days","debit_mentions","adjustment"],"description":"signup_credit, topup, refund, debit_keyword_days, debit_mentions or adjustment."},"amountCents":{"type":"integer","description":"Integer USD cents; credits positive, debits negative."},"day":{"type":"string","nullable":true,"description":"Debit rows: the last UTC day the row settled (YYYY-MM-DD)."},"units":{"type":"integer","nullable":true,"description":"Debit rows: cumulative units (mentions or keyword-days) settled up to this row."},"note":{"type":"string","nullable":true,"description":"Free text on credits and adjustments."},"polarOrderId":{"type":"string","nullable":true,"description":"Top-ups and refunds: the Polar order."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","kind","amountCents","day","units","note","polarOrderId","createdAt"]},"description":"Ledger entries, newest first."},"nextCursor":{"type":"string","nullable":true,"description":"Pass it back as `cursor` for the next page; null on the last."}},"required":["data","nextCursor"]},"InvoiceList":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The Polar order id; what GET /v1/billing/invoices/{id}/url takes."},"createdAt":{"type":"string","description":"When the order was placed (ISO 8601)."},"status":{"type":"string","description":"The order status as Polar reports it (paid, refunded, ...)."},"paid":{"type":"boolean","description":"Whether the order was paid."},"totalAmount":{"type":"integer","description":"What was charged, in minor units of `currency`, tax included."},"currency":{"type":"string","description":"ISO 4217 currency of the order (usd)."},"billingReason":{"type":"string","nullable":true,"description":"Why the order exists, as Polar reports it (purchase, subscription_cycle, ...); null when it does not say."}},"required":["id","createdAt","status","paid","totalAmount","currency","billingReason"]},"description":"Paid orders, newest first; empty before the first top-up."}},"required":["data"]},"Alert":{"type":"object","properties":{"id":{"type":"string","description":"Alert id (feed_...)."},"name":{"type":"string"},"enabled":{"type":"boolean"},"mode":{"type":"string","enum":["instant","hourly","daily","weekly"],"description":"instant: each matching mention as it happens. hourly: one digest each UTC hour (five minutes past, so the last mentions of the hour are scored) covering the previous full hour, nothing when that hour has no mention at or over the rule's relevance floor; Slack, Telegram and webhook channels only. daily: one digest at the scheduled local time. weekly: one digest a week, on schedule.weekday."},"filter":{"type":"object","properties":{"keywordIds":{"type":"array","items":{"type":"string"},"description":"Only these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Only keywords in these groups (grp_...): one rule per customer, say."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"description":"Only posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The rule's relevance floor. Absent, it sends relevant mentions only (scored 40 and up, the classifier's line); lower, down to 0, it also receives the matches the classifier scored as noise; higher, it hears less. Email channels keep the 40 line whatever the rule says. Unclassified mentions never pass."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. A mention without a confidence never passes."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"description":"Only these sentiments."},"intents":{"type":"array","items":{"type":"string"},"description":"At least one of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). A post with no links never passes."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made (bots, templated posts); false: only the rest. Omit for both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): [1, 2] sends the unhappy ones. Every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): [5] keeps the five star reviews out. Posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}}},"schedule":{"type":"object","nullable":true,"properties":{"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59,"default":0},"timezone":{"type":"string","minLength":1,"maxLength":64},"skipEmpty":{"type":"boolean","default":true},"weekday":{"type":"integer","minimum":0,"maximum":6,"description":"Weekly rules: the day it sends, 0 Sunday to 6 Saturday. Required for mode weekly; ignored on daily rules."}},"required":["hour","timezone"],"description":"Daily and weekly alerts only; null for instant and hourly ones."},"event":{"type":"string","description":"Event name carried in webhook payloads; the mode default unless you set one."},"channels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["slack","email","webhook","telegram"]},"label":{"type":"string"}},"required":["id","kind","label"]},"description":"Where it sends."},"stats":{"type":"object","properties":{"sentLast7d":{"type":"integer","minimum":0,"description":"Deliveries in the last 7 days, across channels."},"lastSentAt":{"type":"string","nullable":true,"description":"ISO 8601 timestamp, UTC."},"nextRunAt":{"type":"string","nullable":true,"description":"Hourly, daily and weekly alerts: the next digest; null when disabled or instant."}},"required":["sentLast7d","lastSentAt","nextRunAt"],"description":"Computed over this workspace's deliveries."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","name","enabled","mode","filter","schedule","event","channels","stats","createdAt"]},"AnalyticsSummary":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, inclusive."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, inclusive."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."},"timezone":{"type":"string","description":"IANA zone the days were cut in."}},"required":["from","to","days","timezone"],"description":"The window the report covers."},"matched":{"type":"integer","minimum":0,"description":"Every match in the window, relevant or not: the number usage counts."},"relevant":{"type":"integer","minimum":0,"description":"Matches scored at or above the relevance threshold."},"posts":{"type":"integer","minimum":0,"description":"Distinct posts behind the matches: a post matching two keywords is two matches, one post."},"people":{"type":"integer","minimum":0,"description":"Distinct authors behind the matches."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0,"description":"Classified positive."},"neutral":{"type":"integer","minimum":0,"description":"Classified neutral."},"negative":{"type":"integer","minimum":0,"description":"Classified negative."},"unclassified":{"type":"integer","minimum":0,"description":"Not scored: still queued, or the classifier failed on it."}},"required":["positive","neutral","negative","unclassified"],"description":"Matched mentions by classifier sentiment."},"buyIntent":{"type":"integer","minimum":0,"description":"Matches carrying the buy_intent intent."},"questions":{"type":"integer","minimum":0,"description":"Matches carrying the question intent."},"reach":{"type":"object","properties":{"followers":{"type":"integer","minimum":0,"description":"Followers summed over the distinct authors whose count is known: an estimate of the feeds the posts landed in."},"people":{"type":"integer","minimum":0,"description":"How many of `people` have a known follower count."}},"required":["followers","people"],"description":"Estimated reach."},"triage":{"type":"object","properties":{"open":{"type":"integer","minimum":0,"description":"Status open."},"ignored":{"type":"integer","minimum":0,"description":"Status ignored."},"done":{"type":"integer","minimum":0,"description":"Status done."},"waiting":{"type":"integer","minimum":0,"description":"Relevant, still open, and matched more than 24 hours ago."},"handledRate":{"type":"number","nullable":true,"description":"done divided by relevant, 0 to 1; null when nothing was relevant."},"medianTimeToDoneMs":{"type":"number","nullable":true,"description":"Median milliseconds from match to done; null when nothing was done."}},"required":["open","ignored","done","waiting","handledRate","medianTimeToDoneMs"],"description":"Where the matches stand in your inbox."},"previous":{"type":"object","nullable":true,"properties":{"matched":{"type":"integer","minimum":0,"description":"Every match in the window, relevant or not: the number usage counts."},"relevant":{"type":"integer","minimum":0,"description":"Matches scored at or above the relevance threshold."},"posts":{"type":"integer","minimum":0,"description":"Distinct posts behind the matches: a post matching two keywords is two matches, one post."},"people":{"type":"integer","minimum":0,"description":"Distinct authors behind the matches."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0,"description":"Classified positive."},"neutral":{"type":"integer","minimum":0,"description":"Classified neutral."},"negative":{"type":"integer","minimum":0,"description":"Classified negative."},"unclassified":{"type":"integer","minimum":0,"description":"Not scored: still queued, or the classifier failed on it."}},"required":["positive","neutral","negative","unclassified"],"description":"Matched mentions by classifier sentiment."},"buyIntent":{"type":"integer","minimum":0,"description":"Matches carrying the buy_intent intent."},"questions":{"type":"integer","minimum":0,"description":"Matches carrying the question intent."},"reach":{"type":"object","properties":{"followers":{"type":"integer","minimum":0,"description":"Followers summed over the distinct authors whose count is known: an estimate of the feeds the posts landed in."},"people":{"type":"integer","minimum":0,"description":"How many of `people` have a known follower count."}},"required":["followers","people"],"description":"Estimated reach."},"triage":{"type":"object","properties":{"open":{"type":"integer","minimum":0,"description":"Status open."},"ignored":{"type":"integer","minimum":0,"description":"Status ignored."},"done":{"type":"integer","minimum":0,"description":"Status done."},"waiting":{"type":"integer","minimum":0,"description":"Relevant, still open, and matched more than 24 hours ago."},"handledRate":{"type":"number","nullable":true,"description":"done divided by relevant, 0 to 1; null when nothing was relevant."},"medianTimeToDoneMs":{"type":"number","nullable":true,"description":"Median milliseconds from match to done; null when nothing was done."}},"required":["open","ignored","done","waiting","handledRate","medianTimeToDoneMs"],"description":"Where the matches stand in your inbox."}},"required":["matched","relevant","posts","people","sentiment","buyIntent","questions","reach","triage"],"description":"The same counts over the period of the same length right before the window; null unless compare=true."}},"required":["window","matched","relevant","posts","people","sentiment","buyIntent","questions","reach","triage","previous"]},"AnalyticsSeries":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, inclusive."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, inclusive."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."},"timezone":{"type":"string","description":"IANA zone the days were cut in."},"bucket":{"type":"string","enum":["hour","day","week","month"],"description":"Point granularity used: hour, day, week (Monday to Sunday) or month."}},"required":["from","to","days","timezone","bucket"],"description":"The window the report covers."},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Platform name, keyword id, sentiment (positive, neutral, negative, unclassified), \"total\" for the unsplit series, or \"other\" for the keys beyond the top 20."},"label":{"type":"string","description":"Readable name: the platform, the keyword term, the sentiment, \"Total\" or \"Other\"."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The group the keyword is in."}]}},"required":["id","term","kind","group"],"description":"Set when split by keyword; null otherwise."},"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"The bucket start in `timezone`: the day (YYYY-MM-DD), the Monday of the week, the first of the month, or the hour as YYYY-MM-DDTHH:00."},"matched":{"type":"integer","minimum":0,"description":"Every match published in the bucket."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored at or above the relevance threshold."},"positive":{"type":"integer","minimum":0,"description":"Classified positive."},"neutral":{"type":"integer","minimum":0,"description":"Classified neutral."},"negative":{"type":"integer","minimum":0,"description":"Classified negative."},"unclassified":{"type":"integer","minimum":0,"description":"Not scored: still queued, or the classifier failed on it."}},"required":["date","matched","relevant","positive","neutral","negative","unclassified"]},"description":"One point per bucket across the window, oldest first, zero-filled."}},"required":["key","label","keyword","points"]},"description":"One item per series, most matched first; a single \"total\" item when not split."},"previous":{"type":"array","nullable":true,"items":{"type":"object","properties":{"key":{"type":"string","description":"Platform name, keyword id, sentiment (positive, neutral, negative, unclassified), \"total\" for the unsplit series, or \"other\" for the keys beyond the top 20."},"label":{"type":"string","description":"Readable name: the platform, the keyword term, the sentiment, \"Total\" or \"Other\"."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The group the keyword is in."}]}},"required":["id","term","kind","group"],"description":"Set when split by keyword; null otherwise."},"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"The bucket start in `timezone`: the day (YYYY-MM-DD), the Monday of the week, the first of the month, or the hour as YYYY-MM-DDTHH:00."},"matched":{"type":"integer","minimum":0,"description":"Every match published in the bucket."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored at or above the relevance threshold."},"positive":{"type":"integer","minimum":0,"description":"Classified positive."},"neutral":{"type":"integer","minimum":0,"description":"Classified neutral."},"negative":{"type":"integer","minimum":0,"description":"Classified negative."},"unclassified":{"type":"integer","minimum":0,"description":"Not scored: still queued, or the classifier failed on it."}},"required":["date","matched","relevant","positive","neutral","negative","unclassified"]},"description":"One point per bucket across the window, oldest first, zero-filled."}},"required":["key","label","keyword","points"]},"description":"The same items over the period right before the window, in the same order, points aligned by index with `data` (the last bucket may be missing when weeks split differently); null unless compare=true."}},"required":["window","data","previous"]},"AnalyticsBreakdown":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, inclusive."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, inclusive."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."},"timezone":{"type":"string","description":"IANA zone the days were cut in."}},"required":["from","to","days","timezone"],"description":"The window the report covers."},"by":{"type":"string","enum":["platform","keyword","sentiment","intent","status","hour","person","language"],"description":"The dimension the rows are grouped by."},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The group: platform name, keyword id, sentiment, intent, status, \"weekday-hour\" for by=hour, or an opaque person key."},"label":{"type":"string","description":"Readable name: the keyword term, the person name, otherwise the key."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The group the keyword is in."}]}},"required":["id","term","kind","group"],"description":"by=keyword only; null otherwise."},"person":{"type":"object","nullable":true,"properties":{"id":{"type":"string","nullable":true,"description":"Person id (aut_...); null for posts ingested before people were linked."},"name":{"type":"string","nullable":true,"description":"Display name as the platform shows it."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"url":{"type":"string","nullable":true,"description":"Profile URL."},"avatarUrl":{"type":"string","nullable":true,"description":"Avatar image URL, when the platform gave one."},"followers":{"type":"integer","nullable":true,"minimum":0,"description":"From the audience profile; null when unknown."}},"required":["id","name","platform","url","avatarUrl","followers"],"description":"by=person only; null otherwise."},"slot":{"type":"object","nullable":true,"properties":{"weekday":{"type":"integer","minimum":0,"maximum":6,"description":"0 = Sunday through 6 = Saturday."},"hour":{"type":"integer","minimum":0,"maximum":23,"description":"Hour of day, 0 to 23."}},"required":["weekday","hour"],"description":"by=hour only: the weekday and hour of day in `timezone`; null otherwise."},"matched":{"type":"integer","minimum":0,"description":"Matches in the group."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored at or above the relevance threshold."},"share":{"type":"number","description":"Percent of the window's matched mentions in this group, one decimal. Intents overlap, so their shares can add up past 100."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0,"description":"Classified positive."},"neutral":{"type":"integer","minimum":0,"description":"Classified neutral."},"negative":{"type":"integer","minimum":0,"description":"Classified negative."},"unclassified":{"type":"integer","minimum":0,"description":"Not scored: still queued, or the classifier failed on it."}},"required":["positive","neutral","negative","unclassified"],"description":"Matched mentions by classifier sentiment."},"previous":{"type":"object","nullable":true,"properties":{"matched":{"type":"integer","minimum":0,"description":"Matches in the group then."},"relevant":{"type":"integer","minimum":0,"description":"Relevant matches in the group then."}},"required":["matched","relevant"],"description":"The same group over the period right before the window; null unless compare=true."}},"required":["key","label","keyword","person","slot","matched","relevant","share","sentiment","previous"]},"description":"Most matched first, at most 50 groups. by=hour is chronological and unlimited (168 cells at most)."}},"required":["window","by","data"]},"ShareOfVoice":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, inclusive."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, inclusive."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."},"timezone":{"type":"string","description":"IANA zone the days were cut in."}},"required":["from","to","days","timezone"],"description":"The window the report covers."},"data":{"type":"array","items":{"type":"object","properties":{"keyword":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string","description":"The tracked term."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The group the keyword is in."}]}},"required":["id","term","kind","group"],"description":"The keyword this row is about."},"matched":{"type":"integer","minimum":0,"description":"Matches of this keyword in the window."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored at or above the relevance threshold."},"negative":{"type":"integer","minimum":0,"description":"Of those, classified negative."},"buyIntent":{"type":"integer","minimum":0,"description":"Of those, carrying the buy_intent intent."},"share":{"type":"number","nullable":true,"description":"Percent of brand plus competitor matches, one decimal; null for topics, which stay out of the split."},"previous":{"type":"object","nullable":true,"properties":{"matched":{"type":"integer","minimum":0,"description":"Matches of this keyword then."}},"required":["matched"],"description":"The same keyword over the period right before the window; null unless compare=true."}},"required":["keyword","matched","relevant","negative","buyIntent","share","previous"]},"description":"Every keyword matched in the window, most matched first."}},"required":["window","data"]},"ReviewsReport":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, inclusive."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, inclusive."},"days":{"type":"integer","minimum":0,"description":"Length of the window in days."},"timezone":{"type":"string","description":"IANA zone the days were cut in."},"bucket":{"type":"string","enum":["day","week"],"description":"How the page series are cut: day up to 90 days, else week, unless asked."}},"required":["from","to","days","timezone","bucket"],"description":"The window the report covers."},"totals":{"type":"object","properties":{"reviews":{"type":"integer","minimum":0,"description":"Reviews published in the window; a review matched by two keywords counts once."},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"Average stars, one decimal; null with no reviews."},"distribution":{"type":"object","properties":{"1":{"type":"integer","minimum":0},"2":{"type":"integer","minimum":0},"3":{"type":"integer","minimum":0},"4":{"type":"integer","minimum":0},"5":{"type":"integer","minimum":0}},"required":["1","2","3","4","5"],"description":"Reviews per star rating."},"responded":{"type":"integer","minimum":0,"description":"Reviews carrying the owner's or developer's reply (the App Store's feed has none)."},"openNegative":{"type":"integer","minimum":0,"description":"1 and 2 star reviews nobody has marked done or ignored yet."}},"required":["reviews","averageRating","distribution","responded","openNegative"]},"tags":{"type":"array","items":{"type":"object","properties":{"tag":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["tag","count"]},"description":"Intent and topic tags on the 1 and 2 star reviews, most frequent first: what the unhappy ones are about."},"pages":{"type":"array","items":{"type":"object","properties":{"reviews":{"type":"integer","minimum":0,"description":"Reviews published in the window; a review matched by two keywords counts once."},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"Average stars, one decimal; null with no reviews."},"distribution":{"type":"object","properties":{"1":{"type":"integer","minimum":0},"2":{"type":"integer","minimum":0},"3":{"type":"integer","minimum":0},"4":{"type":"integer","minimum":0},"5":{"type":"integer","minimum":0}},"required":["1","2","3","4","5"],"description":"Reviews per star rating."},"responded":{"type":"integer","minimum":0,"description":"Reviews carrying the owner's or developer's reply (the App Store's feed has none)."},"openNegative":{"type":"integer","minimum":0,"description":"1 and 2 star reviews nobody has marked done or ignored yet."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."},"id":{"type":"string","description":"The page's id: app id, package name, Trustpilot domain, Place ID or cid."},"url":{"type":"string","description":"The review page."},"series":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"Bucket start, YYYY-MM-DD."},"reviews":{"type":"integer","minimum":0},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"Average stars, one decimal; null with no reviews."}},"required":["date","reviews","averageRating"]},"description":"Reviews and average stars per bucket, oldest first, every bucket present."},"previous":{"type":"object","nullable":true,"properties":{"reviews":{"type":"integer","minimum":0},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"Average stars, one decimal; null with no reviews."}},"required":["reviews","averageRating"],"description":"The period of the same length right before the window, with compare=true; else null."}},"required":["reviews","averageRating","distribution","responded","openNegative","platform","id","url","series","previous"]},"description":"One row per review page with reviews in the window, most reviewed first."},"previous":{"type":"object","nullable":true,"properties":{"reviews":{"type":"integer","minimum":0,"description":"Reviews published in the window; a review matched by two keywords counts once."},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"Average stars, one decimal; null with no reviews."},"distribution":{"type":"object","properties":{"1":{"type":"integer","minimum":0},"2":{"type":"integer","minimum":0},"3":{"type":"integer","minimum":0},"4":{"type":"integer","minimum":0},"5":{"type":"integer","minimum":0}},"required":["1","2","3","4","5"],"description":"Reviews per star rating."},"responded":{"type":"integer","minimum":0,"description":"Reviews carrying the owner's or developer's reply (the App Store's feed has none)."},"openNegative":{"type":"integer","minimum":0,"description":"1 and 2 star reviews nobody has marked done or ignored yet."}},"required":["reviews","averageRating","distribution","responded","openNegative"],"description":"Totals for the period right before the window, with compare=true; else null."}},"required":["window","totals","tags","pages","previous"]},"SlackChannel":{"type":"object","properties":{"id":{"type":"string","description":"Channel id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Alerts sending to this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"Of those, enabled ones; 0 means the channel receives nothing right now."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Newest delivery attempt, successful or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries in the last 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Computed over this workspace's deliveries."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"kind":{"type":"string","enum":["slack"]},"config":{"type":"object","properties":{"channelId":{"type":"string","description":"Slack channel id."},"channelName":{"type":"string","description":"Slack channel name, without the #."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike: far more mentions in the last hour than the keyword usually gets. sentiment.negative_spike: the negative share of the last 24 hours jumped. keyword.noisy: most scored matches are noise. channel.failing: the channel's last sends all failed."},"description":"The attention events this channel receives on its own, no rule involved: one short message when an item opens (GET /v1/attention). Empty when it receives none."}},"required":["channelId","channelName","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"EmailChannel":{"type":"object","properties":{"id":{"type":"string","description":"Channel id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Alerts sending to this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"Of those, enabled ones; 0 means the channel receives nothing right now."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Newest delivery attempt, successful or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries in the last 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Computed over this workspace's deliveries."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"kind":{"type":"string","enum":["email"]},"config":{"type":"object","properties":{"recipients":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"confirmedAt":{"type":"string","nullable":true,"description":"Null until the address confirmed through its link; unconfirmed addresses receive nothing."}},"required":["email","confirmedAt"]},"description":"Every address on the list and whether it confirmed."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike: far more mentions in the last hour than the keyword usually gets. sentiment.negative_spike: the negative share of the last 24 hours jumped. keyword.noisy: most scored matches are noise. channel.failing: the channel's last sends all failed."},"description":"The attention events this channel receives on its own, no rule involved: one short message when an item opens (GET /v1/attention). Empty when it receives none."}},"required":["recipients","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"WebhookChannel":{"type":"object","properties":{"id":{"type":"string","description":"Channel id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Alerts sending to this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"Of those, enabled ones; 0 means the channel receives nothing right now."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Newest delivery attempt, successful or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries in the last 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Computed over this workspace's deliveries."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"kind":{"type":"string","enum":["webhook"]},"config":{"type":"object","properties":{"url":{"type":"string","description":"Where the signed POSTs go."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra request headers you configured."},"events":{"type":"array","items":{"type":"string","enum":["keyword.capped","keyword.paused_for_balance","keyword.resumed","wallet.low","wallet.paused","wallet.resumed","mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"keyword.capped: a keyword reached its monthly mention cap and stopped matching. keyword.paused_for_balance: the wallet ran out and paused it. keyword.resumed: it listens again (reason says why). wallet.low: the effective balance fell to 20% of the last credit (once per credit). wallet.paused: the wallet paused every keyword. wallet.resumed: a credit brought them back. The attention events, sent once when an item opens (GET /v1/attention): mention.spike: a keyword got far more mentions in the last hour than it usually does. sentiment.negative_spike: its negative share of the last 24 hours jumped. keyword.noisy: most of its scored matches are noise. channel.failing: a channel's last sends all failed."},"description":"The account events this endpoint receives on its own, no rule involved: keyword and wallet state changes and the attention events. Empty when it receives none; mention and digest deliveries come through rules as before."},"secret":{"type":"string","description":"Only on creation and rotation. Signs every request: X-Mentions-Signature-V2 is v2= plus the hex HMAC-SHA256 of \"<X-Mentions-Timestamp>.<raw body>\" (reject a timestamp older than a few minutes); X-Mentions-Signature, the hex HMAC-SHA256 of the raw body alone, stays for older verifiers."}},"required":["url","headers","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"TelegramChannel":{"type":"object","properties":{"id":{"type":"string","description":"Channel id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Alerts sending to this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"Of those, enabled ones; 0 means the channel receives nothing right now."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Newest delivery attempt, successful or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries in the last 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Computed over this workspace's deliveries."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"kind":{"type":"string","enum":["telegram"]},"config":{"type":"object","properties":{"chatId":{"type":"string","description":"Telegram chat id."},"chatType":{"type":"string","enum":["private","group","supergroup","channel"]},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike: far more mentions in the last hour than the keyword usually gets. sentiment.negative_spike: the negative share of the last 24 hours jumped. keyword.noisy: most scored matches are noise. channel.failing: the channel's last sends all failed."},"description":"The attention events this channel receives on its own, no rule involved: one short message when an item opens (GET /v1/attention). Empty when it receives none."}},"required":["chatId","chatType","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"Channel":{"oneOf":[{"$ref":"#/components/schemas/SlackChannel"},{"$ref":"#/components/schemas/EmailChannel"},{"$ref":"#/components/schemas/WebhookChannel"},{"$ref":"#/components/schemas/TelegramChannel"}],"discriminator":{"propertyName":"kind","mapping":{"slack":"#/components/schemas/SlackChannel","email":"#/components/schemas/EmailChannel","webhook":"#/components/schemas/WebhookChannel","telegram":"#/components/schemas/TelegramChannel"}}},"CreateSlackChannel":{"type":"object","properties":{"kind":{"type":"string","enum":["slack"]},"channelId":{"type":"string","minLength":1,"maxLength":40,"description":"A Slack channel id from the connected workspace."},"channelName":{"type":"string","minLength":1,"maxLength":90,"description":"The channel name, for the label."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike: far more mentions in the last hour than the keyword usually gets. sentiment.negative_spike: the negative share of the last 24 hours jumped. keyword.noisy: most scored matches are noise. channel.failing: the channel's last sends all failed."},"maxItems":4,"description":"Attention events to receive here, on top of whatever rules send. Omit for none."}},"required":["kind","channelId","channelName"]},"CreateEmailChannel":{"type":"object","properties":{"kind":{"type":"string","enum":["email"]},"emails":{"type":"array","items":{"type":"string","format":"email"},"minItems":1,"maxItems":20,"description":"Each address gets a confirmation link; workspace members are confirmed on sight."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike: far more mentions in the last hour than the keyword usually gets. sentiment.negative_spike: the negative share of the last 24 hours jumped. keyword.noisy: most scored matches are noise. channel.failing: the channel's last sends all failed."},"maxItems":4,"description":"Attention events to receive here, on top of whatever rules send. Omit for none."}},"required":["kind","emails"]},"CreateWebhookChannel":{"type":"object","properties":{"kind":{"type":"string","enum":["webhook"]},"url":{"type":"string","format":"uri","description":"Where the signed POSTs go. https in production."},"label":{"type":"string","maxLength":80,"description":"A name for the channel; the host of the URL when omitted."},"headers":{"type":"object","additionalProperties":{"type":"string","maxLength":1024},"description":"Extra request headers to send, for your own auth."},"events":{"type":"array","items":{"type":"string","enum":["keyword.capped","keyword.paused_for_balance","keyword.resumed","wallet.low","wallet.paused","wallet.resumed","mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"keyword.capped: a keyword reached its monthly mention cap and stopped matching. keyword.paused_for_balance: the wallet ran out and paused it. keyword.resumed: it listens again (reason says why). wallet.low: the effective balance fell to 20% of the last credit (once per credit). wallet.paused: the wallet paused every keyword. wallet.resumed: a credit brought them back. The attention events, sent once when an item opens (GET /v1/attention): mention.spike: a keyword got far more mentions in the last hour than it usually does. sentiment.negative_spike: its negative share of the last 24 hours jumped. keyword.noisy: most of its scored matches are noise. channel.failing: a channel's last sends all failed."},"maxItems":10,"description":"Account events to receive at this endpoint (keyword and wallet state changes, attention events), on top of whatever rules send here. Omit for none."}},"required":["kind","url"]}},"parameters":{}},"paths":{"/v1/health":{"get":{"operationId":"getHealth","tags":["System"],"responses":{"200":{"description":"API is up","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/keywords":{"post":{"operationId":"createKeyword","summary":"Track a keyword","description":"Start tracking a word or phrase. Matching, classification and delivery begin on the next poll. A funded workspace tracks up to 500 keywords; each costs $5 per month, deducted daily from the balance. `matching` narrows what the term matches (required and excluded terms, excluded authors, case) before a mention is stored, so a rejected post is never billed; `context` is a sentence the classifier reads for this keyword only. `cap` puts a monthly ceiling on its matched mentions: at the cap it stops matching until the first of the next month (UTC) or until the cap is raised, while its daily keyword charge continues.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"term":{"type":"string","minLength":2,"maxLength":80,"description":"The word or phrase to track, matched case-insensitively as a phrase."},"kind":{"type":"string","enum":["brand","competitor","topic"],"default":"brand","description":"brand: your own names. competitor: theirs. topic: the space. Drives share of voice and segments."},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Platforms to search the term on; omit or null for every platform. [] searches it nowhere: a keyword that only collects reviews, which then needs reviewSources."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"A sentence the classifier reads for this keyword only, on top of the company profile or the group's own description (at most 300 characters): what the term means here, what to ignore. \"Arc is our browser; ignore the geometry word.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"The post must ALSO contain these terms, any one of them or all of them per requiredMode. Empty: no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any: at least one required term must appear. all: every one must."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"A post containing any of these is dropped. A `*` at the start or the end of an entry is a wildcard (beta.* matches beta.0.1; *bot matches nightlybot)."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Posts by these authors are dropped: profile or post links, @handles, u/names, Bluesky DIDs or display names, stored in canonical form like an alert's muted list."},"caseSensitive":{"type":"boolean","description":"true: the term must appear in the case it was typed (RAG, never rag). Default false."}},"description":"Omitted fields are untouched; an empty list clears one."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"Matched mentions allowed per calendar month (UTC). Every match counts, relevant or not, the look-back a new keyword gets included, because every match bills."}},"required":["mentions"],"description":"A monthly mention cap; omit or null for none."},"groupId":{"type":"string","minLength":1,"description":"The group to track it in (grp_...); omit for the workspace's default group. A term may be tracked once per group."},"reviewSources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"The review page's link: an App Store or Google Play app (https://apps.apple.com/us/app/notion/id1232780281, https://play.google.com/store/apps/details?id=notion.id), a Trustpilot page (https://www.trustpilot.com/review/notion.so) or a Google Maps place (its full link, or a maps.app.goo.gl share link). Or give platform and id."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."},"id":{"type":"string","minLength":1,"maxLength":200,"description":"The id on the platform: the digits after \"id\" on the App Store, the package name on Google Play, the company's domain on Trustpilot (notion.so), a Place ID (ChIJ...) on Google Maps."},"countries":{"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"},"minItems":1,"maxItems":20,"description":"App Store and Google Play only: storefronts to read, two-letter codes, at most 20. Default: the one in the link, else us. Each is one more poll a day; the same review seen in two storefronts is one mention. Trustpilot and Google Maps have one page for everyone and take none."},"language":{"type":"string","minLength":2,"maxLength":10,"description":"Google Play only: the language of the reviews to read (en, es, de, pt-BR); Google Play answers one language at a time. Default: the link's hl, else en."}},"description":"A review page whose reviews become this keyword's mentions: its link, or the platform and the id."},"maxItems":10,"description":"Review pages this keyword collects, at most 10: App Store and Google Play apps, Trustpilot pages, Google Maps places. Every new review of one is a mention of the keyword, whatever its text says. Polled once a day (per country on the app stores). A newly connected page brings its last 30 days, the newest 100 reviews (per country), free and never sent as instant alerts; after that each review bills like any mention."}},"required":["term"]}}}},"responses":{"201":{"description":"The created keyword","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Not enough balance for one more keyword-day (insufficient_balance), or the 500-keyword ceiling is reached (keyword_limit_reached)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A keyword with the same normalized term already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listKeywords","summary":"List keywords","description":"The keywords of the workspace with their match stats and poll health. Without parameters: every keyword, newest first. `q` searches the term and the context; `kind`, `status` and `platform` narrow the list; `sort` orders it; `limit` and `offset` page it. `total` counts the keywords that matched before paging.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Text to find in the term or in the keyword's context, case-insensitive."},"required":false,"description":"Text to find in the term or in the keyword's context, case-insensitive.","name":"q","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only keywords in any of these groups (grp_...). Repeatable, or comma-separated."},"required":false,"description":"Only keywords in any of these groups (grp_...). Repeatable, or comma-separated.","name":"groupId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only these kinds: brand, competitor, topic. Repeatable, or comma-separated."},"required":false,"description":"Only these kinds: brand, competitor, topic. Repeatable, or comma-separated.","name":"kind","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["active","muted","paused","noisy","capped"],"description":"active: tracking. muted: switched off by a person. paused: switched off by the wallet for lack of balance. noisy: switched off by the noise brake, mostly irrelevant matches on a workspace running on its welcome credit. capped: at its monthly mention cap until the month turns."},"maxItems":4,"description":"Only keywords in these states: active, muted, paused, capped. Repeatable, or comma-separated."},"required":false,"description":"Only keywords in these states: active, muted, paused, capped. Repeatable, or comma-separated.","name":"status","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only keywords tracked on any of these platforms: its term searched there (every platform when its platforms are null), or for appstore and googleplay, an app of that store among its reviewSources. Repeatable, or comma-separated."},"required":false,"description":"Only keywords tracked on any of these platforms: its term searched there (every platform when its platforms are null), or for appstore and googleplay, an app of that store among its reviewSources. Repeatable, or comma-separated.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["newest","oldest","term","mentions","relevant","recent","lastMention"],"default":"newest","description":"newest: created most recently first. oldest: the reverse. term: A to Z. mentions: most matches first. relevant: most relevant matches first. recent: most matches in the last 7 days first. lastMention: newest matched post first, keywords with none last."},"required":false,"description":"newest: created most recently first. oldest: the reverse. term: A to Z. mentions: most matches first. relevant: most relevant matches first. recent: most matches in the last 7 days first. lastMention: newest matched post first, keywords with none last.","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"description":"Page size, 1 to 500. Omit for every keyword after `offset`."},"required":false,"description":"Page size, 1 to 500. Omit for every keyword after `offset`.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"default":0,"description":"Skip this many keywords."},"required":false,"description":"Skip this many keywords.","name":"offset","in":"query"}],"responses":{"200":{"description":"The matching keywords and how many there are","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Keyword id (kw_...)."},"term":{"type":"string"},"kind":{"type":"string","enum":["brand","competitor","topic"]},"muted":{"type":"boolean","description":"Not polled or matched. Paused by you, by the wallet (see pausedForBalance) or by the noise brake (see pausedForNoise). A keyword at its mention cap is not muted (see pausedForCap)."},"pausedForBalance":{"type":"boolean","description":"Muted by the wallet for lack of balance; a top-up resumes it, unmuting by hand needs balance too."},"pausedForNoise":{"type":"boolean","description":"Muted by the noise brake: on a workspace running on its welcome credit, at least 20 of its matches were scored and under 30% were relevant. A change of its required or excluded terms, platforms or context resumes it (when the balance covers another day), and so does unmuting; a top-up does not."},"pausedForCap":{"type":"boolean","description":"At its monthly mention cap: not matched until the first of next month (UTC) or until the cap is raised. Not muted: it keeps its place and its daily keyword charge."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"Matched mentions allowed per calendar month (UTC). Every match counts, relevant or not, the look-back a new keyword gets included, because every match bills."},"welcome":{"type":"boolean","description":"Set by Rumoro, not you: a workspace on its welcome credit collects at most 200 mentions a keyword a month. The first top-up removes it."},"own":{"type":"integer","nullable":true,"description":"Your own cap. With welcome true, the cap the keyword gets back at the first top-up (null for none); otherwise the same as mentions. Sending mentions: 200 back while welcome is true changes nothing."}},"required":["mentions","welcome","own"],"description":"The monthly mention cap, or null for none."},"group":{"$ref":"#/components/schemas/GroupRef"},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Platforms the term is searched on; null means every platform, [] none (the keyword only collects reviews)."},"reviewSources":{"type":"array","items":{"$ref":"#/components/schemas/ReviewSource"},"description":"Where this keyword collects reviews from (App Store and Google Play apps, Trustpilot pages, Google Maps places); empty for none."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"A sentence the classifier reads for this keyword only, on top of the company profile or the group's own description (at most 300 characters): what the term means here, what to ignore. \"Arc is our browser; ignore the geometry word.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"The post must ALSO contain these terms, any one of them or all of them per requiredMode. Empty: no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any: at least one required term must appear. all: every one must."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"A post containing any of these is dropped. A `*` at the start or the end of an entry is a wildcard (beta.* matches beta.0.1; *bot matches nightlybot)."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Posts by these authors are dropped: profile or post links, @handles, u/names, Bluesky DIDs or display names, stored in canonical form like an alert's muted list."},"caseSensitive":{"type":"boolean","description":"true: the term must appear in the case it was typed (RAG, never rag). Default false."}},"required":["requiredTerms","requiredMode","excludedTerms","excludedAuthors","caseSensitive"],"description":"Matching rules applied before a mention is stored; a rejected post is never billed."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"Every match ever, relevant or not: the number billing counts."},"relevant":{"type":"integer","minimum":0,"description":"Matches scored at or above the relevance threshold."},"last7d":{"type":"integer","minimum":0,"description":"Matches published in the last 7 days."},"thisMonth":{"type":"integer","minimum":0,"description":"Matches recorded this calendar month (UTC), the count a cap compares against."},"lastMentionAt":{"type":"string","nullable":true,"description":"Newest matched post; null until the first one."},"feedback":{"type":"object","properties":{"relevant":{"type":"integer","minimum":0,"description":"Mentions a person marked relevant."},"notRelevant":{"type":"integer","minimum":0,"description":"Mentions a person marked not relevant: the noise the classifier let through."}},"required":["relevant","notRelevant"],"description":"Your verdicts on this keyword's mentions (PATCH /v1/mentions/{id} relevant)."},"noise":{"type":"object","properties":{"scored":{"type":"integer","minimum":0,"description":"Matches of the last 14 days (by match time) the classifier has scored."},"relevant":{"type":"integer","minimum":0,"description":"Of those, the ones scored relevant."},"noisy":{"type":"boolean","description":"At least 20 scored matches in the last 14 days and under 30% of them relevant: tighten the keyword with required terms, excluded terms or context. Every match bills, relevant or not."}},"required":["scored","relevant","noisy"],"description":"Relevance over the last 14 days of scored matches, so a keyword tightened today stops being flagged within two weeks."},"health":{"type":"string","enum":["healthy","noisy","quiet","capped","paused","new"],"description":"The keyword's health over the same 14 days as `noise`, by the rule GET /v1/keywords/{id}/health applies to its own window: paused (muted), capped (at its mention cap), noisy (20 or more scored matches, under 30% relevant), new (under 7 days old and not noisy, or changed in the last 7 days with under 20 scored matches since), quiet (7 days or older, nothing relevant), else healthy. Judged on the matches since the keyword's last change to its matching rules, platforms or context (or its unmute) when that is inside the 14 days, so a keyword tightened today is not flagged on the noise the change removed; `noise` itself keeps the whole 14 days. Always 14 days, while the endpoint reads 30 by default, so the two can differ for the same keyword. The health endpoint says why and what to change."},"cost":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Days this month the keyword was charged for: unmuted at the daily tick. A keyword created today reads 0 until tomorrow's tick."},"keywordCents":{"type":"integer","description":"Those days at the keyword rate ($5 a month, 500/30 cents a day), rounded once on the total."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed this month, counted when they were scored (the clock the ledger settles by), so it can trail thisMonth by the matches still being scored and never counts one that failed to score."},"mentionCents":{"type":"integer","description":"Those matches at $0.008 each, rounded once on the total."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents: what this keyword has cost this month, in USD cents."}},"required":["keywordDays","keywordCents","billableMentions","mentionCents","totalCents"],"description":"What this keyword has cost this calendar month (UTC) at list price: exactly its row in GET /v1/usage/breakdown?month=<this month> (same tables, same rounding). The wallet's ledger, which settles once a day, is what can differ from these list-price numbers, and only by cumulative rounding."}},"required":["mentions","relevant","last7d","thisMonth","lastMentionAt","feedback","noise","health","cost"],"description":"Computed over this workspace's matches."},"polling":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"lastPolledAt":{"type":"string","nullable":true,"description":"Newest poll of this platform for the term; null until the first one."},"emptyPolls":{"type":"integer","description":"Consecutive polls that found nothing new; the scheduler slows down as it grows."}},"required":["platform","lastPolledAt","emptyPolls"]},"description":"Poll health per platform polled on a schedule. Live feeds (Bluesky) have no entry."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","term","kind","muted","pausedForBalance","pausedForNoise","pausedForCap","cap","group","platforms","reviewSources","context","matching","stats","polling","createdAt"]}},"total":{"type":"integer","minimum":0,"description":"Keywords matching the filters, before `limit` and `offset`."}},"required":["data","total"]}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/keywords/{id}":{"get":{"operationId":"getKeyword","summary":"Get a keyword","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Keyword id (kw_...).","example":"kw_abc123"},"required":true,"description":"Keyword id (kw_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The keyword","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateKeyword","summary":"Update a keyword","description":"Mute or unmute it, reclassify it (`kind`), change the platforms it is tracked on, its classifier `context`, its `matching` rules (each rule field optional; an empty list clears one), or its monthly mention `cap` (null removes it; a cap above this month's count resumes a capped keyword at once). Rules apply to new mentions from the next poll; stored mentions are untouched.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Keyword id (kw_...).","example":"kw_abc123"},"required":true,"description":"Keyword id (kw_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"Reclassify it as brand, competitor or topic."},"muted":{"type":"boolean","description":"A muted keyword stops polling and matching; its mentions stay."},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Replaces the platform list; null means every platform, [] none (reviews only, when the keyword has reviewSources)."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"A sentence the classifier reads for this keyword only, on top of the company profile or the group's own description (at most 300 characters): what the term means here, what to ignore. \"Arc is our browser; ignore the geometry word.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"The post must ALSO contain these terms, any one of them or all of them per requiredMode. Empty: no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any: at least one required term must appear. all: every one must."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"A post containing any of these is dropped. A `*` at the start or the end of an entry is a wildcard (beta.* matches beta.0.1; *bot matches nightlybot)."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Posts by these authors are dropped: profile or post links, @handles, u/names, Bluesky DIDs or display names, stored in canonical form like an alert's muted list."},"caseSensitive":{"type":"boolean","description":"true: the term must appear in the case it was typed (RAG, never rag). Default false."}},"description":"Omitted fields are untouched; an empty list clears one."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"Matched mentions allowed per calendar month (UTC). Every match counts, relevant or not, the look-back a new keyword gets included, because every match bills."}},"required":["mentions"],"description":"Replaces the monthly mention cap; null removes it. A cap above this month's count resumes a capped keyword at once, one at or under it pauses it."},"groupId":{"type":"string","minLength":1,"description":"Moves the keyword to this group (grp_...). A 409 when that group already tracks the term."},"reviewSources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"The review page's link: an App Store or Google Play app (https://apps.apple.com/us/app/notion/id1232780281, https://play.google.com/store/apps/details?id=notion.id), a Trustpilot page (https://www.trustpilot.com/review/notion.so) or a Google Maps place (its full link, or a maps.app.goo.gl share link). Or give platform and id."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."},"id":{"type":"string","minLength":1,"maxLength":200,"description":"The id on the platform: the digits after \"id\" on the App Store, the package name on Google Play, the company's domain on Trustpilot (notion.so), a Place ID (ChIJ...) on Google Maps."},"countries":{"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"},"minItems":1,"maxItems":20,"description":"App Store and Google Play only: storefronts to read, two-letter codes, at most 20. Default: the one in the link, else us. Each is one more poll a day; the same review seen in two storefronts is one mention. Trustpilot and Google Maps have one page for everyone and take none."},"language":{"type":"string","minLength":2,"maxLength":10,"description":"Google Play only: the language of the reviews to read (en, es, de, pt-BR); Google Play answers one language at a time. Default: the link's hl, else en."}},"description":"A review page whose reviews become this keyword's mentions: its link, or the platform and the id."},"maxItems":10,"description":"Replaces the list of apps whose reviews this keyword collects; [] disconnects them all (their reviews stay). An app or country added here gets the free 30-day look-back; one already listed keeps its place."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated keyword","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Unmuting needs balance for one more keyword-day (insufficient_balance) or would exceed the 500-keyword ceiling (keyword_limit_reached)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteKeyword","summary":"Delete a keyword","description":"Removes the keyword and its matches. Posts also matched by another keyword stay.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Keyword id (kw_...).","example":"kw_abc123"},"required":true,"description":"Keyword id (kw_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/keywords/{id}/health":{"get":{"operationId":"getKeywordHealth","summary":"Get a keyword's health","description":"Whether the keyword earns what it costs over a trailing window (`range`, default 30d): a status (healthy, noisy, quiet, capped, paused, new) with the reasons in plain words, its numbers by platform and week, what it cost, the words and authors its noise is made of, and suggestions. Each suggestion carries a `patch` to send to PATCH /v1/keywords/{id} as is, and the effect it would have had, measured by running the matcher's own rules over the window's posts. `ai=true` adds a context rewritten by a language model (cached a day, at most 20 model calls an hour per workspace). Read only and never billed; the report is cached for 5 minutes, and a change to the keyword starts a fresh one. At most 30 reads a minute per workspace.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Keyword id (kw_...).","example":"kw_abc123"},"required":true,"description":"Keyword id (kw_...).","name":"id","in":"path"},{"schema":{"type":"string","enum":["7d","30d","90d"],"description":"Trailing window of UTC days ending today, by match time: 7d, 30d, 90d (default 30d)."},"required":false,"description":"Trailing window of UTC days ending today, by match time: 7d, 30d, 90d (default 30d).","name":"range","in":"query"},{"schema":{"type":"boolean","description":"true: also ask a language model for a rewritten context (cached a day per keyword and window, at most 20 model calls an hour per workspace). Default false: every suggestion comes from the rules alone."},"required":false,"description":"true: also ask a language model for a rewritten context (cached a day per keyword and window, at most 20 model calls an hour per workspace). Default false: every suggestion comes from the rules alone.","name":"ai","in":"query"}],"responses":{"200":{"description":"The keyword's health report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeywordHealth"}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"More than 30 health reads this minute (rate_limited)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/filters":{"get":{"operationId":"getFilters","summary":"Get the workspace filters","description":"The noise rules applied to every keyword before a mention is stored: excluded terms and authors, excluded GitHub repositories, and the subreddits Reddit posts may (or may not) come from. A post they reject is never classified, delivered or billed. Keyword-level rules live on each keyword (`matching`); both apply.","tags":["Filters"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The workspace filters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFilters"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateFilters","summary":"Update the workspace filters","description":"Replace any of the lists; an omitted list is untouched and an empty one clears it. Entries are stored in canonical form (terms lowercased, authors as profile links or bare names, repositories as owner/name, subreddits without r/). Takes effect on new mentions within a minute; stored mentions are untouched.","tags":["Filters"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":200,"description":"Replaces the list; [] clears it."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":200,"description":"Replaces the list; [] clears it."},"excludedRepos":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Replaces the list; [] clears it."},"subreddits":{"type":"object","properties":{"only":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Replaces the allowlist; [] clears it."},"excluded":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Replaces the deny list; [] clears it."}},"description":"Reddit only; an omitted list is untouched."}},"description":"Omitted fields are untouched; an empty list clears one."}}}},"responses":{"200":{"description":"The updated filters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFilters"}}}},"400":{"description":"An entry is not a term, an author, a repository or a subreddit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions/{id}":{"patch":{"operationId":"updateMention","summary":"Update a mention","description":"The one write on a mention. Set status to ignored or done to handle it (open puts it back), assign it to a workspace member, snooze it out of the feed, leave an internal note, or correct the classifier: `relevant` true or false is your verdict (relevance becomes 100 or 0, and every list, filter, digest and report follows it), `sentiment` replaces the label; null withdraws a verdict and restores the classifier's value. Omitted fields are untouched. Delivery and billing never change.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Mention id (mm_...).","example":"mm_abc123"},"required":true,"description":"Mention id (mm_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["open","ignored","done"],"description":"ignored or done to handle it; open to put it back."},"assigneeId":{"type":"string","nullable":true,"minLength":1,"description":"A workspace member (user id), or null to unassign."},"snoozedUntil":{"type":"string","description":"ISO 8601 (or epoch ms) until which the mention leaves the feed; null wakes it.","format":"date-time"},"note":{"type":"string","nullable":true,"maxLength":2000,"description":"Internal note; null or empty clears it."},"relevant":{"type":"boolean","nullable":true,"description":"Your verdict on relevance, correcting the classifier: true sets relevance to 100 and puts a filtered mention back in the relevant feed, false sets it to 0 and takes it out; null withdraws the verdict and restores the classifier's score. Never billed or unbilled. A mention still being classified answers 409 classification_pending."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"Your corrected sentiment; null withdraws the correction and restores the classifier's."}},"description":"Every field is optional; omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated mention","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mention"}}}},"400":{"description":"Assignee is not a member of this organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Mention not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A verdict on a mention the classifier has not scored yet (classification_pending)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"getMention","summary":"Get a mention","description":"One mention by id, as it appears in the list: the post, its author with reach and your tags, the classification, the priority score and the triage fields. Ids belong to your organization; any other id is a 404.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Mention id (mm_...).","example":"mm_abc123"},"required":true,"description":"Mention id (mm_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The mention","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mention"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Mention not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions":{"get":{"operationId":"searchMentions","summary":"List mentions","description":"Mentions matched to your keywords, filtered and paginated. Default order is newest match first; sort=priority ranks the last 30 days of matches by attention score. Page with nextCursor, passing the same filters and sort. A mention is one post matched to one keyword. alertId applies an alert rule's filter on top of the others: the same mentions that rule would send. anyOf adds OR: URL-encoded JSON groups of conditions, at least one of which must hold on top of every other filter.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Only matches of this keyword."},"required":false,"description":"Only matches of this keyword.","name":"keywordId","in":"query"},{"schema":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Only posts from this platform."},"required":false,"description":"Only posts from this platform.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status. Omit for every status."},"required":false,"description":"Only mentions in this status. Omit for every status.","name":"status","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest (unclassified included)."},"required":false,"description":"true: only mentions the classifier scored relevant; false: only the rest (unclassified included).","name":"relevant","in":"query"},{"schema":{"type":"string","enum":["positive","neutral","negative"],"description":"Only this sentiment."},"required":false,"description":"Only this sentiment.","name":"sentiment","in":"query"},{"schema":{"type":"string","description":"Only mentions carrying this intent or topic tag (buy_intent, question, complaint, praise, comparison, churn_intent, bug_report, pricing, hiring, event, promotional, testimonial, industry_insight, launch, feedback)."},"required":false,"description":"Only mentions carrying this intent or topic tag (buy_intent, question, complaint, praise, comparison, churn_intent, bug_report, pricing, hiring, event, promotional, testimonial, industry_insight, launch, feedback).","name":"intent","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions that read as machine-made (a bot account, a scheduled or templated post, AI-written text); false: only the rest, mentions judged before this existed included. Omitted: everything."},"required":false,"description":"true: only mentions that read as machine-made (a bot account, a scheduled or templated post, AI-written text); false: only the rest, mentions judged before this existed included. Omitted: everything.","name":"automated","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only this person (an id from /v1/people), merged accounts included. Implies includeMuted."},"required":false,"description":"Only this person (an id from /v1/people), merged accounts included. Implies includeMuted.","name":"personId","in":"query"},{"schema":{"type":"boolean","description":"true: include mentions by people you muted, hidden by default."},"required":false,"description":"true: include mentions by people you muted, hidden by default.","name":"includeMuted","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only mentions assigned to this workspace member (user id)."},"required":false,"description":"Only mentions assigned to this workspace member (user id).","name":"assigneeId","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake."},"required":false,"description":"true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake.","name":"snoozed","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value."},"required":false,"description":"Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value.","name":"excludeAuthors","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Only mentions scored at least this; unclassified ones are excluded."},"required":false,"description":"Only mentions scored at least this; unclassified ones are excluded.","name":"minRelevance","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. Mentions without a confidence are excluded."},"required":false,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. Mentions without a confidence are excluded.","name":"minConfidence","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"required":false,"description":"Only authors with at least this many followers. Unknown reach never passes.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only authors with at most this many followers. Unknown reach never passes."},"required":false,"description":"Only authors with at most this many followers. Unknown reach never passes.","name":"maxFollowers","in":"query"},{"schema":{"type":"boolean","description":"true: only replies and comments (posts answering another post); false: only top-level posts. Omitted: both."},"required":false,"description":"true: only replies and comments (posts answering another post); false: only top-level posts. Omitted: both.","name":"isReply","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Apply an alert rule's filter (an id from GET /v1/alerts) on top of the other filters: the same mentions the rule would send, for a feed-shaped export or a preview. Unknown ids are a 404."},"required":false,"description":"Apply an alert rule's filter (an id from GET /v1/alerts) on top of the other filters: the same mentions the rule would send, for a feed-shaped export or a preview. Unknown ids are a 404.","name":"alertId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Apply a saved view's filter (an id from GET /v1/views) on top of the other filters, every condition ANDed: exactly what the view selects. Unknown ids are a 404."},"required":false,"description":"Apply a saved view's filter (an id from GET /v1/views) on top of the other filters, every condition ANDed: exactly what the view selects. Unknown ids are a 404.","name":"viewId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic. Repeatable, or comma-separated."},"required":false,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic. Repeatable, or comma-separated.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated."},"required":false,"description":"Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated.","name":"tags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). Repeatable, or comma-separated."},"required":false,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). Repeatable, or comma-separated.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"required":false,"description":"Only posts from any of these platforms.","name":"platforms","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"required":false,"description":"Never posts from these platforms.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only matches of any of these keywords."},"required":false,"description":"Only matches of any of these keywords.","name":"keywordIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...). Repeatable, or comma-separated."},"required":false,"description":"Only matches of keywords in any of these groups (grp_...). Repeatable, or comma-separated.","name":"groupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Never matches of keywords in these groups."},"required":false,"description":"Never matches of keywords in these groups.","name":"notGroupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Never matches of these keywords."},"required":false,"description":"Never matches of these keywords.","name":"notKeywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"required":false,"description":"Only these sentiments.","name":"sentiments","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments. A mention the classifier has not scored yet still passes."},"required":false,"description":"Never these sentiments. A mention the classifier has not scored yet still passes.","name":"notSentiments","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"required":false,"description":"Only mentions carrying any of these intent or topic tags.","name":"intents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never mentions carrying these intent or topic tags."},"required":false,"description":"Never mentions carrying these intent or topic tags.","name":"notIntents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts, the host itself or a subdomain of it."},"required":false,"description":"Never posts linking to these hosts, the host itself or a subdomain of it.","name":"notLinkHosts","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never authors your workspace tagged with any of these."},"required":false,"description":"Never authors your workspace tagged with any of these.","name":"notTags","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"required":false,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes.","name":"languages","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages. A post whose language is unknown still passes."},"required":false,"description":"Never posts in these languages. A post whose language is unknown still passes.","name":"notLanguages","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): ratings=1,2 is the unhappy ones. Every other post fails it."},"required":false,"description":"Only app store reviews with any of these star ratings (1 to 5): ratings=1,2 is the unhappy ones. Every other post fails it.","name":"ratings","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): notRatings=5 hides the five star reviews. Posts that are not reviews still pass."},"required":false,"description":"Never reviews with these star ratings (1 to 5): notRatings=5 hides the five star reviews. Posts that are not reviews still pass.","name":"notRatings","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes.","name":"minLikes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes.","name":"minReposts","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes.","name":"minReplies","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes.","name":"minQuotes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes.","name":"minViews","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes.","name":"minBookmarks","in":"query"},{"schema":{"type":"string","description":"OR across groups of conditions, as URL-encoded JSON: [{\"platforms\":[\"reddit\"],\"sentiments\":[\"negative\"]},{\"intents\":[\"buy_intent\"]}] is \"negative on Reddit, or buying intent anywhere\". Each group holds the conditions of a view filter (lists any-of, not lists none-of, all ANDed); a mention passes when at least one group holds, and every other filter here still applies. 1 to 10 groups, none empty, no nesting."},"required":false,"description":"OR across groups of conditions, as URL-encoded JSON: [{\"platforms\":[\"reddit\"],\"sentiments\":[\"negative\"]},{\"intents\":[\"buy_intent\"]}] is \"negative on Reddit, or buying intent anywhere\". Each group holds the conditions of a view filter (lists any-of, not lists none-of, all ANDed); a mention passes when at least one group holds, and every other filter here still applies. 1 to 10 groups, none empty, no nesting.","name":"anyOf","in":"query"},{"schema":{"type":"string","description":"Substring search in the post text or the author's name."},"required":false,"description":"Substring search in the post text or the author's name.","name":"q","in":"query"},{"schema":{"type":"string","description":"Only posts published at or after this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only posts published at or after this instant (ISO 8601, or epoch ms).","name":"since","in":"query"},{"schema":{"type":"string","description":"Only posts published at or before this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only posts published at or before this instant (ISO 8601, or epoch ms).","name":"until","in":"query"},{"schema":{"type":"string","enum":["newest","priority"],"default":"newest","description":"newest: by match time, newest first. priority: by attention score, highest first; priority ranks the last 30 days of matches only, older ones stay reachable under newest. Cursors are specific to a sort."},"required":false,"description":"newest: by match time, newest first. priority: by attention score, highest first; priority ranks the last 30 days of matches only, older ones stay reachable under newest. Cursors are specific to a sort.","name":"sort","in":"query"},{"schema":{"type":"string","description":"nextCursor from the previous page; pass the same filters and sort."},"required":false,"description":"nextCursor from the previous page; pass the same filters and sort.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"Page size, 1 to 100."},"required":false,"description":"Page size, 1 to 100.","name":"limit","in":"query"}],"responses":{"200":{"description":"One page of mentions in the requested order","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Mention"}},"nextCursor":{"type":"string","nullable":true,"description":"Pass as cursor for the next page; null on the last page."}},"required":["data","nextCursor"]}}}},"400":{"description":"Invalid query or pagination cursor, or filter_too_complex: the filters together (anyOf groups, a view or rule on top) name more values than one query can carry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions/export.csv":{"get":{"operationId":"exportMentionsCsv","summary":"Export mentions as CSV","description":"The same mentions GET /v1/mentions would list for these filters, as CSV, newest matched first (the order they entered your feed, which can differ from the post date): id, published_at, platform, keyword, author, author_url, author_followers, relevance, sentiment, intents (pipe-separated), language, confidence, status, relevant, delivered, url, links (pipe-separated), text (first 1,000 characters), group, group_external_id, rating and app_id (app store reviews only), title and image_url (where the platform has them). Capped at 10,000 rows; the X-Mentions-Truncated header says when the cap cut the list. At most 6 exports per minute per workspace; a 429 carries Retry-After.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Only matches of this keyword."},"required":false,"description":"Only matches of this keyword.","name":"keywordId","in":"query"},{"schema":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Only posts from this platform."},"required":false,"description":"Only posts from this platform.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status. Omit for every status."},"required":false,"description":"Only mentions in this status. Omit for every status.","name":"status","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest (unclassified included)."},"required":false,"description":"true: only mentions the classifier scored relevant; false: only the rest (unclassified included).","name":"relevant","in":"query"},{"schema":{"type":"string","enum":["positive","neutral","negative"],"description":"Only this sentiment."},"required":false,"description":"Only this sentiment.","name":"sentiment","in":"query"},{"schema":{"type":"string","description":"Only mentions carrying this intent or topic tag (buy_intent, question, complaint, praise, comparison, churn_intent, bug_report, pricing, hiring, event, promotional, testimonial, industry_insight, launch, feedback)."},"required":false,"description":"Only mentions carrying this intent or topic tag (buy_intent, question, complaint, praise, comparison, churn_intent, bug_report, pricing, hiring, event, promotional, testimonial, industry_insight, launch, feedback).","name":"intent","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions that read as machine-made (a bot account, a scheduled or templated post, AI-written text); false: only the rest, mentions judged before this existed included. Omitted: everything."},"required":false,"description":"true: only mentions that read as machine-made (a bot account, a scheduled or templated post, AI-written text); false: only the rest, mentions judged before this existed included. Omitted: everything.","name":"automated","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only this person (an id from /v1/people), merged accounts included. Implies includeMuted."},"required":false,"description":"Only this person (an id from /v1/people), merged accounts included. Implies includeMuted.","name":"personId","in":"query"},{"schema":{"type":"boolean","description":"true: include mentions by people you muted, hidden by default."},"required":false,"description":"true: include mentions by people you muted, hidden by default.","name":"includeMuted","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only mentions assigned to this workspace member (user id)."},"required":false,"description":"Only mentions assigned to this workspace member (user id).","name":"assigneeId","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake."},"required":false,"description":"true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake.","name":"snoozed","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value."},"required":false,"description":"Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value.","name":"excludeAuthors","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Only mentions scored at least this; unclassified ones are excluded."},"required":false,"description":"Only mentions scored at least this; unclassified ones are excluded.","name":"minRelevance","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. Mentions without a confidence are excluded."},"required":false,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. Mentions without a confidence are excluded.","name":"minConfidence","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"required":false,"description":"Only authors with at least this many followers. Unknown reach never passes.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only authors with at most this many followers. Unknown reach never passes."},"required":false,"description":"Only authors with at most this many followers. Unknown reach never passes.","name":"maxFollowers","in":"query"},{"schema":{"type":"boolean","description":"true: only replies and comments (posts answering another post); false: only top-level posts. Omitted: both."},"required":false,"description":"true: only replies and comments (posts answering another post); false: only top-level posts. Omitted: both.","name":"isReply","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Apply an alert rule's filter (an id from GET /v1/alerts) on top of the other filters: the same mentions the rule would send, for a feed-shaped export or a preview. Unknown ids are a 404."},"required":false,"description":"Apply an alert rule's filter (an id from GET /v1/alerts) on top of the other filters: the same mentions the rule would send, for a feed-shaped export or a preview. Unknown ids are a 404.","name":"alertId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Apply a saved view's filter (an id from GET /v1/views) on top of the other filters, every condition ANDed: exactly what the view selects. Unknown ids are a 404."},"required":false,"description":"Apply a saved view's filter (an id from GET /v1/views) on top of the other filters, every condition ANDed: exactly what the view selects. Unknown ids are a 404.","name":"viewId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic. Repeatable, or comma-separated."},"required":false,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic. Repeatable, or comma-separated.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated."},"required":false,"description":"Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated.","name":"tags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). Repeatable, or comma-separated."},"required":false,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). Repeatable, or comma-separated.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"required":false,"description":"Only posts from any of these platforms.","name":"platforms","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"required":false,"description":"Never posts from these platforms.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only matches of any of these keywords."},"required":false,"description":"Only matches of any of these keywords.","name":"keywordIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...). Repeatable, or comma-separated."},"required":false,"description":"Only matches of keywords in any of these groups (grp_...). Repeatable, or comma-separated.","name":"groupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Never matches of keywords in these groups."},"required":false,"description":"Never matches of keywords in these groups.","name":"notGroupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Never matches of these keywords."},"required":false,"description":"Never matches of these keywords.","name":"notKeywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"required":false,"description":"Only these sentiments.","name":"sentiments","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments. A mention the classifier has not scored yet still passes."},"required":false,"description":"Never these sentiments. A mention the classifier has not scored yet still passes.","name":"notSentiments","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"required":false,"description":"Only mentions carrying any of these intent or topic tags.","name":"intents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never mentions carrying these intent or topic tags."},"required":false,"description":"Never mentions carrying these intent or topic tags.","name":"notIntents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts, the host itself or a subdomain of it."},"required":false,"description":"Never posts linking to these hosts, the host itself or a subdomain of it.","name":"notLinkHosts","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never authors your workspace tagged with any of these."},"required":false,"description":"Never authors your workspace tagged with any of these.","name":"notTags","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"required":false,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes.","name":"languages","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages. A post whose language is unknown still passes."},"required":false,"description":"Never posts in these languages. A post whose language is unknown still passes.","name":"notLanguages","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): ratings=1,2 is the unhappy ones. Every other post fails it."},"required":false,"description":"Only app store reviews with any of these star ratings (1 to 5): ratings=1,2 is the unhappy ones. Every other post fails it.","name":"ratings","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): notRatings=5 hides the five star reviews. Posts that are not reviews still pass."},"required":false,"description":"Never reviews with these star ratings (1 to 5): notRatings=5 hides the five star reviews. Posts that are not reviews still pass.","name":"notRatings","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes.","name":"minLikes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes.","name":"minReposts","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes.","name":"minReplies","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes.","name":"minQuotes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes.","name":"minViews","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes.","name":"minBookmarks","in":"query"},{"schema":{"type":"string","description":"OR across groups of conditions, as URL-encoded JSON: [{\"platforms\":[\"reddit\"],\"sentiments\":[\"negative\"]},{\"intents\":[\"buy_intent\"]}] is \"negative on Reddit, or buying intent anywhere\". Each group holds the conditions of a view filter (lists any-of, not lists none-of, all ANDed); a mention passes when at least one group holds, and every other filter here still applies. 1 to 10 groups, none empty, no nesting."},"required":false,"description":"OR across groups of conditions, as URL-encoded JSON: [{\"platforms\":[\"reddit\"],\"sentiments\":[\"negative\"]},{\"intents\":[\"buy_intent\"]}] is \"negative on Reddit, or buying intent anywhere\". Each group holds the conditions of a view filter (lists any-of, not lists none-of, all ANDed); a mention passes when at least one group holds, and every other filter here still applies. 1 to 10 groups, none empty, no nesting.","name":"anyOf","in":"query"},{"schema":{"type":"string","description":"Substring search in the post text or the author's name."},"required":false,"description":"Substring search in the post text or the author's name.","name":"q","in":"query"},{"schema":{"type":"string","description":"Only posts published at or after this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only posts published at or after this instant (ISO 8601, or epoch ms).","name":"since","in":"query"},{"schema":{"type":"string","description":"Only posts published at or before this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only posts published at or before this instant (ISO 8601, or epoch ms).","name":"until","in":"query"}],"responses":{"200":{"description":"CSV, UTF-8","content":{"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Invalid query, or filter_too_complex: the filters together name more values than one query can carry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"More than 6 exports this minute; retry after the Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions/export.json":{"get":{"operationId":"exportMentionsJson","summary":"Export mentions as JSON","description":"The same mentions GET /v1/mentions would list for these filters, in one response, newest matched first (the order they entered your feed): every row is the full Mention object the list returns, text included. Capped at 10,000 mentions; `truncated` (and the X-Mentions-Truncated header) says when the cap cut the list. Shares the CSV export's limit: at most 6 exports per minute per workspace, either format; a 429 carries Retry-After.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Only matches of this keyword."},"required":false,"description":"Only matches of this keyword.","name":"keywordId","in":"query"},{"schema":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Only posts from this platform."},"required":false,"description":"Only posts from this platform.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status. Omit for every status."},"required":false,"description":"Only mentions in this status. Omit for every status.","name":"status","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest (unclassified included)."},"required":false,"description":"true: only mentions the classifier scored relevant; false: only the rest (unclassified included).","name":"relevant","in":"query"},{"schema":{"type":"string","enum":["positive","neutral","negative"],"description":"Only this sentiment."},"required":false,"description":"Only this sentiment.","name":"sentiment","in":"query"},{"schema":{"type":"string","description":"Only mentions carrying this intent or topic tag (buy_intent, question, complaint, praise, comparison, churn_intent, bug_report, pricing, hiring, event, promotional, testimonial, industry_insight, launch, feedback)."},"required":false,"description":"Only mentions carrying this intent or topic tag (buy_intent, question, complaint, praise, comparison, churn_intent, bug_report, pricing, hiring, event, promotional, testimonial, industry_insight, launch, feedback).","name":"intent","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions that read as machine-made (a bot account, a scheduled or templated post, AI-written text); false: only the rest, mentions judged before this existed included. Omitted: everything."},"required":false,"description":"true: only mentions that read as machine-made (a bot account, a scheduled or templated post, AI-written text); false: only the rest, mentions judged before this existed included. Omitted: everything.","name":"automated","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only this person (an id from /v1/people), merged accounts included. Implies includeMuted."},"required":false,"description":"Only this person (an id from /v1/people), merged accounts included. Implies includeMuted.","name":"personId","in":"query"},{"schema":{"type":"boolean","description":"true: include mentions by people you muted, hidden by default."},"required":false,"description":"true: include mentions by people you muted, hidden by default.","name":"includeMuted","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only mentions assigned to this workspace member (user id)."},"required":false,"description":"Only mentions assigned to this workspace member (user id).","name":"assigneeId","in":"query"},{"schema":{"type":"boolean","description":"true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake."},"required":false,"description":"true: only mentions currently snoozed. Otherwise snoozed mentions stay out until they wake.","name":"snoozed","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value."},"required":false,"description":"Hide these authors: display names, handles or profile URLs. Repeatable, or one comma-separated value.","name":"excludeAuthors","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Only mentions scored at least this; unclassified ones are excluded."},"required":false,"description":"Only mentions scored at least this; unclassified ones are excluded.","name":"minRelevance","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. Mentions without a confidence are excluded."},"required":false,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. Mentions without a confidence are excluded.","name":"minConfidence","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"required":false,"description":"Only authors with at least this many followers. Unknown reach never passes.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only authors with at most this many followers. Unknown reach never passes."},"required":false,"description":"Only authors with at most this many followers. Unknown reach never passes.","name":"maxFollowers","in":"query"},{"schema":{"type":"boolean","description":"true: only replies and comments (posts answering another post); false: only top-level posts. Omitted: both."},"required":false,"description":"true: only replies and comments (posts answering another post); false: only top-level posts. Omitted: both.","name":"isReply","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Apply an alert rule's filter (an id from GET /v1/alerts) on top of the other filters: the same mentions the rule would send, for a feed-shaped export or a preview. Unknown ids are a 404."},"required":false,"description":"Apply an alert rule's filter (an id from GET /v1/alerts) on top of the other filters: the same mentions the rule would send, for a feed-shaped export or a preview. Unknown ids are a 404.","name":"alertId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Apply a saved view's filter (an id from GET /v1/views) on top of the other filters, every condition ANDed: exactly what the view selects. Unknown ids are a 404."},"required":false,"description":"Apply a saved view's filter (an id from GET /v1/views) on top of the other filters, every condition ANDed: exactly what the view selects. Unknown ids are a 404.","name":"viewId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic. Repeatable, or comma-separated."},"required":false,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic. Repeatable, or comma-separated.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated."},"required":false,"description":"Only authors your workspace tagged with any of these (exact, case-sensitive). Repeatable, or comma-separated.","name":"tags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). Repeatable, or comma-separated."},"required":false,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). Repeatable, or comma-separated.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"required":false,"description":"Only posts from any of these platforms.","name":"platforms","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"required":false,"description":"Never posts from these platforms.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only matches of any of these keywords."},"required":false,"description":"Only matches of any of these keywords.","name":"keywordIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...). Repeatable, or comma-separated."},"required":false,"description":"Only matches of keywords in any of these groups (grp_...). Repeatable, or comma-separated.","name":"groupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Never matches of keywords in these groups."},"required":false,"description":"Never matches of keywords in these groups.","name":"notGroupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Never matches of these keywords."},"required":false,"description":"Never matches of these keywords.","name":"notKeywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"required":false,"description":"Only these sentiments.","name":"sentiments","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments. A mention the classifier has not scored yet still passes."},"required":false,"description":"Never these sentiments. A mention the classifier has not scored yet still passes.","name":"notSentiments","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"required":false,"description":"Only mentions carrying any of these intent or topic tags.","name":"intents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never mentions carrying these intent or topic tags."},"required":false,"description":"Never mentions carrying these intent or topic tags.","name":"notIntents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts, the host itself or a subdomain of it."},"required":false,"description":"Never posts linking to these hosts, the host itself or a subdomain of it.","name":"notLinkHosts","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never authors your workspace tagged with any of these."},"required":false,"description":"Never authors your workspace tagged with any of these.","name":"notTags","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"required":false,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes.","name":"languages","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages. A post whose language is unknown still passes."},"required":false,"description":"Never posts in these languages. A post whose language is unknown still passes.","name":"notLanguages","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): ratings=1,2 is the unhappy ones. Every other post fails it."},"required":false,"description":"Only app store reviews with any of these star ratings (1 to 5): ratings=1,2 is the unhappy ones. Every other post fails it.","name":"ratings","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): notRatings=5 hides the five star reviews. Posts that are not reviews still pass."},"required":false,"description":"Never reviews with these star ratings (1 to 5): notRatings=5 hides the five star reviews. Posts that are not reviews still pass.","name":"notRatings","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes.","name":"minLikes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes.","name":"minReposts","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes.","name":"minReplies","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes.","name":"minQuotes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes.","name":"minViews","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"required":false,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes.","name":"minBookmarks","in":"query"},{"schema":{"type":"string","description":"OR across groups of conditions, as URL-encoded JSON: [{\"platforms\":[\"reddit\"],\"sentiments\":[\"negative\"]},{\"intents\":[\"buy_intent\"]}] is \"negative on Reddit, or buying intent anywhere\". Each group holds the conditions of a view filter (lists any-of, not lists none-of, all ANDed); a mention passes when at least one group holds, and every other filter here still applies. 1 to 10 groups, none empty, no nesting."},"required":false,"description":"OR across groups of conditions, as URL-encoded JSON: [{\"platforms\":[\"reddit\"],\"sentiments\":[\"negative\"]},{\"intents\":[\"buy_intent\"]}] is \"negative on Reddit, or buying intent anywhere\". Each group holds the conditions of a view filter (lists any-of, not lists none-of, all ANDed); a mention passes when at least one group holds, and every other filter here still applies. 1 to 10 groups, none empty, no nesting.","name":"anyOf","in":"query"},{"schema":{"type":"string","description":"Substring search in the post text or the author's name."},"required":false,"description":"Substring search in the post text or the author's name.","name":"q","in":"query"},{"schema":{"type":"string","description":"Only posts published at or after this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only posts published at or after this instant (ISO 8601, or epoch ms).","name":"since","in":"query"},{"schema":{"type":"string","description":"Only posts published at or before this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only posts published at or before this instant (ISO 8601, or epoch ms).","name":"until","in":"query"}],"responses":{"200":{"description":"Every matching mention, up to the cap","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Mention"},"description":"At most 10,000 mentions, newest matched first."},"truncated":{"type":"boolean","description":"true when more mentions matched than the cap returns: narrow the filters (since, until) and export again."}},"required":["data","truncated"]}}}},"400":{"description":"Invalid query, or filter_too_complex: the filters together name more values than one query can carry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"More than 6 exports this minute; retry after the Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/export.csv":{"get":{"operationId":"exportPeopleCsv","summary":"Export people as CSV","description":"The same list as GET /v1/people (segmentId included) as CSV, one row per person with their contact columns: handle, followers, email, website, company, location, tags, then outreach stage, owner and last contacted. Capped at 5,000 people. At most 6 exports per minute per workspace; a 429 carries Retry-After.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"People with an account on this platform."},"required":false,"description":"People with an account on this platform.","name":"platform","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Matches the display name or the profile handle or URL, case-insensitively."},"required":false,"description":"Matches the display name or the profile handle or URL, case-insensitively.","name":"q","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":300,"description":"Find a person by one of their accounts: a handle (@jane, u/jane, jane) or a profile or post link (https://x.com/jane). Exact, case-insensitive, merged accounts included; combine with platform to pick one platform. A link names its own platform."},"required":false,"description":"Find a person by one of their accounts: a handle (@jane, u/jane, jane) or a profile or post link (https://x.com/jane). Exact, case-insensitive, merged accounts included; combine with platform to pick one platform. A link names its own platform.","name":"handle","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":40,"description":"Only people carrying this tag (exact, case-sensitive)."},"required":false,"description":"Only people carrying this tag (exact, case-sensitive).","name":"tag","in":"query"},{"schema":{"type":"boolean","description":"true: only muted people; false: only unmuted; omitted: everyone."},"required":false,"description":"true: only muted people; false: only unmuted; omitted: everyone.","name":"muted","in":"query"},{"schema":{"type":"string","description":"Only people whose first matched mention is at or after this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only people whose first matched mention is at or after this instant (ISO 8601, or epoch ms).","name":"since","in":"query"},{"schema":{"type":"string","minLength":1,"description":"A saved segment applied on top of every other filter here. Unknown id: 404."},"required":false,"description":"A saved segment applied on top of every other filter here. Unknown id: 404.","name":"segmentId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms. Repeatable, or comma-separated."},"required":false,"description":"People with an account on any of these platforms. Repeatable, or comma-separated.","name":"platforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People carrying any of these tags. Repeatable, or comma-separated."},"required":false,"description":"People carrying any of these tags. Repeatable, or comma-separated.","name":"tags","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"At least this many followers. Unknown reach never matches."},"required":false,"description":"At least this many followers. Unknown reach never matches.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"At most this many followers."},"required":false,"description":"At most this many followers.","name":"maxFollowers","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"required":false,"description":"At least this many matched mentions.","name":"minMentions","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"required":false,"description":"At least this many negative mentions.","name":"minNegative","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"At least one mention carrying any of these intents."},"required":false,"description":"At least one mention carrying any of these intents.","name":"intents","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms. Repeatable, or comma-separated."},"required":false,"description":"Nobody with an account on these platforms. Repeatable, or comma-separated.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Nobody carrying any of these tags. Repeatable, or comma-separated."},"required":false,"description":"Nobody carrying any of these tags. Repeatable, or comma-separated.","name":"notTags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"Nobody whose mentions carry any of these intents. Repeatable, or comma-separated."},"required":false,"description":"Nobody whose mentions carry any of these intents. Repeatable, or comma-separated.","name":"notIntents","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"required":false,"description":"Mentioned a keyword of any of these kinds.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"required":false,"description":"Never mentioned a keyword of these kinds.","name":"neverKeywordKinds","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"required":false,"description":"First seen within this many days.","name":"newSinceDays","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with at least one mention linking to any of these hosts, the host itself or a subdomain of it. Repeatable, or comma-separated."},"required":false,"description":"People with at least one mention linking to any of these hosts, the host itself or a subdomain of it. Repeatable, or comma-separated.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages. Repeatable, or comma-separated."},"required":false,"description":"People at any of these outreach stages. Repeatable, or comma-separated.","name":"stages","in":"query"},{"schema":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest; omitted: everyone."},"required":false,"description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest; omitted: everyone.","name":"automated","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); `none` matches people nobody owns. Repeatable, or comma-separated."},"required":false,"description":"People owned by any of these members (user ids); `none` matches people nobody owns. Repeatable, or comma-separated.","name":"ownerIds","in":"query"},{"schema":{"type":"string","enum":["mentions","recent","reach","new"],"default":"mentions","description":"mentions: most matches first. recent: last seen first. reach: most followers first, unknown last. new: first seen most recently first."},"required":false,"description":"mentions: most matches first. recent: last seen first. reach: most followers first, unknown last. new: first seen most recently first.","name":"sort","in":"query"}],"responses":{"200":{"description":"CSV, UTF-8","content":{"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such segment for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"More than 6 exports this minute; retry after the Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people":{"get":{"operationId":"listPeople","summary":"List people","description":"The people behind your mentions: one row per person, with their accounts, reach, public profile, per-workspace stats, your annotations and where your outreach stands. Filter by platform, tag, follower range, mention counts, intents seen, keyword kinds mentioned or never mentioned, outreach stage, owner, automated (bot accounts, whose matched posts are mostly machine-made), or a saved segment. Offset-paginated with a total.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"People with an account on this platform."},"required":false,"description":"People with an account on this platform.","name":"platform","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Matches the display name or the profile handle or URL, case-insensitively."},"required":false,"description":"Matches the display name or the profile handle or URL, case-insensitively.","name":"q","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":300,"description":"Find a person by one of their accounts: a handle (@jane, u/jane, jane) or a profile or post link (https://x.com/jane). Exact, case-insensitive, merged accounts included; combine with platform to pick one platform. A link names its own platform."},"required":false,"description":"Find a person by one of their accounts: a handle (@jane, u/jane, jane) or a profile or post link (https://x.com/jane). Exact, case-insensitive, merged accounts included; combine with platform to pick one platform. A link names its own platform.","name":"handle","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":40,"description":"Only people carrying this tag (exact, case-sensitive)."},"required":false,"description":"Only people carrying this tag (exact, case-sensitive).","name":"tag","in":"query"},{"schema":{"type":"boolean","description":"true: only muted people; false: only unmuted; omitted: everyone."},"required":false,"description":"true: only muted people; false: only unmuted; omitted: everyone.","name":"muted","in":"query"},{"schema":{"type":"string","description":"Only people whose first matched mention is at or after this instant (ISO 8601, or epoch ms).","format":"date-time"},"required":false,"description":"Only people whose first matched mention is at or after this instant (ISO 8601, or epoch ms).","name":"since","in":"query"},{"schema":{"type":"string","minLength":1,"description":"A saved segment applied on top of every other filter here. Unknown id: 404."},"required":false,"description":"A saved segment applied on top of every other filter here. Unknown id: 404.","name":"segmentId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms. Repeatable, or comma-separated."},"required":false,"description":"People with an account on any of these platforms. Repeatable, or comma-separated.","name":"platforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People carrying any of these tags. Repeatable, or comma-separated."},"required":false,"description":"People carrying any of these tags. Repeatable, or comma-separated.","name":"tags","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"At least this many followers. Unknown reach never matches."},"required":false,"description":"At least this many followers. Unknown reach never matches.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"At most this many followers."},"required":false,"description":"At most this many followers.","name":"maxFollowers","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"required":false,"description":"At least this many matched mentions.","name":"minMentions","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"required":false,"description":"At least this many negative mentions.","name":"minNegative","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"At least one mention carrying any of these intents."},"required":false,"description":"At least one mention carrying any of these intents.","name":"intents","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms. Repeatable, or comma-separated."},"required":false,"description":"Nobody with an account on these platforms. Repeatable, or comma-separated.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Nobody carrying any of these tags. Repeatable, or comma-separated."},"required":false,"description":"Nobody carrying any of these tags. Repeatable, or comma-separated.","name":"notTags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"Nobody whose mentions carry any of these intents. Repeatable, or comma-separated."},"required":false,"description":"Nobody whose mentions carry any of these intents. Repeatable, or comma-separated.","name":"notIntents","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"required":false,"description":"Mentioned a keyword of any of these kinds.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"required":false,"description":"Never mentioned a keyword of these kinds.","name":"neverKeywordKinds","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"required":false,"description":"First seen within this many days.","name":"newSinceDays","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with at least one mention linking to any of these hosts, the host itself or a subdomain of it. Repeatable, or comma-separated."},"required":false,"description":"People with at least one mention linking to any of these hosts, the host itself or a subdomain of it. Repeatable, or comma-separated.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages. Repeatable, or comma-separated."},"required":false,"description":"People at any of these outreach stages. Repeatable, or comma-separated.","name":"stages","in":"query"},{"schema":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest; omitted: everyone."},"required":false,"description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest; omitted: everyone.","name":"automated","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); `none` matches people nobody owns. Repeatable, or comma-separated."},"required":false,"description":"People owned by any of these members (user ids); `none` matches people nobody owns. Repeatable, or comma-separated.","name":"ownerIds","in":"query"},{"schema":{"type":"string","enum":["mentions","recent","reach","new"],"default":"mentions","description":"mentions: most matches first. recent: last seen first. reach: most followers first, unknown last. new: first seen most recently first."},"required":false,"description":"mentions: most matches first. recent: last seen first. reach: most followers first, unknown last. new: first seen most recently first.","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Page size, 1 to 100."},"required":false,"description":"Page size, 1 to 100.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"default":0,"description":"Skip this many people. Offset paging: a grouped read over hundreds of people, not a stream."},"required":false,"description":"Skip this many people. Offset paging: a grouped read over hundreds of people, not a stream.","name":"offset","in":"query"}],"responses":{"200":{"description":"One page of people","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Person id (aut_...): the canonical account. An account merged into someone resolves to that person."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform of the canonical account; `accounts` lists every account."},"name":{"type":"string","nullable":true,"description":"Display name as of their newest post; null when the platform has none."},"handle":{"type":"string","nullable":true,"description":"Platform handle of the canonical account, formatted as the platform shows it."},"url":{"type":"string","nullable":true,"description":"Profile URL of the canonical account."},"avatarUrl":{"type":"string","nullable":true},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The account id (aut_...); the canonical one equals the person id."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"name":{"type":"string","nullable":true,"description":"Display name as the platform reports it."},"handle":{"type":"string","nullable":true,"description":"Platform handle derived from the profile URL, formatted as the platform shows it."},"url":{"type":"string","nullable":true,"description":"Profile URL."}},"required":["id","platform","name","handle","url"]},"description":"Every account this workspace treats as this person, the canonical one first."},"reach":{"type":"object","properties":{"followers":{"type":"integer","nullable":true},"following":{"type":"integer","nullable":true},"posts":{"type":"integer","nullable":true}},"required":["followers","following","posts"],"description":"Platform counts as of their newest post; null where the platform has no such number."},"profile":{"type":"object","nullable":true,"properties":{"bio":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"email":{"type":"string","nullable":true,"description":"Only when the person made it public on the platform."},"links":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","minLength":1},"url":{"type":"string","format":"uri"}},"required":["provider","url"]},"description":"Other accounts the person lists on their profile."},"fetchedAt":{"type":"string","description":"When the profile was read."}},"required":["bio","company","location","website","email","links","fetchedAt"],"description":"Public profile facts; null until looked up."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"Every match of theirs for this workspace, relevant or not."},"relevant":{"type":"integer","minimum":0,"description":"Of those, scored relevant."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0},"neutral":{"type":"integer","minimum":0},"negative":{"type":"integer","minimum":0}},"required":["positive","neutral","negative"]},"firstSeenAt":{"type":"string","description":"Their oldest matched post."},"lastSeenAt":{"type":"string","description":"Their newest matched post."}},"required":["mentions","relevant","sentiment","firstSeenAt","lastSeenAt"],"description":"Computed over this workspace's matches."},"annotations":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"notes":{"type":"string"},"muted":{"type":"boolean","description":"Their posts stay out of the feed and every channel; ingest and billing are untouched."}},"required":["tags","notes","muted"],"description":"What this workspace wrote about the person."},"outreach":{"type":"object","properties":{"owner":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"User id of the workspace member."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"The teammate who owns the contact; null when nobody does, or the owner left the workspace."},"stage":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"lastContactedAt":{"type":"string","nullable":true,"description":"The newest logged activity; null when nobody logged a contact."}},"required":["owner","stage","lastContactedAt"],"description":"Where your workspace stands with the person. The first logged activity claims an unowned person for whoever reached out and moves not_contacted to contacted."}},"required":["id","platform","name","handle","url","avatarUrl","accounts","reach","profile","stats","annotations","outreach"]}},"total":{"type":"integer","minimum":0,"description":"People matching the filters, across all pages."}},"required":["data","total"]}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such segment for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}":{"get":{"operationId":"getPerson","summary":"Get a person","description":"One person as your workspace sees them. An account merged into someone resolves to that person.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No mention by this person for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updatePerson","summary":"Update your annotations on a person","description":"Tags, notes, mute, and the outreach owner (a workspace member; null clears) and stage, for your workspace only. Mute hides their posts from your feed and every channel; ingest and billing never change.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Replaces the whole list."},"notes":{"type":"string","maxLength":2000},"muted":{"type":"boolean"},"ownerId":{"type":"string","nullable":true,"minLength":1,"description":"The member who owns the contact (user id); null clears."},"stage":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"400":{"description":"Invalid body, or the owner is not a workspace member","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No mention by this person for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/merge":{"post":{"operationId":"mergePeople","summary":"Merge an account into a person","description":"Declare that this account and another person are the same human, for your workspace only. Their mentions, tags, notes and outreach activities combine under the person named by `into`, which keeps its owner and stage unless it had none.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"into":{"type":"string","minLength":1,"description":"The person to fold this account into (their id)."}},"required":["into"]}}}},"responses":{"200":{"description":"The person this account now belongs to","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Either side is unknown to your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/split":{"post":{"operationId":"splitPerson","summary":"Undo a merge","description":"The account becomes its own person again.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The account, as its own person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This account was not merged into anyone","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/activities":{"get":{"operationId":"listPersonActivities","summary":"List outreach activities","description":"Every logged contact with this person across all their accounts, newest first (at most 200): who reached out, the channel, when, and a short note. Read it before reaching out so two teammates never contact the same person without knowing.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The activities","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Activity id (act_...)."},"personId":{"type":"string","description":"The person it belongs to (aut_...)."},"channel":{"type":"string","enum":["email","x","linkedin","bluesky","reddit","github","call","meeting","other"],"description":"How they were reached: email, x, linkedin, bluesky, reddit, github, call, meeting or other."},"note":{"type":"string","description":"What was sent or said, briefly; empty when nothing was written."},"member":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"User id of the workspace member."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"Who reached out; null when an API key logged it without naming a member, or that member left the workspace."},"occurredAt":{"type":"string","description":"When the contact happened."},"createdAt":{"type":"string","description":"When it was logged."}},"required":["id","personId","channel","note","member","occurredAt","createdAt"]},"description":"Newest first, at most 200."}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No mention by this person for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"logPersonActivity","summary":"Log an outreach activity","description":"Record that a teammate reached out to this person: an email, a DM, a call. The first activity claims an unowned person for whoever reached out and moves not_contacted to contacted; an existing owner and a later stage are kept. `memberId` defaults to the signed-in member; an API key that omits it logs an unattributed activity, which claims nobody.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","enum":["email","x","linkedin","bluesky","reddit","github","call","meeting","other"],"description":"How they were reached: email, x, linkedin, bluesky, reddit, github, call, meeting or other."},"note":{"type":"string","maxLength":2000,"default":"","description":"What was sent or said, briefly."},"occurredAt":{"type":"string","description":"When the contact happened (ISO 8601, or epoch ms). Defaults to now.","format":"date-time"},"memberId":{"type":"string","minLength":1,"description":"The member who reached out (user id). Defaults to the signed-in member; an API key that omits it logs an unattributed activity."}},"required":["channel"]}}}},"responses":{"201":{"description":"The logged activity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonActivity"}}}},"400":{"description":"Invalid body, or memberId is not a workspace member","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No mention by this person for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/activities/{activityId}":{"delete":{"operationId":"deletePersonActivity","summary":"Delete an outreach activity","description":"Remove a contact logged by mistake. The person's owner and stage stay as they are.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Person id (aut_...).","example":"aut_abc123"},"required":true,"description":"Person id (aut_...).","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"Activity id (act_...).","example":"act_abc123"},"required":true,"description":"Activity id (act_...).","name":"activityId","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such activity on this person for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/segments":{"get":{"operationId":"listSegments","summary":"List segments","description":"Your saved segments, each with the number of people in it right now (segments are evaluated on every read, never materialized), plus presets you can save as a starting point. Pass a segment id to GET /v1/people to list its members.","tags":["Segments"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Every segment, with presets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Segment id (seg_...)."},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People carrying any of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"At least this many followers. Unknown reach never matches."},"maxFollowers":{"type":"integer","minimum":0,"description":"At most this many followers. Unknown reach never matches."},"minMentions":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"At least one mention carrying any of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Nobody carrying any of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Nobody whose mentions carry any of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"At least one mention linking to any of these hosts, the host itself or a subdomain of it."},"muted":{"type":"boolean","description":"true: only muted people; false: only unmuted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages."},"automated":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); \"none\" matches people nobody owns."}}},"count":{"type":"integer","minimum":0,"description":"People in the segment right now; it is evaluated on every read."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"updatedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","name","description","filter","count","createdAt","updatedAt"]}},"presets":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People carrying any of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"At least this many followers. Unknown reach never matches."},"maxFollowers":{"type":"integer","minimum":0,"description":"At most this many followers. Unknown reach never matches."},"minMentions":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"At least one mention carrying any of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Nobody carrying any of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Nobody whose mentions carry any of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"At least one mention linking to any of these hosts, the host itself or a subdomain of it."},"muted":{"type":"boolean","description":"true: only muted people; false: only unmuted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages."},"automated":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); \"none\" matches people nobody owns."}}}},"required":["key","name","description","filter"]},"description":"Starting points you can save with POST /v1/segments."}},"required":["data","presets"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createSegment","summary":"Create a segment","tags":["Segments"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":500,"default":""},"filter":{"type":"object","properties":{"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People carrying any of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"At least this many followers. Unknown reach never matches."},"maxFollowers":{"type":"integer","minimum":0,"description":"At most this many followers. Unknown reach never matches."},"minMentions":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"At least one mention carrying any of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Nobody carrying any of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Nobody whose mentions carry any of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"At least one mention linking to any of these hosts, the host itself or a subdomain of it."},"muted":{"type":"boolean","description":"true: only muted people; false: only unmuted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages."},"automated":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); \"none\" matches people nobody owns."}},"default":{}}},"required":["name"]}}}},"responses":{"201":{"description":"The saved segment, with its current size","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A segment with this name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/segments/{id}":{"get":{"operationId":"getSegment","summary":"Get a segment","tags":["Segments"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Segment id (seg_...).","example":"seg_abc123"},"required":true,"description":"Segment id (seg_...).","name":"id","in":"path"}],"responses":{"200":{"description":"One segment, with its current size","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such segment for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateSegment","summary":"Update a segment","tags":["Segments"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Segment id (seg_...).","example":"seg_abc123"},"required":true,"description":"Segment id (seg_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":500},"filter":{"type":"object","properties":{"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"People with an account on any of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People carrying any of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"At least this many followers. Unknown reach never matches."},"maxFollowers":{"type":"integer","minimum":0,"description":"At most this many followers. Unknown reach never matches."},"minMentions":{"type":"integer","minimum":1,"description":"At least this many matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"At least this many negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"At least one mention carrying any of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Mentioned a keyword of any of these kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Never mentioned a keyword of these kinds."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Nobody with an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Nobody carrying any of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Nobody whose mentions carry any of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"First seen within this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"At least one mention linking to any of these hosts, the host itself or a subdomain of it."},"muted":{"type":"boolean","description":"true: only muted people; false: only unmuted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"Where your workspace stands with the person: not_contacted, contacted, replied, in_talks, customer or not_a_fit."},"maxItems":6,"description":"People at any of these outreach stages."},"automated":{"type":"boolean","description":"true: only people whose matched posts are mostly machine-made (bot accounts); false: only the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by any of these members (user ids); \"none\" matches people nobody owns."}},"description":"Replaces the whole filter."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such segment for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A segment with this name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteSegment","summary":"Delete a segment","description":"Nobody in it is affected.","tags":["Segments"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Segment id (seg_...).","example":"seg_abc123"},"required":true,"description":"Segment id (seg_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such segment for your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/views":{"get":{"operationId":"listViews","summary":"List views","description":"The saved views of the workspace, oldest first. A view is a named filter over mentions: pass its id as `viewId` to GET /v1/mentions or the export to read exactly what it selects.","tags":["Views"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Saved views","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"View id (vw_...)."},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Substring in the post text or the author's name."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of any of these keywords."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of these keywords."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of keywords in these groups."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status: open, ignored, done."},"relevant":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Only mentions scored at least this."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments; an unscored mention still passes."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never mentions carrying these tags."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made; false: only the rest."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1)."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages; an unknown language still passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never authors tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers; unknown reach never passes."},"maxFollowers":{"type":"integer","minimum":0,"description":"Only authors with at most this many followers; unknown reach never passes."},"isReply":{"type":"boolean","description":"true: only replies and comments; false: only top-level posts."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings; every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings; posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}}},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"updatedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","name","description","filter","createdAt","updatedAt"]},"description":"Saved views, oldest first."}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createView","summary":"Save a view","description":"Save a named filter over mentions. The filter takes the same fields as GET /v1/mentions (lists are any-of, `not` lists none-of, every condition ANDed), plus `anyOf`, groups of those conditions of which at least one must hold; an empty filter is every mention. Nothing is materialized: the view selects whatever matches when it is read.","tags":["Views"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"Unique per workspace, case-insensitive."},"description":{"type":"string","maxLength":500,"default":"","description":"What the view is for, shown under its name."},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Substring in the post text or the author's name."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of any of these keywords."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of these keywords."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of keywords in these groups."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status: open, ignored, done."},"relevant":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Only mentions scored at least this."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments; an unscored mention still passes."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never mentions carrying these tags."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made; false: only the rest."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1)."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages; an unknown language still passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never authors tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers; unknown reach never passes."},"maxFollowers":{"type":"integer","minimum":0,"description":"Only authors with at most this many followers; unknown reach never passes."},"isReply":{"type":"boolean","description":"true: only replies and comments; false: only top-level posts."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings; every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings; posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}},"default":{},"description":"The filter; empty selects every mention."}},"required":["name"]}}}},"responses":{"201":{"description":"The saved view","content":{"application/json":{"schema":{"$ref":"#/components/schemas/View"}}}},"400":{"description":"Invalid filter (an empty anyOf group, for one), or filter_too_complex: more values than one query can carry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A view with that name already exists (duplicate_view)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/views/{id}":{"get":{"operationId":"getView","summary":"Get a view","tags":["Views"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"View id (vw_...).","example":"vw_abc123"},"required":true,"description":"View id (vw_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The view","content":{"application/json":{"schema":{"$ref":"#/components/schemas/View"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such view in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateView","summary":"Update a view","description":"Rename, describe or refilter a view. `filter` replaces the whole filter.","tags":["Views"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"View id (vw_...).","example":"vw_abc123"},"required":true,"description":"View id (vw_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":500},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Substring in the post text or the author's name."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of any of these keywords."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of these keywords."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only matches of keywords of any of these kinds: brand, competitor, topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Only matches of keywords in any of these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Never matches of keywords in these groups."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Only posts from any of these platforms."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"maxItems":20,"description":"Never posts from these platforms."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Only mentions in this status: open, ignored, done."},"relevant":{"type":"boolean","description":"true: only mentions the classifier scored relevant; false: only the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Only mentions scored at least this."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Only these sentiments."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"maxItems":3,"description":"Never these sentiments; an unscored mention still passes."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only mentions carrying any of these intent or topic tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never mentions carrying these tags."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made; false: only the rest."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1)."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Never posts in these languages; an unknown language still passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Never authors tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Never posts linking to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers; unknown reach never passes."},"maxFollowers":{"type":"integer","minimum":0,"description":"Only authors with at most this many followers; unknown reach never passes."},"isReply":{"type":"boolean","description":"true: only replies and comments; false: only top-level posts."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings; every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings; posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}},"description":"Replaces the whole filter."}}}}}},"responses":{"200":{"description":"The updated view","content":{"application/json":{"schema":{"$ref":"#/components/schemas/View"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such view in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A view with that name already exists (duplicate_view)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteView","summary":"Delete a view","description":"Removes the view. No mention is affected.","tags":["Views"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"View id (vw_...).","example":"vw_abc123"},"required":true,"description":"View id (vw_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such view in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/attention":{"get":{"operationId":"listAttention","summary":"List attention items","description":"What needs a person, newest first: a keyword whose mentions spiked in the last hour (mention.spike), whose negative share of the last 24 hours jumped (sentiment.negative_spike), that turned noisy (keyword.noisy), or a channel whose last sends all failed (channel.failing). Detected once an hour; an item opens when its condition starts and resolves on its own when the condition is gone. Open items by default; `status=all` reads the history. Each opening is also an account event of the same name, which webhook, Slack, email and Telegram channels can subscribe to.","tags":["Attention"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["open","resolved","dismissed","all"],"default":"open","description":"open (default), resolved, dismissed, or all."},"required":false,"description":"open (default), resolved, dismissed, or all.","name":"status","in":"query"},{"schema":{"type":"string","description":"Only these kinds, comma separated: mention.spike, sentiment.negative_spike, keyword.noisy, channel.failing."},"required":false,"description":"Only these kinds, comma separated: mention.spike, sentiment.negative_spike, keyword.noisy, channel.failing.","name":"kind","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Items per page, newest first; 50 by default, at most 100."},"required":false,"description":"Items per page, newest first; 50 by default, at most 100.","name":"limit","in":"query"},{"schema":{"type":"string","description":"nextCursor from the previous page."},"required":false,"description":"nextCursor from the previous page.","name":"cursor","in":"query"}],"responses":{"200":{"description":"Attention items","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttentionItem"}},"nextCursor":{"type":"string","nullable":true,"description":"Pass as cursor for the next page; null on the last one."}},"required":["data","nextCursor"]}}}},"400":{"description":"Unknown kind, or a cursor this list did not hand out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/attention/{id}/dismiss":{"post":{"operationId":"dismissAttention","summary":"Dismiss an attention item","description":"Put an item away. It leaves the open list and does not come back while its condition lasts; once the condition clears, a new episode may open a new item. Idempotent.","tags":["Attention"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Attention item id (att_...).","example":"att_abc123"},"required":true,"description":"Attention item id (att_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The dismissed item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttentionItem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such attention item in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/groups":{"get":{"operationId":"listGroups","summary":"List groups","description":"The keyword groups of the workspace, the default group first, then oldest first. A group is how keywords are grouped (a customer, a campaign, a product): a term may be tracked once per group, every keyword belongs to one, and GET /v1/usage/breakdown?by=group says what each group cost. Pass `externalId` to find the group carrying your own id.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Only the group carrying exactly this externalId."},"required":false,"description":"Only the group carrying exactly this externalId.","name":"externalId","in":"query"}],"responses":{"200":{"description":"The groups","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"type":"object","properties":{"context":{"type":"string","nullable":true,"description":"The group's own company description for the classifier, or null for the workspace profile."},"stats":{"type":"object","properties":{"keywords":{"type":"integer","minimum":0,"description":"Keywords in the group, muted ones included."},"active":{"type":"integer","minimum":0,"description":"Keywords in the group that are tracking (not muted)."}},"required":["keywords","active"],"description":"Computed over the group's keywords."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"updatedAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["context","stats","createdAt","updatedAt"]}],"description":"The group the keyword belongs to."},"description":"The workspace's groups, the default first, then oldest first."}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createGroup","summary":"Create a group","description":"Create a keyword group. `name` is unique per workspace; `externalId` (optional, unique too) is your own id for it, a customer id say, so you can find it again without storing ours; `context` (optional) is the group's own company description, which the classifier reads in place of the whole workspace profile for the group's keywords. Then pass the group id as `groupId` when creating a keyword.","tags":["Groups"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"The group's name: a customer, a campaign, a product. Unique per workspace."},"externalId":{"type":"string","nullable":true,"minLength":1,"maxLength":128,"description":"Your own id for the group (a customer id, say). Unique per workspace; find the group by it with GET /v1/groups?externalId=."},"context":{"type":"string","nullable":true,"maxLength":4000,"description":"What the classifier reads as \"the company\" for this group's keywords, in place of the WHOLE workspace profile, its relevance guidelines and competitor list included (at most 4000 characters): who the business is, what it sells, for whom, what is not it, and any rule that should apply to this group (\"ignore job posts\"). For a group per customer, the customer's description. Null: the workspace profile, as for every keyword before groups."}},"required":["name"]}}}},"responses":{"201":{"description":"The new group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A group with that name or externalId already exists (duplicate_group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/groups/{id}":{"get":{"operationId":"getGroup","summary":"Get a group","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Group id (grp_...).","example":"grp_abc123"},"required":true,"description":"Group id (grp_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such group in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateGroup","summary":"Update a group","description":"Rename a group, change your id for it (`externalId`, null clears) or its company description (`context`, null clears: the workspace profile applies again; new mentions are judged with it at once, old ones are not rescored). The default group can be renamed like any other but takes no description: it is the workspace itself and reads the company profile.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Group id (grp_...).","example":"grp_abc123"},"required":true,"description":"Group id (grp_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"The group's name: a customer, a campaign, a product. Unique per workspace."},"externalId":{"type":"string","nullable":true,"minLength":1,"maxLength":128,"description":"Replaces your id for the group; null clears it."},"context":{"type":"string","nullable":true,"maxLength":4000,"description":"Replaces the group's company description; null clears it (the workspace profile applies again). New mentions are judged with it at once; old ones are not rescored. Not on the default group (400 default_group_context): that one is the workspace itself and reads the profile."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"A company description on the default group (default_group_context)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such group in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A group with that name or externalId already exists (duplicate_group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteGroup","summary":"Delete a group and its keywords","description":"Deletes the group and EVERY keyword in it, each the way DELETE /v1/keywords/{id} does (its mentions go with it, alert rules that named it are adjusted; charges already made stay on the usage record). Read the group first: `stats.keywords` says how many go. The default group cannot be deleted: move or delete its keywords instead.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Group id (grp_...).","example":"grp_abc123"},"required":true,"description":"Group id (grp_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted, with its keywords"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such group in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The default group cannot be deleted (default_group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/company":{"get":{"operationId":"getCompany","summary":"Get the company profile","description":"What the classifier knows about you: name, description, use cases, your own accounts, and the composed context it reads.","tags":["Company"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The company profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Company"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Workspace not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateCompany","summary":"Update the company profile","description":"Changing profile fields recomposes the classifier context; setting `context` directly overrides it until the next profile edit. Relevance scores for new mentions follow at once.","tags":["Company"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":1000},"useCases":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Replaces the whole list."},"accounts":{"type":"object","properties":{"x":{"type":"string","nullable":true,"maxLength":60},"linkedin":{"type":"string","nullable":true,"maxLength":200}}},"website":{"type":"string","nullable":true,"maxLength":300,"format":"uri","description":"The company website; null clears it."},"competitors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"maxItems":50,"description":"Replaces the whole list; [] clears it."},"guidelines":{"type":"string","nullable":true,"maxLength":2000,"description":"Free-text rules for the classifier; null clears them."},"context":{"type":"string","maxLength":4000,"description":"Overrides the composed context until the next profile edit."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Company"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Workspace not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/api-keys":{"post":{"operationId":"createApiKey","summary":"Create an API key","description":"Mint a key for this workspace. The key itself is returned once; only its hash is stored. `expiresAt` makes it stop working at an instant (a key for a contractor or a one-off script); it stays listed until revoked.","tags":["API keys"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"A label for the key; \"default\" when omitted."},"scope":{"type":"string","enum":["read","write"],"default":"write","description":"read: GET only. write: everything."},"expiresAt":{"type":"string","description":"When the key stops working (ISO 8601, or epoch ms), for a key handed to a script or a contractor. Must be in the future. Omit or null for a key that never expires.","format":"date-time"}}}}}},"responses":{"201":{"description":"The new key, shown once","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Key id (key_...)."},"name":{"type":"string"},"prefix":{"type":"string","description":"The first characters of the key, to tell keys apart."},"scope":{"type":"string","enum":["read","write"],"description":"read: GET only. write: everything."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"lastUsedAt":{"type":"string","nullable":true,"description":"ISO 8601 timestamp, UTC."},"expiresAt":{"type":"string","nullable":true,"description":"When the key stops working; null for a key that never expires. An expired key stays listed until revoked."},"key":{"type":"string","description":"The full key. Shown once; store it now."}},"required":["id","name","prefix","scope","createdAt","lastUsedAt","expiresAt","key"]}}}},"400":{"description":"expiresAt is not in the future","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listApiKeys","summary":"List API keys","tags":["API keys"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Every key, newest first, without the secret part","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Key id (key_...)."},"name":{"type":"string"},"prefix":{"type":"string","description":"The first characters of the key, to tell keys apart."},"scope":{"type":"string","enum":["read","write"],"description":"read: GET only. write: everything."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"lastUsedAt":{"type":"string","nullable":true,"description":"ISO 8601 timestamp, UTC."},"expiresAt":{"type":"string","nullable":true,"description":"When the key stops working; null for a key that never expires. An expired key stays listed until revoked."}},"required":["id","name","prefix","scope","createdAt","lastUsedAt","expiresAt"]}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/api-keys/{id}":{"delete":{"operationId":"revokeApiKey","summary":"Revoke an API key","description":"Takes effect at once on the API and within a few minutes on cached verifications.","tags":["API keys"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"API key id (key_...).","example":"key_abc123"},"required":true,"description":"API key id (key_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Revoked"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/whoami":{"get":{"operationId":"whoami","summary":"Introspect the credential","description":"The workspace this credential acts on, how the request authenticated (an API key, an OAuth access token from an MCP sign-in, or the dashboard session), whether it may write, and for a key its id and expiry. Run it first: a read key answers 403 read_only_key on every write, and a wrong workspace is the classic scripting mistake.","tags":["Auth"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Whoami"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members":{"get":{"operationId":"listMembers","summary":"List members","description":"Everyone in the workspace, owners first. `userId` is what a mention's assigneeId and a person's ownerId take.","tags":["Members"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The members","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members/invitations":{"get":{"operationId":"listInvitations","summary":"List pending invitations","description":"Invitations sent and not yet accepted, declined or expired. An accepted one appears in GET /v1/members instead.","tags":["Members"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The open invitations","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invitation"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createInvitation","summary":"Invite a member","description":"Send an email invitation to join the workspace as admin or member; it expires after 48 hours. Idempotent: an address that already holds an open invitation gets it back with 200 and no second email. An address that is already a member is a 409 already_member. Team changes need a signed-in owner or admin (an OAuth token from an MCP sign-in, or the dashboard session): an API key answers 403.","tags":["Members"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":200,"format":"email","description":"The address to invite; it receives an email with a link to join."},"role":{"type":"string","enum":["admin","member"],"default":"member","description":"The role they join with. Ownership is only handed over in the dashboard."}},"required":["email"]}}}},"responses":{"200":{"description":"The open invitation this address already had","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"201":{"description":"The invitation, emailed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential is an API key, or its person is not an owner or admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The address is already a member (already_member)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members/invitations/{id}":{"delete":{"operationId":"revokeInvitation","summary":"Revoke an invitation","description":"The link in the email stops working at once. Needs a signed-in owner or admin; an API key answers 403.","tags":["Members"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Invitation id (inv_...).","example":"inv_abc123"},"required":true,"description":"Invitation id (inv_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Revoked"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential is an API key, or its person is not an owner or admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No open invitation with that id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members/{id}":{"delete":{"operationId":"removeMember","summary":"Remove a member","description":"The person loses the workspace within a minute (their dashboard session on the next request, an OAuth token when its short cache lapses). Their mentions, notes and outreach stay. Needs a signed-in owner or admin; only an owner removes another owner, and the last owner cannot be removed (409 last_owner).","tags":["Members"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Membership id (mem_...).","example":"mem_abc123"},"required":true,"description":"Membership id (mem_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Removed"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The credential is an API key, its person is not an owner or admin, or an admin tried to remove an owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Member not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The last owner cannot be removed (last_owner)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/usage":{"get":{"operationId":"getUsage","summary":"Get usage and balance","description":"The prepaid balance (ledger, pending mention charges, and the effective balance the stop rule reads), the daily burn and the days it buys, the keywords the wallet runs and pauses, the matches recorded today and over 30 days, and whether tracking is stopped or the balance is low. Every matched mention bills ($0.008), relevant or not; every active keyword bills $5 a month, charged daily.","tags":["Usage"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The usage summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/usage/breakdown":{"get":{"operationId":"getUsageBreakdown","summary":"Get the usage breakdown","description":"What the workspace consumed and was charged over a window, grouped by one dimension per call (`by`: day, platform or keyword), in USD cents at list price, with the window's totals on every call. `range` reads a trailing window of UTC days ending today (default 30d); `month` reads one calendar month (YYYY-MM), the shape a bill or a per-customer margin is reconciled against. Keyword-days come from the daily tick and mention charges from the matches that billed, so a deleted keyword keeps its charges in the keyword rows (`keyword.removed`) while its mention counts read 0; the same numbers ride on each keyword as `stats.cost` for the running month. `totals.ledgerDebitCents` is what the wallet has debited so far for the window's days: mentions settle the morning after their day, so a window ending today lags `totals.totalCents` by the unsettled ones, and a closed month differs from it only by cumulative rounding. Rows are paged (`limit`, `offset`, `total`); a workspace may read this at most 30 times a minute through its keys and tokens together.","tags":["Usage"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["day","platform","keyword","group"],"default":"keyword","description":"The dimension to group by: day (one row per UTC day of the window), platform, keyword (default: the row a margin is computed from), or group (what a customer or a campaign cost)."},"required":false,"description":"The dimension to group by: day (one row per UTC day of the window), platform, keyword (default: the row a margin is computed from), or group (what a customer or a campaign cost).","name":"by","in":"query"},{"schema":{"type":"string","enum":["7d","30d","90d"],"description":"Trailing window of UTC days ending today: 7d, 30d, 90d (default 30d). Ignored when `month` is given."},"required":false,"description":"Trailing window of UTC days ending today: 7d, 30d, 90d (default 30d). Ignored when `month` is given.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","description":"A calendar month (YYYY-MM, UTC) instead of a trailing window: from its first day to its last, or to today for the running month. A future month is a 400."},"required":false,"description":"A calendar month (YYYY-MM, UTC) instead of a trailing window: from its first day to its last, or to today for the running month. A future month is a 400.","name":"month","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"Rows per page, 1 to 500 (default 100). Only by=keyword can outgrow a page; a window has at most 90 days and a dozen platforms."},"required":false,"description":"Rows per page, 1 to 500 (default 100). Only by=keyword can outgrow a page; a window has at most 90 days and a dozen platforms.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"default":0,"description":"Skip this many rows."},"required":false,"description":"Skip this many rows.","name":"offset","in":"query"}],"responses":{"200":{"description":"The window's totals and one page of rows for the dimension","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageBreakdown"}}}},"400":{"description":"Unknown dimension or range, month malformed or in the future, limit out of range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"More than 30 breakdown reads this minute for the workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/top-ups":{"post":{"operationId":"createTopUp","summary":"Create a top-up checkout","description":"Returns a hosted checkout URL with `amountCents` prefilled (editable there, $20 to $5,000). The balance is credited when the payment lands, within a minute, and tracking the wallet had paused resumes at once. Nothing is charged by this call itself. `successUrl` must be on an origin this deployment trusts; omit it for the dashboard's billing page.","tags":["Billing"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":2000,"maximum":500000,"description":"Amount to add, in USD cents (2000 to 500000). Prefilled at checkout, editable there."},"successUrl":{"type":"string","maxLength":2000,"format":"uri","description":"Where the customer lands after paying: a page on an origin this deployment trusts (the dashboard). Omit it and the dashboard's billing page is used."}},"required":["amountCents"]}}}},"responses":{"200":{"description":"Hosted checkout URL with the amount prefilled","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Hosted Polar checkout URL."}},"required":["url"]}}}},"400":{"description":"Invalid amount or disallowed successUrl","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Workspace has no owner to bill","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"More than a few checkouts a minute for one workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Billing is not configured on this deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/wallet":{"get":{"operationId":"getWallet","summary":"Get the wallet","description":"The prepaid balance in full: ledger, pending mention charges and the effective balance the stop rule reads, the daily burn and the days it buys, how many keywords run and how many the wallet paused, what a day costs and what a resume needs, the welcome credit, the newest top-up, the top-up bounds and the auto-recharge settings. `GET /v1/usage` is the short form.","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Balance, burn, and whether tracking is paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/ledger":{"get":{"operationId":"listLedger","summary":"List ledger entries","description":"Every movement of the balance, newest first: the welcome credit, top-ups, refunds, the daily keyword-day and mention debits, adjustments. A debit row carries the UTC day it settled and the cumulative units behind it. Cursor paged.","tags":["Billing"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Opaque cursor from a previous page (`nextCursor`)."},"required":false,"description":"Opaque cursor from a previous page (`nextCursor`).","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Page size, 1 to 100 (default 25).","example":25},"required":false,"description":"Page size, 1 to 100 (default 25).","name":"limit","in":"query"}],"responses":{"200":{"description":"Ledger entries, newest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerList"}}}},"400":{"description":"Invalid cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/invoices":{"get":{"operationId":"listInvoices","summary":"List receipts","description":"The orders behind the top-ups, newest first, as the merchant of record (Polar) holds them: this workspace's share of the billing customer's newest 100 orders. Empty before the first top-up.","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Recent paid orders (receipts). Empty when the org has never paid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceList"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/invoices/{id}/url":{"get":{"operationId":"getInvoiceUrl","summary":"Get a receipt link","description":"A short-lived link to the receipt PDF of one paid order (an id from the receipts list).","tags":["Billing"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The order id from GET /v1/billing/invoices."},"required":true,"description":"The order id from GET /v1/billing/invoices.","name":"id","in":"path"}],"responses":{"200":{"description":"A short-lived link to the receipt PDF","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A short-lived link to the receipt PDF."}},"required":["url"]}}}},"401":{"description":"Missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such receipt, or its PDF is not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Billing is not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}":{"get":{"operationId":"getAlert","summary":"Get an alert","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The alert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Alert not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateAlert","summary":"Update an alert","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"enabled":{"type":"boolean"},"mode":{"type":"string","enum":["instant","hourly","daily","weekly"]},"filter":{"type":"object","properties":{"keywordIds":{"type":"array","items":{"type":"string"},"description":"Only these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Only keywords in these groups (grp_...): one rule per customer, say."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"description":"Only posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The rule's relevance floor. Absent, it sends relevant mentions only (scored 40 and up, the classifier's line); lower, down to 0, it also receives the matches the classifier scored as noise; higher, it hears less. Email channels keep the 40 line whatever the rule says. Unclassified mentions never pass."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. A mention without a confidence never passes."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"description":"Only these sentiments."},"intents":{"type":"array","items":{"type":"string"},"description":"At least one of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). A post with no links never passes."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made (bots, templated posts); false: only the rest. Omit for both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): [1, 2] sends the unhappy ones. Every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): [5] keeps the five star reviews out. Posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}},"description":"Replaces the whole filter."},"schedule":{"type":"object","nullable":true,"properties":{"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59,"default":0},"timezone":{"type":"string","minLength":1,"maxLength":64},"skipEmpty":{"type":"boolean","default":true},"weekday":{"type":"integer","minimum":0,"maximum":6,"description":"Weekly rules: the day it sends, 0 Sunday to 6 Saturday. Required for mode weekly; ignored on daily rules."}},"required":["hour","timezone"],"description":"Daily and weekly alerts. Ignored on an hourly one, except a weekday, which is refused."},"event":{"type":"string","nullable":true,"maxLength":60,"pattern":"^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$"},"channelIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":20,"description":"Replaces the whole list."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"400":{"description":"A daily or weekly rule without a schedule (or a weekly one without a weekday), an hourly one with a weekday or an email channel (hourly_email_unsupported), or an unknown channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteAlert","summary":"Delete an alert","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts":{"get":{"operationId":"listAlerts","summary":"List alerts","tags":["Alerts"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Every alert rule of the org, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Alert id (feed_...)."},"name":{"type":"string"},"enabled":{"type":"boolean"},"mode":{"type":"string","enum":["instant","hourly","daily","weekly"],"description":"instant: each matching mention as it happens. hourly: one digest each UTC hour (five minutes past, so the last mentions of the hour are scored) covering the previous full hour, nothing when that hour has no mention at or over the rule's relevance floor; Slack, Telegram and webhook channels only. daily: one digest at the scheduled local time. weekly: one digest a week, on schedule.weekday."},"filter":{"type":"object","properties":{"keywordIds":{"type":"array","items":{"type":"string"},"description":"Only these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Only keywords in these groups (grp_...): one rule per customer, say."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"description":"Only posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The rule's relevance floor. Absent, it sends relevant mentions only (scored 40 and up, the classifier's line); lower, down to 0, it also receives the matches the classifier scored as noise; higher, it hears less. Email channels keep the 40 line whatever the rule says. Unclassified mentions never pass."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. A mention without a confidence never passes."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"description":"Only these sentiments."},"intents":{"type":"array","items":{"type":"string"},"description":"At least one of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). A post with no links never passes."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made (bots, templated posts); false: only the rest. Omit for both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): [1, 2] sends the unhappy ones. Every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): [5] keeps the five star reviews out. Posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}}},"schedule":{"type":"object","nullable":true,"properties":{"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59,"default":0},"timezone":{"type":"string","minLength":1,"maxLength":64},"skipEmpty":{"type":"boolean","default":true},"weekday":{"type":"integer","minimum":0,"maximum":6,"description":"Weekly rules: the day it sends, 0 Sunday to 6 Saturday. Required for mode weekly; ignored on daily rules."}},"required":["hour","timezone"],"description":"Daily and weekly alerts only; null for instant and hourly ones."},"event":{"type":"string","description":"Event name carried in webhook payloads; the mode default unless you set one."},"channels":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["slack","email","webhook","telegram"]},"label":{"type":"string"}},"required":["id","kind","label"]},"description":"Where it sends."},"stats":{"type":"object","properties":{"sentLast7d":{"type":"integer","minimum":0,"description":"Deliveries in the last 7 days, across channels."},"lastSentAt":{"type":"string","nullable":true,"description":"ISO 8601 timestamp, UTC."},"nextRunAt":{"type":"string","nullable":true,"description":"Hourly, daily and weekly alerts: the next digest; null when disabled or instant."}},"required":["sentLast7d","lastSentAt","nextRunAt"],"description":"Computed over this workspace's deliveries."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."}},"required":["id","name","enabled","mode","filter","schedule","event","channels","stats","createdAt"]}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createAlert","summary":"Create an alert","description":"A rule (what to watch, the filter) times channels. mode instant sends each matching mention as it happens; hourly sends one digest every UTC hour (five minutes past) for the previous full hour, nothing when it had no mention over the rule's floor, to Slack, Telegram and webhook channels only (no schedule); daily sends one digest at schedule.hour in schedule.timezone; weekly sends one a week on schedule.weekday (0 Sunday to 6 Saturday). filter.anyOf adds OR: groups of conditions in the vocabulary of the mentions list, at least one of which must hold on top of the rest of the filter.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"enabled":{"type":"boolean","default":true},"mode":{"type":"string","enum":["instant","hourly","daily","weekly"],"default":"instant"},"filter":{"type":"object","properties":{"keywordIds":{"type":"array","items":{"type":"string"},"description":"Only these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Only keywords in these groups (grp_...): one rule per customer, say."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place)."},"description":"Only posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The rule's relevance floor. Absent, it sends relevant mentions only (scored 40 and up, the classifier's line); lower, down to 0, it also receives the matches the classifier scored as noise; higher, it hears less. Email channels keep the 40 line whatever the rule says. Unclassified mentions never pass."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Only mentions whose classifier confidence is at least this, 0 to 1. A mention without a confidence never passes."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"Classifier sentiment."},"description":"Only these sentiments."},"intents":{"type":"array","items":{"type":"string"},"description":"At least one of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Never these authors: display names, handles or profile URLs."},"minFollowers":{"type":"integer","minimum":0,"description":"Only authors with at least this many followers. Unknown reach never passes."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Only authors your workspace tagged with any of these."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Only posts linking to any of these hosts, the host itself or a subdomain of it (octolens.com also matches blog.octolens.com). A post with no links never passes."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Only posts in any of these languages (ISO 639-1: en, es, de). A post whose language is unknown never passes."},"automated":{"type":"boolean","description":"true: only posts that read as machine-made (bots, templated posts); false: only the rest. Omit for both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Only app store reviews with any of these star ratings (1 to 5): [1, 2] sends the unhappy ones. Every other post fails it."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Never reviews with these star ratings (1 to 5): [5] keeps the five star reviews out. Posts that are not reviews still pass."},"minLikes":{"type":"integer","minimum":0,"description":"Only posts with at least this many likes (upvotes, reactions), as the platform reported them when the post was found. A post without that count never passes."},"minReposts":{"type":"integer","minimum":0,"description":"Only posts with at least this many reposts (shares, retweets), as the platform reported them when the post was found. A post without that count never passes."},"minReplies":{"type":"integer","minimum":0,"description":"Only posts with at least this many replies (comments), as the platform reported them when the post was found. A post without that count never passes."},"minQuotes":{"type":"integer","minimum":0,"description":"Only posts with at least this many quotes, as the platform reported them when the post was found. A post without that count never passes."},"minViews":{"type":"integer","minimum":0,"description":"Only posts with at least this many views (plays), as the platform reported them when the post was found. A post without that count never passes."},"minBookmarks":{"type":"integer","minimum":0,"description":"Only posts with at least this many bookmarks (saves), as the platform reported them when the post was found. A post without that count never passes."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"OR across groups: a mention passes when it meets every condition of at least one group (1 to 10 groups). The other conditions still apply to every mention: the whole filter is (other conditions) AND (group 1 OR group 2 ...). A group takes the conditions of a view filter (platforms, sentiments, intents, keywordKinds, the not lists ...), with no anyOf of its own."}},"default":{}},"schedule":{"type":"object","properties":{"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59,"default":0},"timezone":{"type":"string","minLength":1,"maxLength":64},"skipEmpty":{"type":"boolean","default":true},"weekday":{"type":"integer","minimum":0,"maximum":6,"description":"Weekly rules: the day it sends, 0 Sunday to 6 Saturday. Required for mode weekly; ignored on daily rules."}},"required":["hour","timezone"],"description":"Required for daily and weekly alerts (weekly ones also need schedule.weekday). Hourly alerts take none: they send every UTC hour, so a time of day and a zone are ignored and a weekday is refused."},"event":{"type":"string","nullable":true,"maxLength":60,"pattern":"^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$","description":"Custom event name for webhook payloads; null for the mode default."},"channelIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":20,"default":[],"description":"Channel ids from GET /v1/channels."}},"required":["name"]}}}},"responses":{"201":{"description":"The created rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"400":{"description":"A daily or weekly rule without a schedule (or a weekly one without a weekday), an hourly one with a weekday or an email channel (hourly_email_unsupported), an unknown channel, or anyOf groups binding more values than one query can carry (filter_too_complex)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/test":{"post":{"operationId":"testAlert","summary":"Send a test through an alert's channels","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"responses":{"200":{"description":"A test message was attempted on every channel of the rule","content":{"application/json":{"schema":{"type":"object","properties":{"outcomes":{"type":"array","items":{"type":"object","properties":{"channelId":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"string","nullable":true}},"required":["channelId","ok","error"]}}},"required":["outcomes"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/run":{"post":{"operationId":"runAlertDigest","summary":"Send a digest now","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The digest for the rule's own period (the last hour, day or week) was sent now (the scheduled one still runs)","content":{"application/json":{"schema":{"type":"object","properties":{"skipped":{"type":"string","nullable":true,"enum":["already_sent","empty","expired","in_flight"],"description":"Why nothing was sent, if nothing was: the period already went out, the window had nothing to show, (hourly rules) the hour's retry window closed before it could send, or another run of the same period is sending it right now."},"matched":{"type":"integer"},"relevant":{"type":"integer"},"outcomes":{"type":"array","items":{"type":"object","properties":{"channelId":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"string","nullable":true}},"required":["channelId","ok","error"]}}},"required":["skipped","matched","relevant","outcomes"]}}}},"400":{"description":"Only hourly, daily and weekly rules have a digest","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/mute":{"post":{"operationId":"muteAlertAuthors","summary":"Mute authors on an alert","description":"Add authors to the alert's muted list without touching the rest of its filter. Links are read the way the dashboard reads them: a post link mutes its author, twitter.com becomes x.com, a Hacker News profile keeps its id. Authors already muted are skipped, so a retry is safe. An entry that names no person (a subreddit, a story) rejects the request with that entry named.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"authors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"minItems":1,"maxItems":50,"description":"Profile or post links (x.com/name, linkedin.com/in/name, reddit.com/user/name, a post URL), handles (@name, u/name), Bluesky DIDs or display names. A link is stored as the author's profile; a plain name or handle matches that name on every platform."}},"required":["authors"],"description":"Authors to add to or remove from the alert's muted list."}}}},"responses":{"200":{"description":"The alert, with its muted list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"400":{"description":"An entry names no person, or the alert would mute more than 200 authors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/unmute":{"post":{"operationId":"unmuteAlertAuthors","summary":"Unmute authors on an alert","description":"Remove authors from the alert's muted list without touching the rest of its filter. Name each one by the stored entry or by any link to that profile or its posts. Authors that are not muted are ignored, so a retry is safe.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Alert id (feed_...).","example":"feed_abc123"},"required":true,"description":"Alert id (feed_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"authors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"minItems":1,"maxItems":50,"description":"Profile or post links (x.com/name, linkedin.com/in/name, reddit.com/user/name, a post URL), handles (@name, u/name), Bluesky DIDs or display names. A link is stored as the author's profile; a plain name or handle matches that name on every platform."}},"required":["authors"],"description":"Authors to add to or remove from the alert's muted list."}}}},"responses":{"200":{"description":"The alert, with its muted list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/summary":{"get":{"operationId":"getAnalyticsSummary","summary":"Headline counts for a window","description":"Matched and relevant mentions, distinct posts and people, sentiment, buying intent and questions, estimated reach, and where the matches stand in triage. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"Preset window ending today. Ignored when from or to is given. Default 30d."},"required":false,"description":"Preset window ending today. Ignored when from or to is given. Default 30d.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, YYYY-MM-DD, inclusive, in `timezone`."},"required":false,"description":"First day, YYYY-MM-DD, inclusive, in `timezone`.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today."},"required":false,"description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword."},"required":false,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword.","name":"keywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"]},"maxItems":20,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform."},"required":false,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the period of the same length right before the window as `previous`."},"required":false,"description":"true adds the period of the same length right before the window as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window."},"required":false,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.","name":"timezone","in":"query"}],"responses":{"200":{"description":"The counts, with `previous` when comparing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSummary"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/series":{"get":{"operationId":"getAnalyticsSeries","summary":"Mentions over time","description":"Matched, relevant and sentiment counts per day or week across the window, as one total series or split per platform or per keyword with `by`. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"Preset window ending today. Ignored when from or to is given. Default 30d."},"required":false,"description":"Preset window ending today. Ignored when from or to is given. Default 30d.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, YYYY-MM-DD, inclusive, in `timezone`."},"required":false,"description":"First day, YYYY-MM-DD, inclusive, in `timezone`.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today."},"required":false,"description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword."},"required":false,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword.","name":"keywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"]},"maxItems":20,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform."},"required":false,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the period of the same length right before the window as `previous`."},"required":false,"description":"true adds the period of the same length right before the window as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window."},"required":false,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["hour","day","week","month"],"description":"Point granularity: hour (windows of at most 14 days), day, week (Monday start) or month. Default: day up to 90 days, week beyond."},"required":false,"description":"Point granularity: hour (windows of at most 14 days), day, week (Monday start) or month. Default: day up to 90 days, week beyond.","name":"bucket","in":"query"},{"schema":{"type":"string","enum":["platform","keyword","sentiment"],"description":"Split into one series per platform, per keyword (the top 20 by matched, the rest folded into \"other\") or per sentiment (positive, neutral, negative, unclassified). Omit for one total series."},"required":false,"description":"Split into one series per platform, per keyword (the top 20 by matched, the rest folded into \"other\") or per sentiment (positive, neutral, negative, unclassified). Omit for one total series.","name":"by","in":"query"}],"responses":{"200":{"description":"Zero-filled series, oldest point first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSeries"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/breakdown":{"get":{"operationId":"getAnalyticsBreakdown","summary":"Mentions grouped by one dimension","description":"One table of matched, relevant and sentiment counts grouped by `by`: platform, keyword, sentiment, intent, status, hour (weekday and hour of day) or person. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"Preset window ending today. Ignored when from or to is given. Default 30d."},"required":false,"description":"Preset window ending today. Ignored when from or to is given. Default 30d.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, YYYY-MM-DD, inclusive, in `timezone`."},"required":false,"description":"First day, YYYY-MM-DD, inclusive, in `timezone`.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today."},"required":false,"description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword."},"required":false,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword.","name":"keywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"]},"maxItems":20,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform."},"required":false,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the period of the same length right before the window as `previous`."},"required":false,"description":"true adds the period of the same length right before the window as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window."},"required":false,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["platform","keyword","sentiment","intent","status","hour","person","language"],"description":"The dimension to group by: platform, keyword, sentiment (unclassified included), intent (a mention can carry several), status (open, ignored, done), hour (weekday and hour of day in `timezone`), person (who posted; anonymous posts are left out), language (ISO 639-1; \"unknown\" for posts without one)."},"required":true,"description":"The dimension to group by: platform, keyword, sentiment (unclassified included), intent (a mention can carry several), status (open, ignored, done), hour (weekday and hour of day in `timezone`), person (who posted; anonymous posts are left out), language (ISO 639-1; \"unknown\" for posts without one).","name":"by","in":"query"}],"responses":{"200":{"description":"Groups, most matched first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsBreakdown"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/share-of-voice":{"get":{"operationId":"getShareOfVoice","summary":"Brand against competitors","description":"Every keyword matched in the window with its counts and its share of brand plus competitor matches; topic keywords are counted but stay out of the split. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"Preset window ending today. Ignored when from or to is given. Default 30d."},"required":false,"description":"Preset window ending today. Ignored when from or to is given. Default 30d.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, YYYY-MM-DD, inclusive, in `timezone`."},"required":false,"description":"First day, YYYY-MM-DD, inclusive, in `timezone`.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today."},"required":false,"description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword."},"required":false,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword.","name":"keywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"]},"maxItems":20,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform."},"required":false,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the period of the same length right before the window as `previous`."},"required":false,"description":"true adds the period of the same length right before the window as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window."},"required":false,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.","name":"timezone","in":"query"}],"responses":{"200":{"description":"Keywords, most matched first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareOfVoice"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/reviews":{"get":{"operationId":"getReviewsReport","summary":"Reviews: stars over a window, per review page","description":"The reviews a keyword collects (App Store, Google Play, Trustpilot, Google Maps): count, average stars, distribution, replies and open 1-2 star reviews, for the workspace and per review page with a series of average stars per `bucket`, plus the tags the unhappy reviews carry. A review matched by two keywords counts once. The window is `range` (7d, 30d, 90d, 365d, ending today) or `from` and `to`, cut into days in `timezone` (UTC by default); `keywordIds` and `platforms` narrow it; `compare=true` adds the period of the same length right before it. Time axis is the publish date.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"Preset window ending today. Ignored when from or to is given. Default 30d."},"required":false,"description":"Preset window ending today. Ignored when from or to is given. Default 30d.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First day, YYYY-MM-DD, inclusive, in `timezone`."},"required":false,"description":"First day, YYYY-MM-DD, inclusive, in `timezone`.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today."},"required":false,"description":"Last day, YYYY-MM-DD, inclusive, in `timezone`. Default today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword."},"required":false,"description":"Only these keyword ids. Repeatable, or comma-separated; omit for every keyword.","name":"keywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"]},"maxItems":20,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform."},"required":false,"description":"Only these platforms. Repeatable, or comma-separated; omit for every platform.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the period of the same length right before the window as `previous`."},"required":false,"description":"true adds the period of the same length right before the window as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window."},"required":false,"description":"IANA zone the days are cut in (Europe/Madrid). Default UTC. One offset, the zone's at the end of the window, applies to the whole window.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["day","week"],"description":"Series bucket: day (default up to 90 days) or week."},"required":false,"description":"Series bucket: day (default up to 90 days) or week.","name":"bucket","in":"query"}],"responses":{"200":{"description":"The report, with `previous` when comparing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewsReport"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}":{"get":{"operationId":"getChannel","summary":"Get a channel","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Channel id (dest_...).","example":"dest_abc123"},"required":true,"description":"Channel id (dest_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateChannel","summary":"Update a channel","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Channel id (dest_...).","example":"dest_abc123"},"required":true,"description":"Channel id (dest_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":80},"url":{"type":"string","format":"uri","description":"Webhooks only."},"headers":{"type":"object","additionalProperties":{"type":"string","maxLength":1024},"description":"Webhooks only; replaces the whole set."},"events":{"type":"array","items":{"type":"string","enum":["keyword.capped","keyword.paused_for_balance","keyword.resumed","wallet.low","wallet.paused","wallet.resumed","mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"keyword.capped: a keyword reached its monthly mention cap and stopped matching. keyword.paused_for_balance: the wallet ran out and paused it. keyword.resumed: it listens again (reason says why). wallet.low: the effective balance fell to 20% of the last credit (once per credit). wallet.paused: the wallet paused every keyword. wallet.resumed: a credit brought them back. The attention events, sent once when an item opens (GET /v1/attention): mention.spike: a keyword got far more mentions in the last hour than it usually does. sentiment.negative_spike: its negative share of the last 24 hours jumped. keyword.noisy: most of its scored matches are noise. channel.failing: a channel's last sends all failed."},"maxItems":10,"description":"Replaces the whole set of account events the channel receives. A webhook takes any of them; a Slack, email or Telegram channel the attention events only (mention.spike, sentiment.negative_spike, keyword.noisy, channel.failing). An empty list unsubscribes it from all of them."}},"description":"Omitted fields are untouched."}}}},"responses":{"200":{"description":"The updated channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"400":{"description":"An event this kind of channel cannot receive: Slack, email and Telegram take the attention events only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteChannel","summary":"Delete a channel","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Channel id (dest_...).","example":"dest_abc123"},"required":true,"description":"Channel id (dest_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}/test":{"post":{"operationId":"testChannel","summary":"Send a test to a channel","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Channel id (dest_...).","example":"dest_abc123"},"required":true,"description":"Channel id (dest_...).","name":"id","in":"path"}],"responses":{"200":{"description":"A test message was attempted on the channel (webhooks receive event \"test\")","content":{"application/json":{"schema":{"type":"object","properties":{"outcomes":{"type":"array","items":{"type":"object","properties":{"channelId":{"type":"string"},"ok":{"type":"boolean"},"error":{"type":"string","nullable":true}},"required":["channelId","ok","error"]}}},"required":["outcomes"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"Rotate a webhook secret","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Channel id (dest_...).","example":"dest_abc123"},"required":true,"description":"Channel id (dest_...).","name":"id","in":"path"}],"responses":{"200":{"description":"A new signing secret, shown once. The previous one stops verifying immediately.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}/deliveries":{"get":{"operationId":"listChannelDeliveries","summary":"List deliveries to a channel","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Channel id (dest_...).","example":"dest_abc123"},"required":true,"description":"Channel id (dest_...).","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"What the channel received, newest first: instant mentions and digest runs, with status and last error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Delivery id (dlv_...), also the webhook payload id."},"kind":{"type":"string","enum":["mention","digest","event"],"description":"mention: an instant rule's delivery. digest: a daily or weekly summary. event: an account event the channel subscribed to."},"event":{"type":"string","description":"The event name the payload carried: the rule's (mention.matched unless it set one, digest for a summary) or the account event's."},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"error":{"type":"string","nullable":true,"description":"The last failure, when there was one."},"sentAt":{"type":"string","nullable":true,"description":"ISO 8601 timestamp, UTC."},"createdAt":{"type":"string","description":"ISO 8601 timestamp, UTC."},"alert":{"type":"object","properties":{"name":{"type":"string","nullable":true}},"required":["name"],"description":"The alert that produced it; name only, since alerts can be deleted. name is null for an account event, which no rule produces."},"mention":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"url":{"type":"string"},"text":{"type":"string"}},"required":["id","url","text"],"description":"For mention deliveries: the post, text cut to 160 characters."}},"required":["id","kind","event","status","attempts","error","sentAt","createdAt","alert","mention"]}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels":{"get":{"operationId":"listChannels","summary":"List channels","tags":["Alerts"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Every channel of the org","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/SlackChannel"},{"$ref":"#/components/schemas/EmailChannel"},{"$ref":"#/components/schemas/WebhookChannel"},{"$ref":"#/components/schemas/TelegramChannel"}],"discriminator":{"propertyName":"kind","mapping":{"slack":"#/components/schemas/SlackChannel","email":"#/components/schemas/EmailChannel","webhook":"#/components/schemas/WebhookChannel","telegram":"#/components/schemas/TelegramChannel"}}}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createChannel","summary":"Create a channel","tags":["Alerts"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CreateSlackChannel"},{"$ref":"#/components/schemas/CreateEmailChannel"},{"$ref":"#/components/schemas/CreateWebhookChannel"}],"discriminator":{"propertyName":"kind","mapping":{"slack":"#/components/schemas/CreateSlackChannel","email":"#/components/schemas/CreateEmailChannel","webhook":"#/components/schemas/CreateWebhookChannel"}}}}}},"responses":{"201":{"description":"The created channel. A webhook includes its signing secret, shown only here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"400":{"description":"An event this kind of channel cannot receive: Slack, email and Telegram take the attention events only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Slack is not connected for this org","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"x-rumoro-errors":[{"code":"unauthorized","status":401,"source":"user","retryable":false,"description":"No credential, or one that does not resolve to a workspace.","fix":"Send Authorization: Bearer ref_… with a key from /api-keys."},{"code":"forbidden","status":403,"source":"user","retryable":false,"description":"The credential is valid but may not do this."},{"code":"read_only_key","status":403,"source":"user","retryable":false,"description":"A read key was used on a write endpoint.","fix":"Create a key with write scope."},{"code":"validation_error","status":400,"source":"user","retryable":false,"description":"The body or query failed validation; the message names the field."},{"code":"not_found","status":404,"source":"user","retryable":false,"description":"No such resource in your workspace. An id from another workspace is a 404, never a 403."},{"code":"invalid_cursor","status":400,"source":"user","retryable":false,"description":"The cursor was not one this endpoint issued, or the filters changed between pages."},{"code":"payload_too_large","status":413,"source":"user","retryable":false,"description":"The body exceeds the endpoint limit."},{"code":"rate_limited","status":429,"source":"user","retryable":true,"description":"The workspace made more than 600 requests in a minute (every key and token together), or hit an endpoint's own cap; Retry-After says when.","fix":"Wait Retry-After seconds and send the same request again. X-RateLimit-Remaining on every response says how much room is left."},{"code":"duplicate_keyword","status":409,"source":"user","retryable":false,"description":"The group already tracks this term. A term may be tracked once per group; another group may track it too."},{"code":"insufficient_balance","status":402,"source":"user","retryable":false,"description":"The wallet cannot cover one more keyword-day.","fix":"Top up from Billing; tracking resumes on its own."},{"code":"keyword_limit_reached","status":402,"source":"user","retryable":false,"description":"The self-serve keyword cap; beyond it is an enterprise conversation."},{"code":"billing_not_configured","status":503,"source":"system","retryable":false,"description":"This deployment has no payment provider set up."},{"code":"schedule_required","status":400,"source":"user","retryable":false,"description":"A daily alert rule was created without a schedule."},{"code":"unknown_channel","status":400,"source":"user","retryable":false,"description":"A rule referenced a channel id the workspace does not own."},{"code":"not_a_digest","status":400,"source":"user","retryable":false,"description":"A digest-only action was called on an instant rule."},{"code":"hourly_email_unsupported","status":400,"source":"user","retryable":false,"description":"An hourly rule was given an email channel (up to 24 emails a day per rule). Use Slack, Telegram or a webhook, or a daily digest by email."},{"code":"slack_not_connected","status":409,"source":"user","retryable":false,"description":"Connect Slack from Settings first. 404 on the Slack connection endpoints, 409 elsewhere."},{"code":"slack_not_configured","status":503,"source":"system","retryable":false,"description":"This deployment has no Slack app credentials."},{"code":"telegram_not_configured","status":503,"source":"system","retryable":false,"description":"This deployment has no Telegram bot."},{"code":"email_not_configured","status":503,"source":"system","retryable":false,"description":"This deployment has no Resend key, so nothing that needs Resend (the audience sync) can run."},{"code":"invalid_assignee","status":400,"source":"user","retryable":false,"description":"The assignee id is not a workspace member."},{"code":"classification_pending","status":409,"source":"user","retryable":true,"description":"A relevance or sentiment verdict was sent for a mention the classifier has not scored yet."},{"code":"invalid_member","status":400,"source":"user","retryable":false,"description":"A person's owner, and the member an outreach activity is credited to, must be workspace members."},{"code":"already_member","status":409,"source":"user","retryable":false,"description":"An invitation was sent to an address that already belongs to a member."},{"code":"last_owner","status":409,"source":"user","retryable":false,"description":"Removing this member would leave the workspace without an owner."},{"code":"duplicate_segment","status":409,"source":"user","retryable":false,"description":"Segment names are unique per workspace."},{"code":"filter_too_complex","status":400,"source":"user","retryable":false,"description":"The filters together (lists, anyOf groups, a view or alert rule applied on top) name more values than one query can carry. Shorten the lists or use fewer groups."},{"code":"duplicate_view","status":409,"source":"user","retryable":false,"description":"View names are unique per workspace."},{"code":"duplicate_group","status":409,"source":"user","retryable":false,"description":"Group names and externalIds are unique per workspace."},{"code":"default_group","status":409,"source":"user","retryable":false,"description":"Every workspace keeps one default group, where a keyword lands when no group is named."},{"code":"default_group_context","status":400,"source":"user","retryable":false,"description":"The default group is the workspace itself: its company is the profile (PATCH /v1/company). A company description goes on any other group."},{"code":"group_changed","status":409,"source":"user","retryable":false,"description":"A keyword was created in or moved into the group while its keywords were being deleted. Its other keywords are gone; retry the delete."},{"code":"invalid_signature","status":401,"source":"user","retryable":false,"description":"An inbound webhook did not carry a valid signature."},{"code":"webhook_not_configured","status":503,"source":"system","retryable":false,"description":"The inbound webhook has no secret on this deployment."},{"code":"invalid_token","status":400,"source":"user","retryable":false,"description":"A signed link (unsubscribe, confirmation) was tampered with or is malformed."},{"code":"protected_user","status":409,"source":"user","retryable":false,"description":"Staff accounts cannot be deleted from the admin page."},{"code":"upstream_unavailable","status":502,"source":"platform","retryable":true,"description":"A provider (Slack, Telegram, Polar, …) failed while serving your request. Retry with backoff."},{"code":"internal_error","status":500,"source":"system","retryable":false,"description":"Something failed on our side. The response carries a requestId; quote it to support."}],"servers":[{"url":"https://api.rumoro.dev"}]}