{"openapi":"3.0.0","info":{"title":"Rumoro API","version":"0.0.1","description":"Social listening for developers and AI agents."},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key from POST /v1/api-keys. Keys start with ref_."}},"schemas":{"GroupRef":{"type":"object","properties":{"id":{"type":"string","description":"The group's id (grp_...)."},"name":{"type":"string","description":"Name of the group."},"externalId":{"type":"string","nullable":true,"description":"An id from your own system, or null."},"isDefault":{"type":"boolean","description":"True for the workspace's default group. New keywords go there when you don't name a group."}},"required":["id","name","externalId","isDefault"],"description":"The keyword's group."},"ReviewSource":{"type":"object","properties":{"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"Where the reviews come from. appstore is the Apple App Store, googleplay is Google Play, trustpilot is a company's Trustpilot page and googlemaps is the Google reviews of a place."},"id":{"type":"string","description":"The platform's own id. An App Store app id, a Google Play package name, a Trustpilot domain, or a Google Place ID or cid."},"url":{"type":"string","description":"URL of the review page, such as an app's store listing, a company's Trustpilot page or a place on Google Maps."},"countries":{"type":"array","items":{"type":"string"},"description":"Two-letter storefront codes, lowercase. Empty for Trustpilot and Google Maps."},"language":{"type":"string","nullable":true,"description":"The review language on Google Play. Null on other platforms."},"connectedAt":{"type":"string","description":"When the keyword began collecting reviews from this page."}},"required":["platform","id","url","countries","language","connectedAt"]},"Keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string"},"kind":{"type":"string","enum":["brand","competitor","topic"]},"muted":{"type":"boolean","description":"True when the keyword is neither polled nor matched. You, the wallet (pausedForBalance) or the noise brake (pausedForNoise) can mute it. Reaching the mention cap does not mute it (pausedForCap)."},"pausedForBalance":{"type":"boolean","description":"Muted because the balance ran out. A top-up resumes it. Unmuting it yourself also needs balance."},"pausedForNoise":{"type":"boolean","description":"Set when the noise brake muted the keyword. That happens on welcome credit once 20 or more matches are scored and under 30% are relevant. Unmuting it, or changing its required or excluded terms, platforms or context, resumes it when the balance covers another day. A top-up alone does not."},"pausedForCap":{"type":"boolean","description":"Hit its monthly mention cap. Matching resumes on the 1st (UTC) or when you raise the cap. The keyword isn't muted and is still charged daily."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"How many matched mentions the keyword may collect per calendar month (UTC). Every match counts, relevant or not, including a new keyword's look-back, since every match is billed."},"welcome":{"type":"boolean","description":"Rumoro sets this while the workspace uses its welcome credit. It limits each keyword to 200 mentions a month until the first top-up."},"own":{"type":"integer","nullable":true,"description":"The cap you chose. While welcome is true it is the cap restored at the first top-up (null for none), and sending `mentions: 200` changes nothing. Otherwise it equals mentions."}},"required":["mentions","welcome","own"],"description":"Monthly limit on matched mentions. Null means 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":"The platforms searched for the term. Null means all of them. An empty list means none, and the keyword only collects reviews."},"reviewSources":{"type":"array","items":{"$ref":"#/components/schemas/ReviewSource"},"description":"The review pages the keyword reads, such as App Store and Google Play apps, Trustpilot pages and Google Maps places. Empty when there are none."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"Up to 300 characters the classifier reads for this keyword only, in addition to the company profile or the group's description. Say what the term means for you and what to ignore, for example \"Basil is our deploy tool, not the herb.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Terms the post must contain as well. requiredMode says whether one or all of them must appear. An empty list sets no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any needs one of the required terms in the post. all needs every one."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Posts that contain one of these terms are dropped. Put `*` at the start or end of a term as a wildcard, so deploy* matches deployment and *bot matches nightlybot."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Authors whose posts this keyword ignores. Each entry is a profile or post link, @handle, u/name, Bluesky DID or display name. Entries are normalized the same way as an alert's muted authors."},"caseSensitive":{"type":"boolean","description":"When true, the term only matches in the exact case you typed, so RAG never matches rag. Defaults to false."}},"required":["requiredTerms","requiredMode","excludedTerms","excludedAuthors","caseSensitive"],"description":"Rules a post must pass before it is stored as a mention. A post they reject is never billed."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"All matches so far, relevant or not. Billing counts this number."},"relevant":{"type":"integer","minimum":0,"description":"Matches whose relevance score reached the threshold."},"last7d":{"type":"integer","minimum":0,"description":"Matches with a post date in the past 7 days."},"thisMonth":{"type":"integer","minimum":0,"description":"Matches recorded in the current calendar month (UTC). The cap is checked against this count."},"lastMentionAt":{"type":"string","nullable":true,"description":"Time of the latest matched post. Null before the first match."},"feedback":{"type":"object","properties":{"relevant":{"type":"integer","minimum":0,"description":"Marked relevant by your team."},"notRelevant":{"type":"integer","minimum":0,"description":"Mentions someone on your team marked not relevant. This is noise the classifier missed."}},"required":["relevant","notRelevant"],"description":"Your team's relevance marks, set with PATCH /v1/mentions/{id}."},"noise":{"type":"object","properties":{"scored":{"type":"integer","minimum":0,"description":"How many of the last 14 days' matches are scored."},"relevant":{"type":"integer","minimum":0,"description":"How many of them were scored relevant."},"noisy":{"type":"boolean","description":"True when the past 14 days have 20 or more scored matches and fewer than 30% are relevant. Narrow the keyword with required terms, excluded terms or context, because every match is billed, relevant or not."}},"required":["scored","relevant","noisy"],"description":"Relevance of the scored matches from the past 14 days. A keyword you narrow today drops the flag within two weeks."},"health":{"type":"string","enum":["healthy","noisy","quiet","capped","paused","new"],"description":"Health over the 14 days `noise` covers, by the same rule as GET /v1/keywords/{id}/health. The first that applies wins. paused (muted), capped (at its cap), noisy (20+ scored matches, under 30% relevant), new (under 7 days old, or changed in the last 7 days with under 20 scored since), quiet (7+ days, nothing relevant), otherwise healthy. After a change to matching rules, platforms or context, or an unmute, within the 14 days, only later matches count, while `noise` keeps all 14 days. The endpoint defaults to 30 days, so the two can differ, and it explains why and what to change."},"cost":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Charged days this month. A day is charged when the keyword is unmuted at the daily run, so a new keyword shows 0 until tomorrow."},"keywordCents":{"type":"integer","description":"keywordDays at 500/30 cents each, which is $5 a month. Only the total is rounded."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed this month. A match counts when it is scored, which is the time the ledger settles by. So this can lag behind thisMonth while matches are still being scored, and a match that failed to score never counts."},"mentionCents":{"type":"integer","description":"Those matches priced at $0.008 each, with the total rounded once."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents. The keyword's cost this month in US cents."}},"required":["keywordDays","keywordCents","billableMentions","mentionCents","totalCents"],"description":"List-price cost this calendar month (UTC), equal to this keyword's row in GET /v1/usage/breakdown?month=<this month>. The ledger settles daily and can differ only by cumulative rounding."}},"required":["mentions","relevant","last7d","thisMonth","lastMentionAt","feedback","noise","health","cost"],"description":"Counted from this workspace's matches only."},"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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"lastPolledAt":{"type":"string","nullable":true,"description":"When the term was last polled on this platform. Null before the first poll."},"emptyPolls":{"type":"integer","description":"How many polls in a row found nothing new. The higher it gets, the less often the term is polled."}},"required":["platform","lastPolledAt","emptyPolls"]},"description":"Polling status for each platform that is polled on a schedule. Live feeds such as Bluesky are not listed."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."}},"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","unknown_channel","not_a_digest","hourly_email_unsupported","slack_not_connected","slack_not_configured","telegram_not_configured","email_not_configured","invalid_assignee","classification_pending","already_member","last_owner","duplicate_segment","duplicate_view","duplicate_group","default_group","default_group_context","invalid_signature","invalid_token","upstream_unavailable","internal_error","unsupported_media_type","request_timeout","key_limit","conflict","no_billing_owner","rule_disabled","no_channels","channel_disabled","no_recipients","recipient_suppressed","confirmation_rate_limited","confirmation_requires_resend","email_test_rate_limited","email_hourly_limit","email_idempotency_expired","email_transport_unavailable","delivery_not_configured","delivery_key_unavailable","not_retryable","not_replayable","digest_has_replay","digest_retry_expired","delivery_request_incomplete","request_conflict","stale_version","version_conflict","already_classified","keyword_inactive","source_unavailable","source_timeout","invalid_host","invalid_origin","database_unavailable","database_not_ready","not_configured"],"description":"A stable code for programs. Branch on it, not on the message. New codes may be added, so treat an unknown one as a general failure with the same status."},"message":{"type":"string","description":"A description for people. Its wording can change."},"requestId":{"type":"string","description":"This request's id, also sent in the X-Request-Id header. Include it when you contact support."},"retryAfterSeconds":{"type":"integer","description":"Seconds to wait before retrying, on rate_limited and other errors you can retry. Same value as the Retry-After header."}},"required":["code","message"],"description":"Details of the error."}},"required":["error"]},"KeywordSuggestion":{"type":"object","properties":{"type":{"type":"string","enum":["excluded_terms","excluded_authors","required_terms","platforms","context"],"description":"What the suggestion changes. The excluded_* types add to the matching rules, required_terms swaps the required list, platforms drops the platforms that bring nearly only noise, and context rewrites the classifier's sentence."},"values":{"type":"array","items":{"type":"string"},"description":"The terms or authors to add, the platforms to remove, or the new context."},"why":{"type":"string","description":"Why, and what the change would have done, in plain words."},"patch":{"type":"object","properties":{"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"New kind (brand, competitor or topic)."},"muted":{"type":"boolean","description":"Muting stops polling and matching. Existing mentions are kept."},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Sets a new platform list. Null means all platforms. An empty list means none, which works when the keyword has reviewSources and only collects reviews."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"Up to 300 characters the classifier reads for this keyword only, in addition to the company profile or the group's description. Say what the term means for you and what to ignore, for example \"Basil is our deploy tool, not the herb.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Terms the post must contain as well. requiredMode says whether one or all of them must appear. An empty list sets no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any needs one of the required terms in the post. all needs every one."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Posts that contain one of these terms are dropped. Put `*` at the start or end of a term as a wildcard, so deploy* matches deployment and *bot matches nightlybot."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Authors whose posts this keyword ignores. Each entry is a profile or post link, @handle, u/name, Bluesky DID or display name. Entries are normalized the same way as an alert's muted authors."},"caseSensitive":{"type":"boolean","description":"When true, the term only matches in the exact case you typed, so RAG never matches rag. Defaults to false."}},"description":"Fields you leave out stay as they are. An empty list clears a field."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"How many matched mentions the keyword may collect per calendar month (UTC). Every match counts, relevant or not, including a new keyword's look-back, since every match is billed."}},"required":["mentions"],"description":"Sets a new monthly mention cap, or null for no cap. A cap above this month's count resumes a capped keyword right away. A cap at or below the count pauses it."},"groupId":{"type":"string","minLength":1,"description":"Target group (grp_...). 409 if it already has this term."},"reviewSources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"Review page link, or send platform and id instead. Accepts App Store and Google Play app links (https://apps.apple.com/us/app/slack/id618783545, https://play.google.com/store/apps/details?id=com.Slack), Trustpilot pages (https://www.trustpilot.com/review/slack.com) and Google Maps places (full or maps.app.goo.gl link)."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"Where the reviews come from. appstore is the Apple App Store, googleplay is Google Play, trustpilot is a company's Trustpilot page and googlemaps is the Google reviews of a place."},"id":{"type":"string","minLength":1,"maxLength":200,"description":"The platform's own id. On the App Store it is the number after \"id\" in the link, on Google Play the package name, on Trustpilot the company's domain (slack.com) and on Google Maps a Place ID (ChIJ...)."},"countries":{"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"},"minItems":1,"maxItems":20,"description":"For App Store and Google Play. Up to 20 storefronts to read, as two-letter codes. Without it, the storefront in the link is used, or us. Each storefront adds one poll a day, and a review found in two storefronts is still one mention. Trustpilot and Google Maps have a single page and take no countries."},"language":{"type":"string","minLength":2,"maxLength":10,"description":"For Google Play. The review language to read, such as en, es, de or pt-BR, since Google Play returns one language at a time. Without it, the link's hl is used, or en."}},"description":"A review page, by link or by platform and id. Its reviews become this keyword's mentions."},"maxItems":10,"description":"Sets a new list of review pages for this keyword. An empty list disconnects them all, and their reviews are kept. A page or country you add gets the free 30-day look-back. Pages already listed are unchanged."}},"description":"Send this body unchanged to PATCH /v1/keywords/{id} to apply the suggestion. Lists hold the full new list, with the current entries included."},"effect":{"type":"object","nullable":true,"properties":{"noiseRemoved":{"type":"integer","minimum":0,"description":"How many noise matches the change would have removed in the window (since stats.judgedSince if set). Sampled unless exact is true."},"relevantRemoved":{"type":"integer","minimum":0,"description":"How many relevant matches the change would have cut from the window."},"centsSaved":{"type":"integer","description":"Money the change would have saved in the window, at the mention rate for each removed match."},"sample":{"type":"object","properties":{"noiseRemoved":{"type":"integer","minimum":0,"description":"Noise posts in the sample that the change would reject."},"noise":{"type":"integer","minimum":0,"description":"Noise posts in the sample."},"relevantRemoved":{"type":"integer","minimum":0,"description":"Relevant posts in the sample that the change would reject."},"relevant":{"type":"integer","minimum":0,"description":"Relevant posts in the sample."}},"required":["noiseRemoved","noise","relevantRemoved","relevant"],"description":"Counts behind the estimate. The matcher's rules were run on each sampled post."},"exact":{"type":"boolean","description":"True when the sample covered the whole window, so the counts are exact."}},"required":["noiseRemoved","relevantRemoved","centsSaved","sample","exact"],"description":"The result of replaying the change on the window's matches with the matcher's rules. Null for context suggestions, which alter scores rather than matches."},"source":{"type":"string","enum":["rules","ai"],"description":"rules means it was computed from the posts in the window. ai means a language model wrote it (with ai=true)."}},"required":["type","values","why","patch","effect","source"]},"KeywordHealth":{"type":"object","properties":{"keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term exactly as entered."},"group":{"$ref":"#/components/schemas/GroupRef"}},"required":["id","term","group"],"description":"The keyword this report covers."},"window":{"type":"object","properties":{"from":{"type":"string","description":"Start date (UTC, YYYY-MM-DD), included."},"to":{"type":"string","description":"The last day included, which is today."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."}},"required":["from","to","days"],"description":"The days the report covers, in UTC and by match time."},"status":{"type":"string","enum":["healthy","noisy","quiet","capped","paused","new"],"description":"The first that applies wins. paused when you, the wallet or the noise brake muted it. capped at the monthly mention cap. noisy with 20+ scored matches in the window and under 30% relevant. new when under 7 days old, or changed in the last 7 days with under 20 scored matches since. quiet when 7+ days old with nothing relevant in the window. Otherwise healthy. After a rules, platforms or context change, or an unmute, inside the window, only later matches count (stats.judgedSince)."},"reasons":{"type":"array","items":{"type":"string"},"description":"Plain-word explanation, status first."},"stats":{"type":"object","properties":{"matches":{"type":"integer","minimum":0,"description":"Match count for the window, relevant or not."},"relevant":{"type":"integer","minimum":0,"description":"Matches with a relevance score of 40 or more."},"filtered":{"type":"integer","minimum":0,"description":"Matches scored below 40, the noise. They are billed like any other match."},"unscored":{"type":"integer","minimum":0,"description":"Matches not scored yet, or whose scoring failed. A failed one is never billed."},"noiseShare":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Share of scored matches that were filtered. Null if none were scored."},"workspaceShare":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"The part of the workspace's matches in the window that came from this keyword. Null when the workspace had no matches."},"judgedSince":{"type":"string","nullable":true,"description":"The last change to the keyword's matching rules, platforms or context, or its last unmute, if that falls inside the window. The status, reasons, noiseTerms, noiseAuthors and suggestions then only look at matches since this time. These numbers still cover the whole window. Null means everything covers 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"matches":{"type":"integer","minimum":0,"description":"This platform's match count for the window."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored 40 or more."},"filtered":{"type":"integer","minimum":0,"description":"How many of them scored below 40, the noise."},"noiseShare":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Share of scored matches that were filtered. Null if none were scored."}},"required":["platform","matches","relevant","filtered","noiseShare"]},"description":"A row for each platform with matches, the busiest first."},"weekly":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","description":"Week start as YYYY-MM-DD. Weeks run in 7-day steps from the start of the window."},"matches":{"type":"integer","minimum":0,"description":"Matches during these 7 days."},"relevant":{"type":"integer","minimum":0,"description":"How many of them were relevant."}},"required":["from","matches","relevant"]},"description":"The trend in rows of 7 days, oldest first. The last row can be shorter."},"cost":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Charged days in the window."},"keywordCents":{"type":"integer","description":"What keywordDays cost at the keyword rate."},"billableMentions":{"type":"integer","minimum":0,"description":"Billed matches in the window, dated by scoring time."},"mentionCents":{"type":"integer","description":"What billableMentions cost at the mention rate."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents, equal to this keyword's GET /v1/usage/breakdown row for that range."}},"required":["keywordDays","keywordCents","billableMentions","mentionCents","totalCents"],"description":"List-price cost of this keyword in the window."}},"required":["matches","relevant","filtered","unscored","noiseShare","workspaceShare","judgedSince","byPlatform","weekly","cost"],"description":"Based on this keyword's matches in the window."},"sample":{"type":"object","properties":{"noise":{"type":"integer","minimum":0,"description":"Noise posts that were read, up to 200 of the newest in the window or since stats.judgedSince, from platforms matched by text. Zero when fewer than 20 matches were scored since a change."},"relevant":{"type":"integer","minimum":0,"description":"Relevant posts that were read, chosen the same way."}},"required":["noise","relevant"],"description":"The posts used for noiseTerms, noiseAuthors and the effects. Only posts the keyword's current rules accept count, not ones an older rule let in. Review platforms match by app rather than text and are left out."},"noiseTerms":{"type":"array","items":{"type":"object","properties":{"term":{"type":"string","description":"One word or a phrase of two words."},"noisePosts":{"type":"integer","minimum":0,"description":"Noise posts in the sample that contain it."},"relevantPosts":{"type":"integer","minimum":0,"description":"Relevant posts in the sample that contain it."},"lift":{"type":"number","nullable":true,"description":"Ratio of the term's rate in noise to its rate in relevant posts, smoothed. Null without a relevant post."}},"required":["term","noisePosts","relevantPosts","lift"]},"description":"Up to 10 words or phrases that show up far more in noise than in relevant posts, strongest first. Words of the keyword itself are skipped."},"noiseAuthors":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The author's name as shown on the platform."},"entry":{"type":"string","description":"The entry matching.excludedAuthors would store for this author."},"noisePosts":{"type":"integer","minimum":0,"description":"Noise posts in the sample written by this author."}},"required":["name","entry","noisePosts"]},"description":"Authors in the sample with no relevant post and 3 or more noise posts."},"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/KeywordSuggestion"},"description":"Suggested noise fixes, each a body for PATCH /v1/keywords/{id}. The list is empty if no fix helps, or if fewer than 20 matches were scored after the last change. A reason explains which."},"ai":{"type":"object","properties":{"requested":{"type":"boolean","description":"True when the request had ai=true."},"status":{"type":"string","enum":["off","generated","cached","unavailable","rate_limited"],"description":"off means it was not requested. generated means it was written for this request. cached means it was written earlier today for the same keyword, window and settings. unavailable means the model failed, gave nothing usable or is not set up. rate_limited means the workspace used its 20 model calls for this hour."}},"required":["requested","status"],"description":"The optional part of the report written by a language model."},"generatedAt":{"type":"string","description":"When the report was built. Reports are cached for 5 minutes, and changing the keyword builds a new 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":"Posts that contain one of these terms are dropped, whichever keyword matched them. Terms follow the same phrase rule as a keyword, and `*` at either end is a wildcard. A common list is \"hiring, job, careers\"."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":200,"description":"Authors ignored across all keywords, such as your own accounts, teammates or known spammers. Entries may be profile or post links, @handles, u/names, Bluesky DIDs or display names, and are saved in canonical form."},"excludedRepos":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Repositories to ignore, as owner/name or a github.com link (vercel/next.js, https://github.com/vercel/next.js). Their issues, pull requests and comments are dropped."},"subreddits":{"type":"object","properties":{"only":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Allowlist of subreddits (r/name or name). When set, other subreddits are dropped and `excluded` is ignored."},"excluded":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Subreddits to ignore, written as r/name or name."}},"required":["only","excluded"],"description":"Applies to Reddit only."},"updatedAt":{"type":"string","nullable":true,"description":"When the filters were last changed. Null if never."}},"required":["excludedTerms","excludedAuthors","excludedRepos","subreddits","updatedAt"],"description":"Matching rules for the whole workspace. A post they reject is never billed."},"Mention":{"type":"object","properties":{"id":{"type":"string","description":"The mention's id (mm_...). A mention is one post matched to one keyword, so a post that matches two keywords has two ids."},"status":{"type":"string","enum":["open","ignored","done"],"description":"open means no one has handled it. ignored means you hid it from the feed and channels. done means it was handled."},"relevant":{"type":"boolean","description":"True when the classifier's relevance score is 40 or more, the delivery threshold."},"delivered":{"type":"boolean","description":"true once any channel of yours received it."},"priority":{"type":"number","description":"How much the mention deserves attention, with one decimal, worked out when you read it. It adds half the relevance, points for the author's followers (8 when unknown) and points for the strongest intent (from 20 for buy intent down to 5 for praise). It then takes off 2 points per day of age, at most 20."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"group":{"$ref":"#/components/schemas/GroupRef"}},"required":["id","term","group"],"description":"The keyword the post matched, with its group."},"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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"url":{"type":"string","description":"A stable link to the post."},"text":{"type":"string","description":"The title and body, cut to 8 KB when the post is collected."},"title":{"type":"string","nullable":true,"description":"The post's title on platforms that have titles, such as Hacker News stories, Reddit threads, GitHub issues and pull requests, Stack Overflow questions, DEV articles, YouTube videos, news articles and reviews with a title. Null on platforms without titles (X, Bluesky, LinkedIn) and for posts collected before October 2026."},"imageUrl":{"type":"string","nullable":true,"description":"Preview image sent by the platform, or null. Examples are YouTube thumbnails, DEV covers, news sharing images and Bluesky images or link cards."},"links":{"type":"array","items":{"type":"string"},"description":"Up to 20 links found in the post, in the order they appear. Empty when there are none and for posts collected before September 2026."},"publishedAt":{"type":"string","description":"When the post went live on the platform."},"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 numbers as the platform gave them when the post was collected, often a few minutes after it was written. A number the platform lacks is null. The whole object is null on platforms that report none and for posts collected before September 2026. X reports all six."},"replyTo":{"type":"object","nullable":true,"properties":{"author":{"type":"string","nullable":true,"description":"Who wrote the parent post, as named on the platform."},"url":{"type":"string","nullable":true,"description":"Link to the parent post."},"text":{"type":"string","nullable":true,"description":"Text of the parent post, if the platform provided it."}},"required":["author","url","text"],"description":"The post being replied to, on X and Bluesky. Null when the post is not a reply."}},"required":["platform","url","text","title","imageUrl","links","publishedAt","engagement","replyTo"]},"author":{"type":"object","nullable":true,"properties":{"id":{"type":"string","nullable":true,"description":"aut_... id for GET /v1/people/{id}, or null while the account isn't in your audience yet."},"name":{"type":"string","nullable":true,"description":"The name shown on the platform."},"handle":{"type":"string","nullable":true,"description":"The handle taken from the profile link, written the platform's way (@name, u/name). Null on platforms without handles."},"url":{"type":"string","nullable":true,"description":"Link to the profile."},"avatarUrl":{"type":"string","nullable":true,"description":"Avatar URL, or null if the platform has none."},"followers":{"type":"integer","nullable":true,"description":"Followers at the time of their latest post. Null if the platform has no follower count."},"tags":{"type":"array","items":{"type":"string"},"description":"Tags your workspace gave this person."}},"required":["id","name","handle","url","avatarUrl","followers","tags"],"description":"The author of the post. Null when the platform gave no author."},"review":{"type":"object","nullable":true,"properties":{"rating":{"type":"integer","minimum":1,"maximum":5,"description":"The reviewer's star rating."},"ratingMax":{"type":"integer","description":"The highest possible rating, which is 5 on both stores."},"title":{"type":"string","nullable":true,"description":"The review's title. Null where reviews have none, as on Google Play."},"version":{"type":"string","nullable":true,"description":"The app version the reviewer used, if the store reports it."},"country":{"type":"string","nullable":true,"description":"A lowercase two-letter code. On the App Store and Google Play it is the storefront the review was read in. On Trustpilot it is the reviewer's country. Null when the platform gives none."},"verified":{"type":"boolean","nullable":true,"description":"True when Trustpilot marks the review as verified. Null on platforms without that mark."},"response":{"type":"string","nullable":true,"description":"The developer's reply at the time the review was collected. Null when there was none."},"responseAt":{"type":"string","nullable":true,"description":"Time of the developer's reply."},"app":{"type":"object","properties":{"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"Where the reviews come from. appstore is the Apple App Store, googleplay is Google Play, trustpilot is a company's Trustpilot page and googlemaps is the Google reviews of a place."},"id":{"type":"string","description":"The app's id in the store."},"url":{"type":"string","description":"Link to the app in the store."}},"required":["platform","id","url"],"description":"The app the review is about."}},"required":["rating","ratingMax","title","version","country","verified","response","responseAt","app"],"description":"Details of an app store review. Null for any other post. The stars set the sentiment, with 4 and 5 positive, 3 neutral, and 1 and 2 negative. A review always counts as relevant, because you picked the app."},"classification":{"type":"object","nullable":true,"properties":{"relevance":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Score out of 100, or null if classification failed."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"intents":{"type":"array","items":{"type":"string"},"description":"Tags for intent and topic. The values are buy_intent, question, complaint, praise, comparison, churn_intent (moving away from the keyword), bug_report, pricing, hiring, event, promotional, testimonial (a user recommending it from experience), industry_insight (analysis or numbers about the market), launch (a new product or feature announced) and feedback (an idea or request for it)."},"automated":{"type":"boolean","description":"A label for posts that look machine-made. Examples are bot or app accounts, scheduled or template posts and obvious AI summaries. Such mentions are kept, delivered and billed as usual. false until judged."},"language":{"type":"string","nullable":true,"description":"ISO 639-1 code (en, es, de) of the post's language. Null if unknown or scored before languages were stored."},"confidence":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"The classifier's confidence in its relevance score, from 0 to 1. Null when the fallback model scored the post, or when it was scored before confidence was stored."},"uncertain":{"type":"boolean","description":"True when a person should check the score, because confidence is below 0.4 or the model that wrote the note disagreed with it. It is a hint for reviewers and never hides a mention."},"note":{"type":"string","nullable":true,"description":"A sentence from the classifier on why it gave this score."},"failed":{"type":"boolean","description":"Set when the model failed to score the post. Such posts remain in the feed and cost nothing."},"feedback":{"type":"object","nullable":true,"properties":{"relevant":{"type":"boolean","nullable":true,"description":"Whether you judged it relevant. Null if you only changed the sentiment."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"The sentiment you set. Null if you only judged relevance."},"at":{"type":"string","description":"When the latest feedback was given."},"original":{"type":"object","properties":{"relevance":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"The classifier's score before your feedback. Null if it had not scored the post."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"The classifier's sentiment before you changed it."}},"required":["relevance","sentiment"],"description":"The classifier's values that your feedback overrode."}},"required":["relevant","sentiment","at","original"],"description":"Feedback from your team, or null. Judging relevance sets `relevance` to 100 or 0 and updates `relevant` to match. A new sentiment replaces `sentiment`. Lists, filters, digests and reports all use the corrected values."}},"required":["relevance","sentiment","intents","automated","language","confidence","uncertain","note","failed","feedback"],"description":"The classifier's result with your feedback applied. Null while the post waits to be classified."},"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":"The member handling this mention. Null if nobody is assigned."},"snoozedUntil":{"type":"string","nullable":true,"description":"The mention is hidden from the feed until this time. Null when it is not snoozed."},"note":{"type":"string","nullable":true,"description":"A note for your team, or null."}},"required":["assignee","snoozedUntil","note"]},"createdAt":{"type":"string","description":"When the match was stored. The feed is sorted by this by default."}},"required":["id","status","relevant","delivered","priority","keyword","post","author","review","classification","triage","createdAt"]},"Person":{"type":"object","properties":{"id":{"type":"string","description":"The person's id (aut_...), which is the id of their main account. An account merged into a person leads to that person."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The main account's platform. See `accounts` for all of them."},"name":{"type":"string","nullable":true,"description":"The name shown on their latest post. Null if the platform has none."},"handle":{"type":"string","nullable":true,"description":"The main account's handle, written the platform's way."},"url":{"type":"string","nullable":true,"description":"Link to the main account's profile."},"avatarUrl":{"type":"string","nullable":true},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The account's id (aut_...). The main account's id is the person's id."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"name":{"type":"string","nullable":true,"description":"The name shown on the platform."},"handle":{"type":"string","nullable":true,"description":"The handle taken from the profile link, written the platform's way."},"url":{"type":"string","nullable":true,"description":"Link to the profile."}},"required":["id","platform","name","handle","url"]},"description":"All accounts this workspace counts as this person, starting with the main one."},"reach":{"type":"object","properties":{"followers":{"type":"integer","nullable":true},"following":{"type":"integer","nullable":true},"posts":{"type":"integer","nullable":true}},"required":["followers","following","posts"],"description":"Counts from the platform, taken from their latest post. Null where a platform lacks the 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":"Filled in only for a public address 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 linked from the person's profile."},"fetchedAt":{"type":"string","description":"Last profile fetch time."}},"required":["bio","company","location","website","email","links","fetchedAt"],"description":"Details from the public profile. Null until the profile is fetched."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"All their matches in this workspace, relevant or not."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored as 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":"Time of their first matched post."},"lastSeenAt":{"type":"string","description":"Time of their latest matched post."}},"required":["mentions","relevant","sentiment","firstSeenAt","lastSeenAt"],"description":"Counted from this workspace's matches only."},"annotations":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"notes":{"type":"string"},"muted":{"type":"boolean","description":"Their posts are kept out of the feed and all channels. Collection and billing still happen."}},"required":["tags","notes","muted"],"description":"Notes and tags your workspace added to the person."},"outreach":{"type":"object","properties":{"owner":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The member's user id."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"The teammate responsible for this contact. Null when no one is, or when that member has left the workspace."},"stage":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"lastContactedAt":{"type":"string","nullable":true,"description":"Time of the latest logged activity. Null when no contact was logged."}},"required":["owner","stage","lastContactedAt"],"description":"Your outreach to this person. Logging the first activity makes the member who reached out the owner, if there was none, 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":"The activity's id (act_...)."},"personId":{"type":"string","description":"The person's id (aut_...)."},"channel":{"type":"string","enum":["email","x","linkedin","bluesky","reddit","github","call","meeting","other"],"description":"How the person was contacted."},"note":{"type":"string","description":"A short summary of what was sent or said. Empty if none was written."},"member":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The member's user id."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"Who made contact. Null for an API-key entry without memberId, or after that member leaves."},"occurredAt":{"type":"string","description":"When the contact took place."},"createdAt":{"type":"string","description":"When the activity was logged."}},"required":["id","personId","channel","note","member","occurredAt","createdAt"]},"Segment":{"type":"object","properties":{"id":{"type":"string","description":"The segment's 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Only people with a profile on one of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People with one of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"This many followers or fewer. People with an unknown count are left out."},"minMentions":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people who have an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out people with one of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Excludes people with a mention of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with a mention that links to one of these hosts or its subdomains."},"muted":{"type":"boolean","description":"true keeps only muted people and false only people who are not muted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Only people in one of these outreach stages."},"automated":{"type":"boolean","description":"true keeps people whose matched posts are mostly automated, like bots. false keeps the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by one of these members, by user id. Use \"none\" for people without an owner."}}},"count":{"type":"integer","minimum":0,"description":"How many people are in the segment now. It is counted again on each read."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"updatedAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["id","name","description","filter","count","createdAt","updatedAt"]},"FilterGroup":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Searches post text and author names."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keeps matches of these keywords only."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keyword ids to exclude."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keyword kinds to keep, out of brand, competitor and topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Limits to keywords from these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Hides matches from keywords that belong to 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only (open, ignored or done)."},"relevant":{"type":"boolean","description":"Filter on the classifier's verdict. true keeps relevant mentions, false the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Minimum relevance score a mention needs."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Keeps mentions whose classifier confidence is this value or higher."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Hides these sentiments. Unscored mentions stay."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Hides mentions with these tags."},"automated":{"type":"boolean","description":"true keeps posts that look machine-made. false keeps the others."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Keeps posts in these languages only, as ISO 639-1 codes."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out authors with one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or more. Unknown counts are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or fewer. Unknown counts are left out."},"isReply":{"type":"boolean","description":"true keeps replies and comments. false keeps posts that are not replies."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Hides reviews with these star ratings. Other posts are not affected."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."}},"additionalProperties":false,"description":"A set of conditions that must all be true. It uses the same fields as a view filter, except anyOf."},"View":{"type":"object","properties":{"id":{"type":"string","description":"The view's id (vw_...)."},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Searches post text and author names."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keeps matches of these keywords only."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keyword ids to exclude."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keyword kinds to keep, out of brand, competitor and topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Limits to keywords from these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Hides matches from keywords that belong to 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only (open, ignored or done)."},"relevant":{"type":"boolean","description":"Filter on the classifier's verdict. true keeps relevant mentions, false the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Minimum relevance score a mention needs."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Keeps mentions whose classifier confidence is this value or higher."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Hides these sentiments. Unscored mentions stay."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Hides mentions with these tags."},"automated":{"type":"boolean","description":"true keeps posts that look machine-made. false keeps the others."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Keeps posts in these languages only, as ISO 639-1 codes."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out authors with one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or more. Unknown counts are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or fewer. Unknown counts are left out."},"isReply":{"type":"boolean","description":"true keeps replies and comments. false keeps posts that are not replies."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Hides reviews with these star ratings. Other posts are not affected."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}}},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"updatedAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["id","name","description","filter","createdAt","updatedAt"]},"MentionSpikeEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"Related attention item (att_...). See GET /v1/attention, dismiss with POST /v1/attention/{id}/dismiss."},"url":{"type":"string","description":"The dashboard page to open."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"name":{"type":"string","description":"The keyword's display name. It is the term, or \"term (Group)\" when the keyword is not in the default group."},"groupId":{"type":"string","description":"The keyword's group id (grp_...)."}},"required":["id","term","kind","name","groupId"],"description":"The keyword this item concerns."},"window":{"type":"object","properties":{"from":{"type":"string","description":"Start time, included."},"to":{"type":"string","description":"End time, not included."}},"required":["from","to"],"description":"Match-time range of the counts."},"matches":{"type":"integer","minimum":0,"description":"New matches during the hour, meaning posts that matched within 6 hours of being published. Look-backs and free reviews are not counted."},"relevant":{"type":"integer","minimum":0,"description":"How many of them have been scored relevant so far."},"baseline":{"type":"object","properties":{"meanPerHour":{"type":"number","minimum":0,"description":"Average new matches per hour during the baseline."},"stddevPerHour":{"type":"number","minimum":0,"description":"The standard deviation of that average."},"hours":{"type":"integer","minimum":0,"description":"How many hours the baseline covers. It is the week before the window, or the time since the keyword was created if that is shorter."}},"required":["meanPerHour","stddevPerHour","hours"],"description":"The keyword's normal volume."}},"required":["attentionId","url","keyword","window","matches","relevant","baseline"]},"NegativeSpikeEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"Related attention item (att_...). See GET /v1/attention, dismiss with POST /v1/attention/{id}/dismiss."},"url":{"type":"string","description":"The dashboard page to open."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"name":{"type":"string","description":"The keyword's display name. It is the term, or \"term (Group)\" when the keyword is not in the default group."},"groupId":{"type":"string","description":"The keyword's group id (grp_...)."}},"required":["id","term","kind","name","groupId"],"description":"The keyword this item concerns."},"window":{"type":"object","properties":{"from":{"type":"string","description":"Start time, included."},"to":{"type":"string","description":"End time, not included."}},"required":["from","to"],"description":"Match-time range of the counts."},"negative":{"type":"integer","minimum":0,"description":"Relevant matches in the window with negative sentiment."},"relevant":{"type":"integer","minimum":0,"description":"Relevant match count for the window."},"share":{"type":"number","minimum":0,"maximum":1,"description":"negative divided by relevant."},"baseline":{"type":"object","properties":{"negative":{"type":"integer","minimum":0,"description":"How many relevant matches were negative in the prior week."},"relevant":{"type":"integer","minimum":0,"description":"Relevant match count for those 7 days."},"share":{"type":"number","minimum":0,"maximum":1,"description":"The normal share of negative matches, smoothed so that a quiet week still gives a value."}},"required":["negative","relevant","share"],"description":"The keyword's normal sentiment."}},"required":["attentionId","url","keyword","window","negative","relevant","share","baseline"]},"KeywordNoisyEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"Related attention item (att_...). See GET /v1/attention, dismiss with POST /v1/attention/{id}/dismiss."},"url":{"type":"string","description":"The dashboard page to open."},"keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"name":{"type":"string","description":"The keyword's display name. It is the term, or \"term (Group)\" when the keyword is not in the default group."},"groupId":{"type":"string","description":"The keyword's group id (grp_...)."}},"required":["id","term","kind","name","groupId"],"description":"The keyword this item concerns."},"windowDays":{"type":"integer","minimum":0,"description":"How many days the noise is measured over. If the keyword changed within that time, it starts at the change."},"scored":{"type":"integer","minimum":0,"description":"Matches scored by the classifier during that time."},"relevant":{"type":"integer","minimum":0,"description":"How many of them were relevant."},"noiseShare":{"type":"number","minimum":0,"maximum":1,"description":"The part that scored below 40. Every match is billed, relevant or not."}},"required":["attentionId","url","keyword","windowDays","scored","relevant","noiseShare"]},"ChannelFailingEventData":{"type":"object","properties":{"attentionId":{"type":"string","description":"Related attention item (att_...). See GET /v1/attention, dismiss with POST /v1/attention/{id}/dismiss."},"url":{"type":"string","description":"The dashboard page to open."},"channel":{"type":"object","properties":{"id":{"type":"string","description":"The channel's id (dest_...)."},"kind":{"type":"string","enum":["slack","email","webhook","telegram"],"description":"Type of channel."},"label":{"type":"string","description":"The name you gave the channel."}},"required":["id","kind","label"],"description":"The channel that keeps failing."},"failures":{"type":"integer","minimum":0,"description":"Consecutive failed sends in the past 24 hours."},"lastError":{"type":"string","nullable":true,"description":"The latest error, as Slack, email, the webhook or Telegram returned it."},"since":{"type":"string","description":"Time of the first of those failures."}},"required":["attentionId","url","channel","failures","lastError","since"]},"AttentionItem":{"type":"object","properties":{"id":{"type":"string","description":"The attention item's id (att_...)."},"kind":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike flags an hour with far more mentions than usual, and sentiment.negative_spike a jump in the negative share over 24 hours. keyword.noisy flags a keyword whose scored matches are mostly noise, and channel.failing a channel whose recent sends all failed."},"status":{"type":"string","enum":["open","resolved","dismissed"],"description":"open means the condition is still true. resolved means it is not anymore. dismissed means someone dismissed it, and it will not reopen for the same episode."},"subject":{"type":"object","properties":{"type":{"type":"string","enum":["keyword","channel"],"description":"Either keyword or channel."},"id":{"type":"string","description":"The keyword's id (kw_...) or the channel's id (dest_...)."}},"required":["type","id"],"description":"The keyword or channel the item concerns."},"title":{"type":"string","description":"A one-line summary of what happened."},"openedAt":{"type":"string","description":"First time the condition was seen."},"resolvedAt":{"type":"string","nullable":true,"description":"When the condition ended. Null while it lasts."},"dismissedAt":{"type":"string","nullable":true,"description":"When someone dismissed it. Null if no one did."},"data":{"anyOf":[{"$ref":"#/components/schemas/MentionSpikeEventData"},{"$ref":"#/components/schemas/NegativeSpikeEventData"},{"$ref":"#/components/schemas/KeywordNoisyEventData"},{"$ref":"#/components/schemas/ChannelFailingEventData"}],"description":"The numbers at the time it opened. This is the same object the account event with the same name sends 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":"A company description just for this group, which the classifier reads. Null means the workspace profile is used."},"stats":{"type":"object","properties":{"keywords":{"type":"integer","minimum":0,"description":"Number of keywords in the group, muted or not."},"active":{"type":"integer","minimum":0,"description":"Number of unmuted keywords in the group."}},"required":["keywords","active"],"description":"Counted from the group's keywords."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"updatedAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["context","stats","createdAt","updatedAt"]}],"description":"The keyword's group."},"Company":{"type":"object","properties":{"name":{"type":"string","description":"The name of your brand or company, as the classifier should use it."},"description":{"type":"string","description":"A paragraph on what the company does."},"useCases":{"type":"array","items":{"type":"string"},"description":"Typical uses of the product."},"accounts":{"type":"object","properties":{"x":{"type":"string","nullable":true,"description":"Your X handle, without @."},"linkedin":{"type":"string","nullable":true,"description":"Your LinkedIn page, as its slug or link."}},"required":["x","linkedin"],"description":"Your company's accounts, so posts from them are recognized as yours."},"website":{"type":"string","nullable":true,"description":"The company's website, as entered during onboarding."},"competitors":{"type":"array","items":{"type":"string"},"description":"Names of competitors, so the classifier knows when a post is about one of them. Often the same names as your competitor keywords."},"guidelines":{"type":"string","nullable":true,"description":"Rules for the classifier in your own words, saying what is relevant to you and what never is, for example \"questions about our SDK, never job ads\". After the description, this has the most effect on scores."},"context":{"type":"string","description":"Classifier input. Built from the other fields unless you write it yourself."}},"required":["name","description","useCases","accounts","website","competitors","guidelines","context"]},"Whoami":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string","description":"The workspace's id (org_...)."},"name":{"type":"string","description":"The workspace's name as shown in the dashboard."}},"required":["id","name"],"description":"The workspace this credential works in."},"auth":{"type":"object","properties":{"kind":{"type":"string","enum":["api_key","oauth","session"],"description":"Which credential was used. API key, MCP sign-in token or dashboard session."},"scope":{"type":"string","enum":["read","write"],"description":"write can do everything. read is limited to GET."},"apiKeyId":{"type":"string","nullable":true,"description":"The API key's id (key_...). Null for other credentials."},"expiresAt":{"type":"string","nullable":true,"description":"Expiry of the API key. Null for non-expiring keys, OAuth tokens and sessions."}},"required":["kind","scope","apiKeyId","expiresAt"],"description":"Details of the credential used."},"user":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The user's id. Use it for assigneeId and ownerId."},"email":{"type":"string","description":"The user's email address."},"name":{"type":"string","nullable":true,"description":"The user's name. Null if they have not set one."}},"required":["id","email","name"],"description":"The user who signed in, for an OAuth token or a session. Null for an API key, since a key is not tied to a user."}},"required":["workspace","auth","user"]},"Member":{"type":"object","properties":{"id":{"type":"string","description":"The membership's id (mem_...). Use it with DELETE /v1/members/{id}."},"userId":{"type":"string","description":"The member's user id. Use it for assigneeId and ownerId."},"email":{"type":"string","description":"The user's email address."},"name":{"type":"string","nullable":true,"description":"The user's name. Null if they have not set one."},"role":{"type":"string","enum":["owner","admin","member"],"description":"owner can do everything, including billing. admin can also manage the team. member works with the feed."},"joinedAt":{"type":"string","description":"When the member joined."}},"required":["id","userId","email","name","role","joinedAt"]},"Invitation":{"type":"object","properties":{"id":{"type":"string","description":"The invitation's id (inv_...)."},"email":{"type":"string","description":"The email address invited, in lowercase."},"role":{"type":"string","enum":["owner","admin","member"],"description":"The role they get when they join."},"invitedBy":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string","nullable":true}},"required":["id","email","name"],"description":"The member who sent it. Invitations sent with an API key come from the oldest owner."},"expiresAt":{"type":"string","description":"When the invitation expires, 48 hours after it was sent. Expired invitations are not listed."},"createdAt":{"type":"string","description":"When it was sent."}},"required":["id","email","role","invitedBy","expiresAt","createdAt"]},"UsageSummary":{"type":"object","properties":{"balance":{"type":"object","properties":{"cents":{"type":"integer","description":"The ledger balance, all credits minus all settled debits."},"pendingCents":{"type":"integer","description":"Cost of mentions matched after the last daily settlement. Not debited yet."},"effectiveCents":{"type":"integer","description":"cents minus pendingCents. Pausing at zero and the check before adding keywords both use this number."},"currency":{"type":"string","enum":["USD"]}},"required":["cents","pendingCents","effectiveCents","currency"],"description":"The prepaid balance."},"burn":{"type":"object","properties":{"perDayCents":{"type":"integer","description":"Mean daily debit across the past 7 days, or the workspace's lifetime if shorter."},"daysLeft":{"type":"integer","nullable":true,"minimum":0,"description":"effectiveCents over perDayCents, rounded down. Null when perDayCents is 0."}},"required":["perDayCents","daysLeft"],"description":"How quickly the balance is being spent."},"keywords":{"type":"object","properties":{"active":{"type":"integer","minimum":0,"description":"Keywords that are not muted. These are charged each day."},"paused":{"type":"integer","minimum":0,"description":"Keywords paused because the balance ran out. A top-up resumes them."},"capped":{"type":"integer","minimum":0,"description":"Keywords that are not muted but reached their monthly mention cap. They are still charged each day and are not matched until the next month or until the cap is raised."},"limit":{"type":"integer","minimum":0,"description":"Keywords the workspace may run now. 0 if the balance can't cover one more keyword-day, otherwise the self-serve maximum."},"dayCents":{"type":"integer","description":"Daily cost of the active keywords."}},"required":["active","paused","capped","limit","dayCents"],"description":"Keyword counts compared with the balance."},"mentions":{"type":"object","properties":{"today":{"type":"integer","minimum":0,"description":"Count of matches since midnight UTC, relevant or not."},"last30d":{"type":"integer","minimum":0,"description":"Match count for the past 30 days."}},"required":["today","last30d"],"description":"Matched mentions, which are billed along with keyword-days."},"stopped":{"type":"boolean","description":"True when tracking is paused because the balance ran out. It resumes after a top-up that covers one day of every keyword."},"lowBalance":{"type":"boolean","description":"true when 20 percent or less of the last credit remains (effective balance) and tracking is on."},"lastTopUpAt":{"type":"string","nullable":true,"description":"Latest paid top-up time, or null if there is none."}},"required":["balance","burn","keywords","mentions","stopped","lowBalance","lastTopUpAt"]},"UsageBreakdown":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","description":"Start date (UTC, YYYY-MM-DD), included."},"to":{"type":"string","description":"The last day included. It is today for a trailing range or the current month."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."},"keywordDaysFrom":{"type":"string","nullable":true,"description":"Earliest day in the window with a keyword count, or null. Earlier days show `keywordDays: null`."}},"required":["from","to","days","keywordDaysFrom"],"description":"Report range in UTC days."},"by":{"type":"string","enum":["day","platform","keyword","group"],"description":"Grouping used for the rows."},"currency":{"type":"string","enum":["USD"],"description":"All amounts are in US cents."},"totals":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Sum of keyword-days over the window."},"keywordCents":{"type":"integer","description":"Those keyword-days priced at $5 a month (500/30 cents a day), with the total rounded once."},"matchedMentions":{"type":"integer","minimum":0,"description":"Match count for the window, relevant or not."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed in the window that fall in this row. Every scored match is billed, relevant or not."},"mentionCents":{"type":"integer","description":"Those mentions priced at $0.008 each, with the total rounded once."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents."},"unclassifiedMentions":{"type":"integer","minimum":0,"description":"Matches whose classification failed. They are never charged."},"ledgerDebitCents":{"type":"integer","description":"Debits recorded so far for the window's days, each on its settlement day. Mentions settle the next morning, so a window ending today trails totalCents by today's mentions, plus yesterday's before the 00:05 UTC run. A closed month differs only by cumulative rounding."},"unattributedBillable":{"type":"integer","minimum":0,"description":"Billed mentions whose match was removed with a deleted keyword, so they belong to no platform or keyword row. They were still charged."}},"required":["keywordDays","keywordCents","matchedMentions","billableMentions","mentionCents","totalCents","unclassifiedMentions","ledgerDebitCents","unattributedBillable"],"description":"Totals for the whole window. They are the same whatever `by` is."},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"What the row stands for. A UTC day (YYYY-MM-DD) with by=day, a platform with by=platform, a keyword id with by=keyword and a group id with by=group."},"label":{"type":"string","description":"A name to display. The keyword's term or the group's name, or else the key."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The keyword's id (kw_...). Deleted keywords keep their id here."},"term":{"type":"string","description":"The term when it was last charged, or its current term."},"removed":{"type":"boolean","description":"The keyword was deleted later. Charges remain, but its mentions are gone, so mention counts are 0."}},"required":["id","term","removed"],"description":"Set only with by=keyword. Null otherwise."},"group":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The group's id. It is \"none\" for keyword-days charged before groups existed when the keyword has since been deleted."},"name":{"type":"string","description":"Current group name, or \"Deleted group\" or \"No group\"."},"removed":{"type":"boolean","description":"True when the group was deleted later."}},"required":["id","name","removed"],"description":"Set only with by=group. Null otherwise."},"keywordDays":{"type":"integer","nullable":true,"minimum":0,"description":"Keyword-days charged in this row by the daily run. Null with by=platform, since a keyword-day has no platform, and for days before the first recorded run, where the count is unknown rather than zero. A keyword row only counts recorded days, so before window.keywordDaysFrom it is a minimum, not zero."},"keywordCents":{"type":"integer","description":"Those keyword-days priced at $5 a month (500/30 cents a day), with the total rounded once."},"matchedMentions":{"type":"integer","minimum":0,"description":"Match count for the window, relevant or not."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed in the window that fall in this row. Every scored match is billed, relevant or not."},"mentionCents":{"type":"integer","description":"Those mentions priced at $0.008 each, with the total rounded once."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents."}},"required":["key","label","keyword","group","keywordDays","keywordCents","matchedMentions","billableMentions","mentionCents","totalCents"]},"description":"With by=day the rows are in date order. With by=platform and by=keyword the most expensive come first, then those with the most matches, deleted keywords included."},"total":{"type":"integer","minimum":0,"description":"The number of rows before `limit` and `offset` are applied."}},"required":["window","by","currency","totals","data","total"]},"Wallet":{"type":"object","properties":{"balanceCents":{"type":"integer","description":"The ledger balance, all credits minus all settled debits."},"pendingCents":{"type":"integer","description":"Cost of mentions matched after the last daily settlement. Not debited yet."},"effectiveBalanceCents":{"type":"integer","description":"balanceCents minus pendingCents. Pausing at zero and the check before adding keywords both use this number."},"burnPerDayCents":{"type":"integer","description":"Mean daily debit across the past 7 days, or the workspace's lifetime if shorter."},"daysLeft":{"type":"integer","nullable":true,"minimum":0,"description":"effectiveBalanceCents over burnPerDayCents, rounded down. Null when burnPerDayCents is 0."},"stopped":{"type":"boolean","description":"True when tracking is paused because the balance ran out. It resumes after a top-up that covers one day of every keyword."},"lowBalance":{"type":"boolean","description":"True when tracking is running and the effective balance is 20 percent of the last credit or less. The low-balance email uses the same rule."},"activeKeywords":{"type":"integer","minimum":0,"description":"Keywords that are not muted."},"autoMutedKeywords":{"type":"integer","minimum":0,"description":"Keywords muted for low balance. A top-up restarts them."},"nextDayCents":{"type":"integer","description":"Next day's cost for the running keywords. Tracking stops if the effective balance drops below it."},"resumeCostCents":{"type":"integer","description":"Daily cost of every keyword, running or paused. Tracking restarts once the effective balance reaches this amount."},"signupCredit":{"type":"object","nullable":true,"properties":{"amountCents":{"type":"integer","description":"Whole US cents."},"grantedAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["amountCents","grantedAt"],"description":"Welcome credit given to this workspace. Null when the user already got it in another workspace."},"lastTopUpAt":{"type":"string","nullable":true,"description":"Latest paid top-up time, or null if there is none."},"billingConfigured":{"type":"boolean","description":"Whether top-ups work here. false when Polar isn't configured, which hides the top-up button."},"minTopUpCents":{"type":"integer","description":"The minimum top-up at checkout."},"maxTopUpCents":{"type":"integer","description":"The maximum for one top-up."},"defaultTopUpCents":{"type":"integer","description":"The amount the checkout starts with."},"currency":{"type":"string","enum":["USD"],"description":"All amounts here are in US cents."},"autoRecharge":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether saved-card charging works on this deployment. The setting is hidden when false."},"enabled":{"type":"boolean","description":"When true, the saved card is charged automatically if the balance gets low."},"thresholdCents":{"type":"integer","description":"The card is charged when the effective balance falls below this."},"amountCents":{"type":"integer","description":"The amount each automatic charge adds, within the same limits as a manual top-up."},"lastRunAt":{"type":"string","nullable":true,"description":"Time of the latest successful automatic charge."},"lastError":{"type":"string","nullable":true,"description":"Error of the last failed automatic charge, cleared by a successful one."}},"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":"The ledger entry's id (led_...)."},"kind":{"type":"string","enum":["signup_credit","topup","refund","debit_keyword_days","debit_mentions","adjustment"],"description":"Type of ledger entry."},"amountCents":{"type":"integer","description":"Whole US cents. Credits are positive and debits negative."},"day":{"type":"string","nullable":true,"description":"For debits, the last UTC day this entry settles (YYYY-MM-DD)."},"units":{"type":"integer","nullable":true,"description":"For debits, the running total of mentions or keyword-days settled up to and including this entry."},"note":{"type":"string","nullable":true,"description":"Note attached to a credit or adjustment."},"polarOrderId":{"type":"string","nullable":true,"description":"Polar order of a top-up or refund. Null otherwise."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["id","kind","amountCents","day","units","note","polarOrderId","createdAt"]},"description":"Ledger entries, latest first."},"nextCursor":{"type":"string","nullable":true,"description":"Cursor for the next page, or null when there are no more pages."}},"required":["data","nextCursor"]},"InvoiceList":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pass it to GET /v1/billing/invoices/{id}/url for the receipt."},"createdAt":{"type":"string","description":"Order date and time (ISO 8601)."},"status":{"type":"string","description":"Polar's status for the order, such as paid or refunded."},"paid":{"type":"boolean","description":"True if the order is paid."},"totalAmount":{"type":"integer","description":"The amount charged including tax, in the smallest unit of `currency`."},"currency":{"type":"string","description":"The order's currency as an ISO 4217 code, such as usd."},"billingReason":{"type":"string","nullable":true,"description":"Polar's reason for the order, such as purchase or subscription_cycle. Null when Polar gives none."}},"required":["id","createdAt","status","paid","totalAmount","currency","billingReason"]},"description":"Most recent paid orders first. None until the first top-up."}},"required":["data"]},"Alert":{"type":"object","properties":{"id":{"type":"string","description":"The alert's id (feed_...)."},"name":{"type":"string"},"enabled":{"type":"boolean"},"mode":{"type":"string","enum":["instant","hourly","daily","weekly"],"description":"instant sends each matching mention as it arrives. hourly sends a digest of the previous full UTC hour at five past the hour, so the hour's last mentions are scored. It skips hours with no mention at or above the rule's relevance minimum, and works with Slack, Telegram and webhook channels only. daily sends one digest at the scheduled local time. weekly sends one digest a week on schedule.weekday."},"filter":{"type":"object","properties":{"keywordIds":{"type":"array","items":{"type":"string"},"description":"Limits the rule to these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Limits the rule to keywords in these groups (grp_...), for example one rule for each client."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"description":"Limits the rule to posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The lowest relevance score the rule sends. Without it, only relevant mentions are sent, meaning a score of 40 or more. A lower value, down to 0, also sends matches the classifier rated as noise. A higher value sends fewer. Email channels always use 40, whatever the rule says. Mentions without a score are never sent."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Sends only mentions whose classifier confidence is this value or higher, from 0 to 1. Mentions without a confidence are left out."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"description":"Keeps mentions with these sentiments only."},"intents":{"type":"array","items":{"type":"string"},"description":"Sends only mentions with one or more of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"minFollowers":{"type":"integer","minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Sends only posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Posts without links are left out."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"automated":{"type":"boolean","description":"true sends only posts that look machine-made, such as bot or template posts. false sends only the others. Leave it out to send both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Sends only reviews with one of these star ratings, from 1 to 5. Use [1, 2] for the unhappy ones. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to skip, such as [5]. Other posts still go out."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}}},"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":"The day a weekly rule sends, from 0 for Sunday to 6 for Saturday. Required when mode is weekly and ignored for daily rules."}},"required":["hour","timezone"],"description":"Null for instant and hourly alerts, which have no schedule."},"event":{"type":"string","description":"The event name sent in webhook payloads. Unless you set one, it is the default for the mode."},"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":"The channels the alert sends to."},"stats":{"type":"object","properties":{"sentLast7d":{"type":"integer","minimum":0,"description":"Deliveries over the past 7 days, all channels together."},"lastSentAt":{"type":"string","nullable":true,"description":"UTC time in ISO 8601."},"nextRunAt":{"type":"string","nullable":true,"description":"When the next digest is due, for hourly, daily and weekly alerts. Null when the alert is disabled or instant."}},"required":["sentLast7d","lastSentAt","nextRunAt"],"description":"Counted from this workspace's deliveries."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."}},"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":"The first day included."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day included."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."},"timezone":{"type":"string","description":"The IANA time zone used to split the days."}},"required":["from","to","days","timezone"],"description":"Start and end of the period."},"matched":{"type":"integer","minimum":0,"description":"All matches in the window, relevant or not. Usage counts this number."},"relevant":{"type":"integer","minimum":0,"description":"Matches whose relevance score reached the threshold."},"posts":{"type":"integer","minimum":0,"description":"Unique posts among the matches. A post that matches two keywords counts as two matches but one post."},"people":{"type":"integer","minimum":0,"description":"Unique authors among the matches."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0,"description":"Matches with positive sentiment."},"neutral":{"type":"integer","minimum":0,"description":"Matches with neutral sentiment."},"negative":{"type":"integer","minimum":0,"description":"Matches with negative sentiment."},"unclassified":{"type":"integer","minimum":0,"description":"Matches without a score, either still waiting or failed."}},"required":["positive","neutral","negative","unclassified"],"description":"Sentiment split of the matched mentions."},"buyIntent":{"type":"integer","minimum":0,"description":"Matches tagged buy_intent."},"questions":{"type":"integer","minimum":0,"description":"Matches tagged question."},"reach":{"type":"object","properties":{"followers":{"type":"integer","minimum":0,"description":"The total followers of the unique authors with a known count. A rough idea of how many feeds the posts reached."},"people":{"type":"integer","minimum":0,"description":"The number of `people` whose follower count is known."}},"required":["followers","people"],"description":"An estimate of reach."},"triage":{"type":"object","properties":{"open":{"type":"integer","minimum":0,"description":"Matches with status open."},"ignored":{"type":"integer","minimum":0,"description":"Matches with status ignored."},"done":{"type":"integer","minimum":0,"description":"Matches with status done."},"waiting":{"type":"integer","minimum":0,"description":"Relevant matches still open more than 24 hours after they matched."},"handledRate":{"type":"number","nullable":true,"description":"The done count over the relevant count. Null if nothing was relevant."},"medianTimeToDoneMs":{"type":"number","nullable":true,"description":"The median time in milliseconds between a match and its done status. Null when nothing is done."}},"required":["open","ignored","done","waiting","handledRate","medianTimeToDoneMs"],"description":"The status of the matches in your inbox."},"previous":{"type":"object","nullable":true,"properties":{"matched":{"type":"integer","minimum":0,"description":"All matches in the window, relevant or not. Usage counts this number."},"relevant":{"type":"integer","minimum":0,"description":"Matches whose relevance score reached the threshold."},"posts":{"type":"integer","minimum":0,"description":"Unique posts among the matches. A post that matches two keywords counts as two matches but one post."},"people":{"type":"integer","minimum":0,"description":"Unique authors among the matches."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0,"description":"Matches with positive sentiment."},"neutral":{"type":"integer","minimum":0,"description":"Matches with neutral sentiment."},"negative":{"type":"integer","minimum":0,"description":"Matches with negative sentiment."},"unclassified":{"type":"integer","minimum":0,"description":"Matches without a score, either still waiting or failed."}},"required":["positive","neutral","negative","unclassified"],"description":"Sentiment split of the matched mentions."},"buyIntent":{"type":"integer","minimum":0,"description":"Matches tagged buy_intent."},"questions":{"type":"integer","minimum":0,"description":"Matches tagged question."},"reach":{"type":"object","properties":{"followers":{"type":"integer","minimum":0,"description":"The total followers of the unique authors with a known count. A rough idea of how many feeds the posts reached."},"people":{"type":"integer","minimum":0,"description":"The number of `people` whose follower count is known."}},"required":["followers","people"],"description":"An estimate of reach."},"triage":{"type":"object","properties":{"open":{"type":"integer","minimum":0,"description":"Matches with status open."},"ignored":{"type":"integer","minimum":0,"description":"Matches with status ignored."},"done":{"type":"integer","minimum":0,"description":"Matches with status done."},"waiting":{"type":"integer","minimum":0,"description":"Relevant matches still open more than 24 hours after they matched."},"handledRate":{"type":"number","nullable":true,"description":"The done count over the relevant count. Null if nothing was relevant."},"medianTimeToDoneMs":{"type":"number","nullable":true,"description":"The median time in milliseconds between a match and its done status. Null when nothing is done."}},"required":["open","ignored","done","waiting","handledRate","medianTimeToDoneMs"],"description":"The status of the matches in your inbox."}},"required":["matched","relevant","posts","people","sentiment","buyIntent","questions","reach","triage"],"description":"With compare=true, the same counts for the equal period before. Otherwise null."}},"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":"The first day included."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day included."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."},"timezone":{"type":"string","description":"The IANA time zone used to split the days."},"bucket":{"type":"string","enum":["hour","day","week","month"],"description":"The size of each point. One of hour, day, week (Monday to Sunday) or month."}},"required":["from","to","days","timezone","bucket"],"description":"Start and end of the period."},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"A platform name, a keyword id or a sentiment (positive, neutral, negative, unclassified). It is \"total\" when the series is not split and \"other\" for everything past the top 20."},"label":{"type":"string","description":"Display name such as a platform, keyword term or sentiment, or \"Total\" and \"Other\"."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The keyword's group."}]}},"required":["id","term","kind","group"],"description":"The keyword, when split by keyword. Otherwise null."},"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"Start of the point in `timezone`. YYYY-MM-DD for a day, the Monday for a week, the 1st for a month, or YYYY-MM-DDTHH:00 for an hour."},"matched":{"type":"integer","minimum":0,"description":"All matches published during this point."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored 40 or more."},"positive":{"type":"integer","minimum":0,"description":"Matches with positive sentiment."},"neutral":{"type":"integer","minimum":0,"description":"Matches with neutral sentiment."},"negative":{"type":"integer","minimum":0,"description":"Matches with negative sentiment."},"unclassified":{"type":"integer","minimum":0,"description":"Matches without a score, either still waiting or failed."}},"required":["date","matched","relevant","positive","neutral","negative","unclassified"]},"description":"A point for every step of the window, oldest first, with zeros where nothing matched."}},"required":["key","label","keyword","points"]},"description":"One item for each series, the one with the most matches first. Without a split there is a single \"total\" item."},"previous":{"type":"array","nullable":true,"items":{"type":"object","properties":{"key":{"type":"string","description":"A platform name, a keyword id or a sentiment (positive, neutral, negative, unclassified). It is \"total\" when the series is not split and \"other\" for everything past the top 20."},"label":{"type":"string","description":"Display name such as a platform, keyword term or sentiment, or \"Total\" and \"Other\"."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The keyword's group."}]}},"required":["id","term","kind","group"],"description":"The keyword, when split by keyword. Otherwise null."},"points":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"Start of the point in `timezone`. YYYY-MM-DD for a day, the Monday for a week, the 1st for a month, or YYYY-MM-DDTHH:00 for an hour."},"matched":{"type":"integer","minimum":0,"description":"All matches published during this point."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored 40 or more."},"positive":{"type":"integer","minimum":0,"description":"Matches with positive sentiment."},"neutral":{"type":"integer","minimum":0,"description":"Matches with neutral sentiment."},"negative":{"type":"integer","minimum":0,"description":"Matches with negative sentiment."},"unclassified":{"type":"integer","minimum":0,"description":"Matches without a score, either still waiting or failed."}},"required":["date","matched","relevant","positive","neutral","negative","unclassified"]},"description":"A point for every step of the window, oldest first, with zeros where nothing matched."}},"required":["key","label","keyword","points"]},"description":"With compare=true, the same items for the prior period in the same order, index-aligned with `data`. The last point can be missing when weeks split differently. Otherwise null."}},"required":["window","data","previous"]},"AnalyticsBreakdown":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day included."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day included."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."},"timezone":{"type":"string","description":"The IANA time zone used to split the days."}},"required":["from","to","days","timezone"],"description":"Start and end of the period."},"by":{"type":"string","enum":["platform","keyword","sentiment","intent","status","hour","person","language"],"description":"Grouping used for the rows."},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"What the row stands for. A platform name, keyword id, sentiment, intent or status, \"weekday-hour\" with by=hour, or a person key you should not parse."},"label":{"type":"string","description":"A name to display. The keyword's term or the person's name, or else the key."},"keyword":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The keyword's group."}]}},"required":["id","term","kind","group"],"description":"Set only with by=keyword. Null otherwise."},"person":{"type":"object","nullable":true,"properties":{"id":{"type":"string","nullable":true,"description":"The person's aut_... id. Older posts, from before people were linked, have null."},"name":{"type":"string","nullable":true,"description":"The name shown on the platform."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"url":{"type":"string","nullable":true,"description":"Link to the profile."},"avatarUrl":{"type":"string","nullable":true,"description":"Link to the profile picture, if the platform provided one."},"followers":{"type":"integer","nullable":true,"minimum":0,"description":"Follower count from the audience profile, or null."}},"required":["id","name","platform","url","avatarUrl","followers"],"description":"Set only with by=person. Null otherwise."},"slot":{"type":"object","nullable":true,"properties":{"weekday":{"type":"integer","minimum":0,"maximum":6,"description":"The day of the week, from 0 for Sunday to 6 for Saturday."},"hour":{"type":"integer","minimum":0,"maximum":23,"description":"The hour, from 0 to 23."}},"required":["weekday","hour"],"description":"Weekday and hour in `timezone` when by=hour, otherwise null."},"matched":{"type":"integer","minimum":0,"description":"Matches in this row."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored 40 or more."},"share":{"type":"number","description":"The percentage of the window's matches that fall in this row, with one decimal. A mention can have several intents, so intent shares can total more than 100."},"sentiment":{"type":"object","properties":{"positive":{"type":"integer","minimum":0,"description":"Matches with positive sentiment."},"neutral":{"type":"integer","minimum":0,"description":"Matches with neutral sentiment."},"negative":{"type":"integer","minimum":0,"description":"Matches with negative sentiment."},"unclassified":{"type":"integer","minimum":0,"description":"Matches without a score, either still waiting or failed."}},"required":["positive","neutral","negative","unclassified"],"description":"Sentiment split of the matched mentions."},"previous":{"type":"object","nullable":true,"properties":{"matched":{"type":"integer","minimum":0,"description":"Matches in this row during that period."},"relevant":{"type":"integer","minimum":0,"description":"Relevant matches in this row during that period."}},"required":["matched","relevant"],"description":"This row for the period just before the window. Null unless compare=true."}},"required":["key","label","keyword","person","slot","matched","relevant","share","sentiment","previous"]},"description":"Up to 50 rows, the one with the most matches first. With by=hour the rows are in time order and not limited, so up to 168."}},"required":["window","by","data"]},"ShareOfVoice":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day included."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day included."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."},"timezone":{"type":"string","description":"The IANA time zone used to split the days."}},"required":["from","to","days","timezone"],"description":"Start and end of the period."},"data":{"type":"array","items":{"type":"object","properties":{"keyword":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string","description":"The term being tracked."},"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"The keyword's kind, brand, competitor or topic."},"group":{"allOf":[{"$ref":"#/components/schemas/GroupRef"},{"description":"The keyword's group."}]}},"required":["id","term","kind","group"],"description":"Which keyword the row covers."},"matched":{"type":"integer","minimum":0,"description":"This keyword's match count in the window."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored 40 or more."},"negative":{"type":"integer","minimum":0,"description":"How many of them were negative."},"buyIntent":{"type":"integer","minimum":0,"description":"How many of them were tagged buy_intent."},"share":{"type":"number","nullable":true,"description":"The percentage of all brand and competitor matches, with one decimal. Null for topics, which are not part of the split."},"previous":{"type":"object","nullable":true,"properties":{"matched":{"type":"integer","minimum":0,"description":"The keyword's matches during that period."}},"required":["matched"],"description":"With compare=true, this keyword for the prior period. Otherwise null."}},"required":["keyword","matched","relevant","negative","buyIntent","share","previous"]},"description":"All keywords with matches in the window, the one with the most first."}},"required":["window","data"]},"ReviewsReport":{"type":"object","properties":{"window":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The first day included."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The last day included."},"days":{"type":"integer","minimum":0,"description":"How many days the window spans."},"timezone":{"type":"string","description":"The IANA time zone used to split the days."},"bucket":{"type":"string","enum":["day","week"],"description":"The step of each page's series. Days for windows up to 90 days and weeks beyond, unless you ask for one."}},"required":["from","to","days","timezone","bucket"],"description":"Start and end of the period."},"totals":{"type":"object","properties":{"reviews":{"type":"integer","minimum":0,"description":"Reviews published in the window, counting each review once across keywords."},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"The average star rating with one decimal. Null when there are 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":"How many reviews have each star rating."},"responded":{"type":"integer","minimum":0,"description":"Reviews with a reply from the owner or developer. The App Store feed has no replies."},"openNegative":{"type":"integer","minimum":0,"description":"Reviews of 1 or 2 stars still open in triage."}},"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":"The intent and topic tags of 1 and 2 star reviews, most common first. They show what unhappy reviewers write about."},"pages":{"type":"array","items":{"type":"object","properties":{"reviews":{"type":"integer","minimum":0,"description":"Reviews published in the window, counting each review once across keywords."},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"The average star rating with one decimal. Null when there are 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":"How many reviews have each star rating."},"responded":{"type":"integer","minimum":0,"description":"Reviews with a reply from the owner or developer. The App Store feed has no replies."},"openNegative":{"type":"integer","minimum":0,"description":"Reviews of 1 or 2 stars still open in triage."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"Where the reviews come from. appstore is the Apple App Store, googleplay is Google Play, trustpilot is a company's Trustpilot page and googlemaps is the Google reviews of a place."},"id":{"type":"string","description":"Page id. Trustpilot domain, Place ID or cid, or the app's id or package name."},"url":{"type":"string","description":"Link to the review page."},"series":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"The first day of the step, as YYYY-MM-DD."},"reviews":{"type":"integer","minimum":0},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"The average star rating with one decimal. Null when there are no reviews."}},"required":["date","reviews","averageRating"]},"description":"Reviews and average stars for every step, oldest first, with no gaps."},"previous":{"type":"object","nullable":true,"properties":{"reviews":{"type":"integer","minimum":0},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"The average star rating with one decimal. Null when there are no reviews."}},"required":["reviews","averageRating"],"description":"The equally long period just before the window, when compare=true. Null otherwise."}},"required":["reviews","averageRating","distribution","responded","openNegative","platform","id","url","series","previous"]},"description":"A row for each review page with reviews in the window, the page with the most first."},"previous":{"type":"object","nullable":true,"properties":{"reviews":{"type":"integer","minimum":0,"description":"Reviews published in the window, counting each review once across keywords."},"averageRating":{"type":"number","nullable":true,"minimum":1,"maximum":5,"description":"The average star rating with one decimal. Null when there are 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":"How many reviews have each star rating."},"responded":{"type":"integer","minimum":0,"description":"Reviews with a reply from the owner or developer. The App Store feed has no replies."},"openNegative":{"type":"integer","minimum":0,"description":"Reviews of 1 or 2 stars still open in triage."}},"required":["reviews","averageRating","distribution","responded","openNegative"],"description":"With compare=true, totals for the period before the window. Otherwise null."}},"required":["window","totals","tags","pages","previous"]},"SlackChannel":{"type":"object","properties":{"id":{"type":"string","description":"The channel's id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Number of alerts using this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"How many of them are enabled. At 0 the channel currently gets nothing."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Time of the latest delivery attempt, whether it worked or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries over the past 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Counted from this workspace's deliveries."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"kind":{"type":"string","enum":["slack"]},"config":{"type":"object","properties":{"channelId":{"type":"string","description":"The Slack channel's id."},"channelName":{"type":"string","description":"The Slack channel's name, without #."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike flags an hour with far more mentions than usual, and sentiment.negative_spike a jump in the negative share over 24 hours. keyword.noisy flags a keyword whose scored matches are mostly noise, and channel.failing a channel whose recent sends all failed."},"description":"Attention events this channel gets directly, without a rule. Each sends one short message when an item opens (see GET /v1/attention). Empty when there are none."}},"required":["channelId","channelName","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"EmailChannel":{"type":"object","properties":{"id":{"type":"string","description":"The channel's id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Number of alerts using this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"How many of them are enabled. At 0 the channel currently gets nothing."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Time of the latest delivery attempt, whether it worked or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries over the past 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Counted from this workspace's deliveries."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"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 is confirmed with its link. Addresses that are not confirmed get nothing."}},"required":["email","confirmedAt"]},"description":"All addresses on the list, each with its confirmation."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike flags an hour with far more mentions than usual, and sentiment.negative_spike a jump in the negative share over 24 hours. keyword.noisy flags a keyword whose scored matches are mostly noise, and channel.failing a channel whose recent sends all failed."},"description":"Attention events this channel gets directly, without a rule. Each sends one short message when an item opens (see GET /v1/attention). Empty when there are none."}},"required":["recipients","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"WebhookChannel":{"type":"object","properties":{"id":{"type":"string","description":"The channel's id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Number of alerts using this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"How many of them are enabled. At 0 the channel currently gets nothing."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Time of the latest delivery attempt, whether it worked or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries over the past 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Counted from this workspace's deliveries."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"kind":{"type":"string","enum":["webhook"]},"config":{"type":"object","properties":{"url":{"type":"string","description":"The URL that receives the signed POST requests."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional headers you set for each request."},"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":"Account events are keyword.capped (hit the monthly cap, stops matching), keyword.paused_for_balance (paused when the balance ran out), keyword.resumed (matching again, cause in reason), wallet.low (effective balance down to 20% of the last credit, once per credit), wallet.paused (every keyword paused) and wallet.resumed (a credit restarted them). Attention events go out once when an item opens (GET /v1/attention). They are mention.spike (far more mentions than usual in the last hour), sentiment.negative_spike (24-hour negative share jumped), keyword.noisy (scored matches mostly noise) and channel.failing (recent sends all failed)."},"description":"Account events this endpoint gets directly, without a rule. These are keyword and wallet changes and the attention events. Empty when there are none. Mentions and digests still arrive through rules."},"secret":{"type":"string","description":"Returned only when the channel is created or the secret rotated. It signs each request. X-Mentions-Signature-V2 holds v2= followed by the hex HMAC-SHA256 of \"<X-Mentions-Timestamp>.<raw body>\". Reject timestamps more than a few minutes old. X-Mentions-Signature, the hex HMAC-SHA256 of the raw body only, is still sent for older verifiers."}},"required":["url","headers","events"]}},"required":["id","label","stats","createdAt","kind","config"]},"TelegramChannel":{"type":"object","properties":{"id":{"type":"string","description":"The channel's id (dest_...)."},"label":{"type":"string"},"stats":{"type":"object","properties":{"alerts":{"type":"integer","minimum":0,"description":"Number of alerts using this channel."},"activeAlerts":{"type":"integer","minimum":0,"description":"How many of them are enabled. At 0 the channel currently gets nothing."},"lastDeliveryAt":{"type":"string","nullable":true,"description":"Time of the latest delivery attempt, whether it worked or not."},"last7d":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","failed"],"description":"Deliveries over the past 7 days."}},"required":["alerts","activeAlerts","lastDeliveryAt","last7d"],"description":"Counted from this workspace's deliveries."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"kind":{"type":"string","enum":["telegram"]},"config":{"type":"object","properties":{"chatId":{"type":"string","description":"The Telegram chat's 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 flags an hour with far more mentions than usual, and sentiment.negative_spike a jump in the negative share over 24 hours. keyword.noisy flags a keyword whose scored matches are mostly noise, and channel.failing a channel whose recent sends all failed."},"description":"Attention events this channel gets directly, without a rule. Each sends one short message when an item opens (see GET /v1/attention). Empty when there are 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":"The id of a channel in the connected Slack workspace."},"channelName":{"type":"string","minLength":1,"maxLength":90,"description":"The Slack channel's name, used as the label."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike flags an hour with far more mentions than usual, and sentiment.negative_spike a jump in the negative share over 24 hours. keyword.noisy flags a keyword whose scored matches are mostly noise, and channel.failing a channel whose recent sends all failed."},"maxItems":4,"description":"Attention events to send here, in addition to what rules send. Leave it out 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 link to confirm it. Workspace members are confirmed right away."},"events":{"type":"array","items":{"type":"string","enum":["mention.spike","sentiment.negative_spike","keyword.noisy","channel.failing"],"description":"mention.spike flags an hour with far more mentions than usual, and sentiment.negative_spike a jump in the negative share over 24 hours. keyword.noisy flags a keyword whose scored matches are mostly noise, and channel.failing a channel whose recent sends all failed."},"maxItems":4,"description":"Attention events to send here, in addition to what rules send. Leave it out for none."}},"required":["kind","emails"]},"CreateWebhookChannel":{"type":"object","properties":{"kind":{"type":"string","enum":["webhook"]},"url":{"type":"string","format":"uri","description":"The URL that receives the signed POST requests. Must be https in production."},"label":{"type":"string","maxLength":80,"description":"A name for the channel. Defaults to the URL's host."},"headers":{"type":"object","additionalProperties":{"type":"string","maxLength":1024},"description":"Additional headers to send with each request, such as 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":"Account events are keyword.capped (hit the monthly cap, stops matching), keyword.paused_for_balance (paused when the balance ran out), keyword.resumed (matching again, cause in reason), wallet.low (effective balance down to 20% of the last credit, once per credit), wallet.paused (every keyword paused) and wallet.resumed (a credit restarted them). Attention events go out once when an item opens (GET /v1/attention). They are mention.spike (far more mentions than usual in the last hour), sentiment.negative_spike (24-hour negative share jumped), keyword.noisy (scored matches mostly noise) and channel.failing (recent sends all failed)."},"maxItems":10,"description":"Account events to send to this endpoint, in addition to what rules send. These are keyword and wallet changes and attention events. Leave it out for none."}},"required":["kind","url"]}},"parameters":{}},"paths":{"/v1/health":{"get":{"operationId":"getHealth","description":"Checks that the API is up. Needs no key and is not rate limited. Returns `ok: true` with the state of the database and each background worker.","tags":["System"],"responses":{"200":{"description":"The API is running","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}},"required":["ok"]}}}}}}},"/v1/keywords":{"post":{"operationId":"createKeyword","summary":"Create a keyword","description":"Starts monitoring a word or phrase. Matching, scoring and delivery start with the next poll. A workspace with balance can have up to 500 keywords, each costing $5 a month, taken from the balance day by day. `matching` narrows what counts as a match, with required and excluded terms, excluded authors and case, before anything is stored, so rejected posts are never billed. `context` is a sentence only this keyword's classifier reads. `cap` limits matched mentions per month. At the cap the keyword stops matching until the 1st of next month (UTC) or until you raise the cap, and its daily 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 monitor. It matches as a whole phrase, ignoring case."},"kind":{"type":"string","enum":["brand","competitor","topic"],"default":"brand","description":"brand is for your own names, competitor for a rival's, and topic for your market. Share of voice and segments use it."},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"The platforms to search for the term. Leave it out or send null for all platforms. An empty list searches nowhere, for a keyword that only collects reviews and so needs reviewSources."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"Up to 300 characters the classifier reads for this keyword only, in addition to the company profile or the group's description. Say what the term means for you and what to ignore, for example \"Basil is our deploy tool, not the herb.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Terms the post must contain as well. requiredMode says whether one or all of them must appear. An empty list sets no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any needs one of the required terms in the post. all needs every one."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Posts that contain one of these terms are dropped. Put `*` at the start or end of a term as a wildcard, so deploy* matches deployment and *bot matches nightlybot."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Authors whose posts this keyword ignores. Each entry is a profile or post link, @handle, u/name, Bluesky DID or display name. Entries are normalized the same way as an alert's muted authors."},"caseSensitive":{"type":"boolean","description":"When true, the term only matches in the exact case you typed, so RAG never matches rag. Defaults to false."}},"description":"Fields you leave out stay as they are. An empty list clears a field."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"How many matched mentions the keyword may collect per calendar month (UTC). Every match counts, relevant or not, including a new keyword's look-back, since every match is billed."}},"required":["mentions"],"description":"Monthly limit on matched mentions. Omit or null means none."},"groupId":{"type":"string","minLength":1,"description":"The group to put it in (grp_...). Without it, the workspace's default group is used. Each group can hold a term only once."},"reviewSources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"Review page link, or send platform and id instead. Accepts App Store and Google Play app links (https://apps.apple.com/us/app/slack/id618783545, https://play.google.com/store/apps/details?id=com.Slack), Trustpilot pages (https://www.trustpilot.com/review/slack.com) and Google Maps places (full or maps.app.goo.gl link)."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"Where the reviews come from. appstore is the Apple App Store, googleplay is Google Play, trustpilot is a company's Trustpilot page and googlemaps is the Google reviews of a place."},"id":{"type":"string","minLength":1,"maxLength":200,"description":"The platform's own id. On the App Store it is the number after \"id\" in the link, on Google Play the package name, on Trustpilot the company's domain (slack.com) and on Google Maps a Place ID (ChIJ...)."},"countries":{"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"},"minItems":1,"maxItems":20,"description":"For App Store and Google Play. Up to 20 storefronts to read, as two-letter codes. Without it, the storefront in the link is used, or us. Each storefront adds one poll a day, and a review found in two storefronts is still one mention. Trustpilot and Google Maps have a single page and take no countries."},"language":{"type":"string","minLength":2,"maxLength":10,"description":"For Google Play. The review language to read, such as en, es, de or pt-BR, since Google Play returns one language at a time. Without it, the link's hl is used, or en."}},"description":"A review page, by link or by platform and id. Its reviews become this keyword's mentions."},"maxItems":10,"description":"Review pages for this keyword, at most 10 (App Store and Google Play apps, Trustpilot pages, Google Maps places). Every new review on them is a mention, whatever it says. Pages are read daily, per country on the app stores. A newly added page imports its last 30 days, up to 100 newest reviews per country, free and without instant alerts. Later reviews are billed like other mentions."}},"required":["term"]}}}},"responses":{"201":{"description":"The new keyword","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"The balance cannot cover one more keyword-day (insufficient_balance), or the workspace already has 500 keywords (keyword_limit_reached)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The group already has a keyword with this term after normalizing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listKeywords","summary":"List keywords","description":"Returns the workspace's keywords with their match counts and polling status. With no parameters you get all keywords, latest first. `q` searches the term and context. `kind`, `status` and `platform` filter the list, `sort` orders it, and `limit` and `offset` page through it. `total` is the number of matching keywords before paging.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive search in the term and context."},"required":false,"description":"Case-insensitive search in the term and context.","name":"q","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps keywords in these groups only (grp_...). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps keywords in these groups only (grp_...). Repeat the parameter or separate values with commas.","name":"groupId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keeps keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas.","name":"kind","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["active","muted","paused","noisy","capped"],"description":"active means it is running. muted means someone turned it off. paused means it stopped because the balance ran out. noisy means the noise brake stopped it, because most matches were irrelevant on a workspace still on its welcome credit. capped means it reached its monthly mention cap and waits for the next month."},"maxItems":4,"description":"Keeps keywords in these states only (active, muted, paused, capped). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps keywords in these states only (active, muted, paused, capped). Repeat the parameter or separate values with commas.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps keywords that run on one of these platforms. That means the term is searched there, which is every platform when platforms is null. For appstore and googleplay it means an app from that store is in reviewSources. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps keywords that run on one of these platforms. That means the term is searched there, which is every platform when platforms is null. For appstore and googleplay it means an app from that store is in reviewSources. Repeat the parameter or separate values with commas.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["newest","oldest","term","mentions","relevant","recent","lastMention"],"default":"newest","description":"newest puts the latest created first and oldest the earliest. term sorts A to Z. mentions puts the most matches first and relevant the most relevant matches. recent puts the most matches of the past 7 days first. lastMention puts the latest matched post first, with keywords that have none at the end."},"required":false,"description":"newest puts the latest created first and oldest the earliest. term sorts A to Z. mentions puts the most matches first and relevant the most relevant matches. recent puts the most matches of the past 7 days first. lastMention puts the latest matched post first, with keywords that have none at the end.","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"description":"How many to return, from 1 to 500. Leave it out to get all keywords after `offset`."},"required":false,"description":"How many to return, from 1 to 500. Leave it out to get all keywords after `offset`.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"default":0,"description":"How many keywords to skip."},"required":false,"description":"How many keywords to skip.","name":"offset","in":"query"}],"responses":{"200":{"description":"The keywords that match, with their total","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The keyword's id (kw_...)."},"term":{"type":"string"},"kind":{"type":"string","enum":["brand","competitor","topic"]},"muted":{"type":"boolean","description":"True when the keyword is neither polled nor matched. You, the wallet (pausedForBalance) or the noise brake (pausedForNoise) can mute it. Reaching the mention cap does not mute it (pausedForCap)."},"pausedForBalance":{"type":"boolean","description":"Muted because the balance ran out. A top-up resumes it. Unmuting it yourself also needs balance."},"pausedForNoise":{"type":"boolean","description":"Set when the noise brake muted the keyword. That happens on welcome credit once 20 or more matches are scored and under 30% are relevant. Unmuting it, or changing its required or excluded terms, platforms or context, resumes it when the balance covers another day. A top-up alone does not."},"pausedForCap":{"type":"boolean","description":"Hit its monthly mention cap. Matching resumes on the 1st (UTC) or when you raise the cap. The keyword isn't muted and is still charged daily."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"How many matched mentions the keyword may collect per calendar month (UTC). Every match counts, relevant or not, including a new keyword's look-back, since every match is billed."},"welcome":{"type":"boolean","description":"Rumoro sets this while the workspace uses its welcome credit. It limits each keyword to 200 mentions a month until the first top-up."},"own":{"type":"integer","nullable":true,"description":"The cap you chose. While welcome is true it is the cap restored at the first top-up (null for none), and sending `mentions: 200` changes nothing. Otherwise it equals mentions."}},"required":["mentions","welcome","own"],"description":"Monthly limit on matched mentions. Null means 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":"The platforms searched for the term. Null means all of them. An empty list means none, and the keyword only collects reviews."},"reviewSources":{"type":"array","items":{"$ref":"#/components/schemas/ReviewSource"},"description":"The review pages the keyword reads, such as App Store and Google Play apps, Trustpilot pages and Google Maps places. Empty when there are none."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"Up to 300 characters the classifier reads for this keyword only, in addition to the company profile or the group's description. Say what the term means for you and what to ignore, for example \"Basil is our deploy tool, not the herb.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Terms the post must contain as well. requiredMode says whether one or all of them must appear. An empty list sets no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any needs one of the required terms in the post. all needs every one."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Posts that contain one of these terms are dropped. Put `*` at the start or end of a term as a wildcard, so deploy* matches deployment and *bot matches nightlybot."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Authors whose posts this keyword ignores. Each entry is a profile or post link, @handle, u/name, Bluesky DID or display name. Entries are normalized the same way as an alert's muted authors."},"caseSensitive":{"type":"boolean","description":"When true, the term only matches in the exact case you typed, so RAG never matches rag. Defaults to false."}},"required":["requiredTerms","requiredMode","excludedTerms","excludedAuthors","caseSensitive"],"description":"Rules a post must pass before it is stored as a mention. A post they reject is never billed."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"All matches so far, relevant or not. Billing counts this number."},"relevant":{"type":"integer","minimum":0,"description":"Matches whose relevance score reached the threshold."},"last7d":{"type":"integer","minimum":0,"description":"Matches with a post date in the past 7 days."},"thisMonth":{"type":"integer","minimum":0,"description":"Matches recorded in the current calendar month (UTC). The cap is checked against this count."},"lastMentionAt":{"type":"string","nullable":true,"description":"Time of the latest matched post. Null before the first match."},"feedback":{"type":"object","properties":{"relevant":{"type":"integer","minimum":0,"description":"Marked relevant by your team."},"notRelevant":{"type":"integer","minimum":0,"description":"Mentions someone on your team marked not relevant. This is noise the classifier missed."}},"required":["relevant","notRelevant"],"description":"Your team's relevance marks, set with PATCH /v1/mentions/{id}."},"noise":{"type":"object","properties":{"scored":{"type":"integer","minimum":0,"description":"How many of the last 14 days' matches are scored."},"relevant":{"type":"integer","minimum":0,"description":"How many of them were scored relevant."},"noisy":{"type":"boolean","description":"True when the past 14 days have 20 or more scored matches and fewer than 30% are relevant. Narrow the keyword with required terms, excluded terms or context, because every match is billed, relevant or not."}},"required":["scored","relevant","noisy"],"description":"Relevance of the scored matches from the past 14 days. A keyword you narrow today drops the flag within two weeks."},"health":{"type":"string","enum":["healthy","noisy","quiet","capped","paused","new"],"description":"Health over the 14 days `noise` covers, by the same rule as GET /v1/keywords/{id}/health. The first that applies wins. paused (muted), capped (at its cap), noisy (20+ scored matches, under 30% relevant), new (under 7 days old, or changed in the last 7 days with under 20 scored since), quiet (7+ days, nothing relevant), otherwise healthy. After a change to matching rules, platforms or context, or an unmute, within the 14 days, only later matches count, while `noise` keeps all 14 days. The endpoint defaults to 30 days, so the two can differ, and it explains why and what to change."},"cost":{"type":"object","properties":{"keywordDays":{"type":"integer","minimum":0,"description":"Charged days this month. A day is charged when the keyword is unmuted at the daily run, so a new keyword shows 0 until tomorrow."},"keywordCents":{"type":"integer","description":"keywordDays at 500/30 cents each, which is $5 a month. Only the total is rounded."},"billableMentions":{"type":"integer","minimum":0,"description":"Matches billed this month. A match counts when it is scored, which is the time the ledger settles by. So this can lag behind thisMonth while matches are still being scored, and a match that failed to score never counts."},"mentionCents":{"type":"integer","description":"Those matches priced at $0.008 each, with the total rounded once."},"totalCents":{"type":"integer","description":"keywordCents plus mentionCents. The keyword's cost this month in US cents."}},"required":["keywordDays","keywordCents","billableMentions","mentionCents","totalCents"],"description":"List-price cost this calendar month (UTC), equal to this keyword's row in GET /v1/usage/breakdown?month=<this month>. The ledger settles daily and can differ only by cumulative rounding."}},"required":["mentions","relevant","last7d","thisMonth","lastMentionAt","feedback","noise","health","cost"],"description":"Counted from this workspace's matches only."},"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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"lastPolledAt":{"type":"string","nullable":true,"description":"When the term was last polled on this platform. Null before the first poll."},"emptyPolls":{"type":"integer","description":"How many polls in a row found nothing new. The higher it gets, the less often the term is polled."}},"required":["platform","lastPolledAt","emptyPolls"]},"description":"Polling status for each platform that is polled on a schedule. Live feeds such as Bluesky are not listed."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["id","term","kind","muted","pausedForBalance","pausedForNoise","pausedForCap","cap","group","platforms","reviewSources","context","matching","stats","polling","createdAt"]}},"total":{"type":"integer","minimum":0,"description":"Count of matching keywords, ignoring `limit` and `offset`."}},"required":["data","total"]}}}},"400":{"description":"A query parameter is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/keywords/{id}":{"get":{"operationId":"getKeyword","summary":"Get a keyword","description":"Returns one keyword with its matching rules, review pages, this month's cost and the polling status on each platform.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The keyword's id (kw_...).","example":"kw_abc123"},"required":true,"description":"The keyword's id (kw_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The requested keyword","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No keyword with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateKeyword","summary":"Update a keyword","description":"Mutes or unmutes the keyword, or changes its `kind`, platforms, classifier `context`, `matching` rules or monthly mention `cap`. Each rule field is optional and an empty list clears it. A null cap removes the cap, and a cap above this month's count resumes a capped keyword right away. New rules apply to mentions from the next poll on. Stored mentions stay as they are.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The keyword's id (kw_...).","example":"kw_abc123"},"required":true,"description":"The keyword's id (kw_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["brand","competitor","topic"],"description":"New kind (brand, competitor or topic)."},"muted":{"type":"boolean","description":"Muting stops polling and matching. Existing mentions are kept."},"platforms":{"type":"array","nullable":true,"items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram"]},"description":"Sets a new platform list. Null means all platforms. An empty list means none, which works when the keyword has reviewSources and only collects reviews."},"context":{"type":"string","nullable":true,"maxLength":300,"description":"Up to 300 characters the classifier reads for this keyword only, in addition to the company profile or the group's description. Say what the term means for you and what to ignore, for example \"Basil is our deploy tool, not the herb.\" Null clears it."},"matching":{"type":"object","properties":{"requiredTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Terms the post must contain as well. requiredMode says whether one or all of them must appear. An empty list sets no requirement."},"requiredMode":{"type":"string","enum":["any","all"],"description":"any needs one of the required terms in the post. all needs every one."},"excludedTerms":{"type":"array","items":{"type":"string","minLength":1,"maxLength":80},"maxItems":50,"description":"Posts that contain one of these terms are dropped. Put `*` at the start or end of a term as a wildcard, so deploy* matches deployment and *bot matches nightlybot."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":100,"description":"Authors whose posts this keyword ignores. Each entry is a profile or post link, @handle, u/name, Bluesky DID or display name. Entries are normalized the same way as an alert's muted authors."},"caseSensitive":{"type":"boolean","description":"When true, the term only matches in the exact case you typed, so RAG never matches rag. Defaults to false."}},"description":"Fields you leave out stay as they are. An empty list clears a field."},"cap":{"type":"object","nullable":true,"properties":{"mentions":{"type":"integer","minimum":1,"maximum":1000000,"description":"How many matched mentions the keyword may collect per calendar month (UTC). Every match counts, relevant or not, including a new keyword's look-back, since every match is billed."}},"required":["mentions"],"description":"Sets a new monthly mention cap, or null for no cap. A cap above this month's count resumes a capped keyword right away. A cap at or below the count pauses it."},"groupId":{"type":"string","minLength":1,"description":"Target group (grp_...). 409 if it already has this term."},"reviewSources":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":500,"description":"Review page link, or send platform and id instead. Accepts App Store and Google Play app links (https://apps.apple.com/us/app/slack/id618783545, https://play.google.com/store/apps/details?id=com.Slack), Trustpilot pages (https://www.trustpilot.com/review/slack.com) and Google Maps places (full or maps.app.goo.gl link)."},"platform":{"type":"string","enum":["appstore","googleplay","trustpilot","googlemaps"],"description":"Where the reviews come from. appstore is the Apple App Store, googleplay is Google Play, trustpilot is a company's Trustpilot page and googlemaps is the Google reviews of a place."},"id":{"type":"string","minLength":1,"maxLength":200,"description":"The platform's own id. On the App Store it is the number after \"id\" in the link, on Google Play the package name, on Trustpilot the company's domain (slack.com) and on Google Maps a Place ID (ChIJ...)."},"countries":{"type":"array","items":{"type":"string","pattern":"^[A-Za-z]{2}$"},"minItems":1,"maxItems":20,"description":"For App Store and Google Play. Up to 20 storefronts to read, as two-letter codes. Without it, the storefront in the link is used, or us. Each storefront adds one poll a day, and a review found in two storefronts is still one mention. Trustpilot and Google Maps have a single page and take no countries."},"language":{"type":"string","minLength":2,"maxLength":10,"description":"For Google Play. The review language to read, such as en, es, de or pt-BR, since Google Play returns one language at a time. Without it, the link's hl is used, or en."}},"description":"A review page, by link or by platform and id. Its reviews become this keyword's mentions."},"maxItems":10,"description":"Sets a new list of review pages for this keyword. An empty list disconnects them all, and their reviews are kept. A page or country you add gets the free 30-day look-back. Pages already listed are unchanged."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The keyword after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"The balance can't cover another keyword-day (insufficient_balance), or the workspace already runs 500 keywords (keyword_limit_reached)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No keyword with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteKeyword","summary":"Delete a keyword","description":"Deletes the keyword with its matches. A post that another keyword also matched is kept.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The keyword's id (kw_...).","example":"kw_abc123"},"required":true,"description":"The keyword's id (kw_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No keyword with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/keywords/{id}/health":{"get":{"operationId":"getKeywordHealth","summary":"Check a keyword's health","description":"Checks whether the keyword earns its cost over `range` (default 30d). Returns a status (healthy, noisy, quiet, capped, paused or new) with plain-word reasons, numbers by platform and week, cost, the words and authors behind the noise, and suggestions. Send a suggestion's `patch` unchanged to PATCH /v1/keywords/{id}. Its effect comes from replaying the matcher's rules on the window's posts. `ai=true` adds a model-written context (cached a day, up to 20 model calls an hour per workspace). Read only and never billed. Reports are cached 5 minutes and rebuilt after a keyword change. Up to 30 reads a minute per workspace.","tags":["Keywords"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The keyword's id (kw_...).","example":"kw_abc123"},"required":true,"description":"The keyword's id (kw_...).","name":"id","in":"path"},{"schema":{"type":"string","enum":["7d","30d","90d"],"description":"How many UTC days back from today to read, by match time. One of 7d, 30d or 90d, 30d by default."},"required":false,"description":"How many UTC days back from today to read, by match time. One of 7d, 30d or 90d, 30d by default.","name":"range","in":"query"},{"schema":{"type":"boolean","description":"true also asks a language model to rewrite the context. The answer is cached for a day per keyword and window, with at most 20 model calls an hour per workspace. With the default false, all suggestions come from the rules only."},"required":false,"description":"true also asks a language model to rewrite the context. The answer is cached for a day per keyword and window, with at most 20 model calls an hour per workspace. With the default false, all suggestions come from the rules only.","name":"ai","in":"query"}],"responses":{"200":{"description":"The health report for the keyword","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeywordHealth"}}}},"400":{"description":"A query parameter is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No keyword with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Health was read over 30 times this minute (rate_limited)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/filters":{"get":{"operationId":"getFilters","summary":"Get the workspace filters","description":"Returns the workspace noise rules, applied to every keyword before a mention is stored. They exclude terms, authors and GitHub repositories, and allow or block subreddits. Rejected posts are never classified, sent or billed. Keywords add their own `matching` rules on top.","tags":["Filters"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The workspace's filters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFilters"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateFilters","summary":"Update the workspace filters","description":"Sets new values for any of the lists. A list you leave out stays as it is, and an empty list clears it. Rumoro normalizes each entry. Terms become lowercase, authors profile links or plain names, repositories owner/name, and subreddits lose the r/. New mentions follow the change within a minute. Stored mentions stay as they are.","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":"Sets a new list. An empty list clears it."},"excludedAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":500},"maxItems":200,"description":"Sets a new list. An empty list clears it."},"excludedRepos":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Sets a new list. An empty list clears it."},"subreddits":{"type":"object","properties":{"only":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Sets a new list of allowed subreddits. An empty list clears it."},"excluded":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":200,"description":"Sets a new list of blocked subreddits. An empty list clears it."}},"description":"Applies to Reddit only. A list you leave out stays as it is."}},"description":"Fields you leave out stay as they are. An empty list clears a field."}}}},"responses":{"200":{"description":"The filters after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFilters"}}}},"400":{"description":"Could not parse an entry as a term, author, repository or subreddit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions/{id}":{"patch":{"operationId":"updateMention","summary":"Update a mention","description":"The only way to change a mention. Set status to ignored or done when it is handled, or back to open. You can also assign it to a member, snooze it out of the feed, add a note for your team, or correct the classifier. `relevant` true or false is your judgment, which sets relevance to 100 or 0 for every list, filter, digest and report. `sentiment` replaces the label. Null removes your correction and brings back the classifier's value. Fields you leave out stay as they are. Delivery and billing are never affected.","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 marks it handled, and open reopens it."},"assigneeId":{"type":"string","nullable":true,"minLength":1,"description":"The user id of a workspace member, or null to remove the assignment."},"snoozedUntil":{"type":"string","description":"Hides the mention from the feed until this time, given as ISO 8601 or epoch ms. Send null to bring it back now.","format":"date-time"},"note":{"type":"string","nullable":true,"maxLength":2000,"description":"A note for your team. Null or an empty string removes it."},"relevant":{"type":"boolean","nullable":true,"description":"Set it to override the classifier, or null to restore the classifier's score. true means relevance 100, and a filtered mention joins the relevant feed. false means 0, and it leaves. Billing is unaffected. While the mention is still being classified this returns 409 classification_pending."},"sentiment":{"type":"string","nullable":true,"enum":["positive","neutral","negative"],"description":"The sentiment you choose. Null removes it and brings back the classifier's."}},"description":"All fields are optional. Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The updated mention","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mention"}}}},"400":{"description":"assigneeId isn't a workspace member","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Mention not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The classifier has not scored this mention yet (classification_pending)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"getMention","summary":"Get a mention","description":"Fetches one mention by id, with the same fields the list returns. An id from another workspace gets 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":"The API key is missing or not valid","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":"Lists your keywords' mentions with filters and paging. Each mention pairs one post with one keyword. Latest match first by default, or sort=priority to rank the last 30 days by attention score. For the next page, send nextCursor and keep the filters and sort. alertId applies an alert's filter, giving what that alert would send. anyOf adds OR groups as URL-encoded JSON, at least one of which must match along with every other filter.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Only this keyword's matches."},"required":false,"description":"Only this keyword's matches.","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 this platform's posts."},"required":false,"description":"Only this platform's posts.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only. Leave it out for all statuses."},"required":false,"description":"Keeps mentions with this status only. Leave it out for all statuses.","name":"status","in":"query"},{"schema":{"type":"boolean","description":"true keeps mentions the classifier scored relevant. false keeps the others, including unscored ones."},"required":false,"description":"true keeps mentions the classifier scored relevant. false keeps the others, including unscored ones.","name":"relevant","in":"query"},{"schema":{"type":"string","enum":["positive","neutral","negative"],"description":"Keeps mentions with this sentiment only."},"required":false,"description":"Keeps mentions with this sentiment only.","name":"sentiment","in":"query"},{"schema":{"type":"string","description":"Returns only mentions with this tag. One of bug_report, buy_intent, churn_intent, comparison, complaint, event, feedback, hiring, industry_insight, launch, praise, pricing, promotional, question and testimonial."},"required":false,"description":"Returns only mentions with this tag. One of bug_report, buy_intent, churn_intent, comparison, complaint, event, feedback, hiring, industry_insight, launch, praise, pricing, promotional, question and testimonial.","name":"intent","in":"query"},{"schema":{"type":"boolean","description":"true keeps mentions that look machine-made, such as bot accounts, scheduled or template posts and AI-written text. false keeps the others, including mentions scored before this flag existed. Leave it out for all."},"required":false,"description":"true keeps mentions that look machine-made, such as bot accounts, scheduled or template posts and AI-written text. false keeps the others, including mentions scored before this flag existed. Leave it out for all.","name":"automated","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Keeps mentions by this person (an id from /v1/people), including merged accounts. Turns on includeMuted."},"required":false,"description":"Keeps mentions by this person (an id from /v1/people), including merged accounts. Turns on includeMuted.","name":"personId","in":"query"},{"schema":{"type":"boolean","description":"true also returns mentions by muted people, which are hidden by default."},"required":false,"description":"true also returns mentions by muted people, which are hidden by default.","name":"includeMuted","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Member user id. Returns only mentions assigned to them."},"required":false,"description":"Member user id. Returns only mentions assigned to them.","name":"assigneeId","in":"query"},{"schema":{"type":"boolean","description":"true shows only snoozed mentions, which are otherwise hidden until they wake."},"required":false,"description":"true shows only snoozed mentions, which are otherwise hidden until they wake.","name":"snoozed","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links. Repeat the parameter or send one value with commas."},"required":false,"description":"Leaves out these authors, given as display names, handles or profile links. Repeat the parameter or send one value with commas.","name":"excludeAuthors","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Keeps mentions with this relevance score or higher. Unscored mentions are left out."},"required":false,"description":"Keeps mentions with this relevance score or higher. Unscored mentions are left out.","name":"minRelevance","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Minimum classifier confidence, 0 to 1. Mentions with no confidence are dropped."},"required":false,"description":"Minimum classifier confidence, 0 to 1. Mentions with no confidence are dropped.","name":"minConfidence","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"required":false,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts by authors with this many followers or fewer. Unknown counts are left out."},"required":false,"description":"Keeps posts by authors with this many followers or fewer. Unknown counts are left out.","name":"maxFollowers","in":"query"},{"schema":{"type":"boolean","description":"true keeps replies and comments, meaning posts that answer another post. false keeps posts that are not replies. Leave it out for both."},"required":false,"description":"true keeps replies and comments, meaning posts that answer another post. false keeps posts that are not replies. Leave it out for both.","name":"isReply","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds an alert rule's filter (an id from GET /v1/alerts) to the other filters. You get the mentions the rule would send, useful for a preview or an export in feed form. An unknown id returns 404."},"required":false,"description":"Adds an alert rule's filter (an id from GET /v1/alerts) to the other filters. You get the mentions the rule would send, useful for a preview or an export in feed form. An unknown id returns 404.","name":"alertId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds a saved view's filter (an id from GET /v1/views) to the other filters, with every condition joined by AND. You get exactly what the view shows. An unknown id returns 404."},"required":false,"description":"Adds a saved view's filter (an id from GET /v1/views) to the other filters, with every condition joined by AND. You get exactly what the view shows. An unknown id returns 404.","name":"viewId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keeps matches of keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps matches of keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags, matched exactly and by case. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps authors your workspace gave one of these tags, matched exactly and by case. Repeat the parameter or separate values with commas.","name":"tags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Repeat the parameter or separate values with commas.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"required":false,"description":"Keeps posts from these platforms only.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"required":false,"description":"Platforms to exclude.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps matches of these keywords only."},"required":false,"description":"Keeps matches of these keywords only.","name":"keywordIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps matches of keywords in these groups only (grp_...). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps matches of keywords in these groups only (grp_...). Repeat the parameter or separate values with commas.","name":"groupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Hides matches from keywords that belong to these groups."},"required":false,"description":"Hides matches from keywords that belong to these groups.","name":"notGroupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keyword ids to exclude."},"required":false,"description":"Keyword ids to exclude.","name":"notKeywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"required":false,"description":"Keeps mentions with these sentiments only.","name":"sentiments","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Leaves out these sentiments. Mentions not scored yet are kept."},"required":false,"description":"Leaves out these sentiments. Mentions not scored yet are kept.","name":"notSentiments","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"required":false,"description":"Keeps mentions tagged with one of these intents or topics.","name":"intents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Intent or topic tags to exclude."},"required":false,"description":"Intent or topic tags to exclude.","name":"notIntents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts or their subdomains."},"required":false,"description":"Leaves out posts that link to these hosts or their subdomains.","name":"notLinkHosts","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out authors your workspace gave one of these tags."},"required":false,"description":"Leaves out authors your workspace gave one of these tags.","name":"notTags","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"required":false,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out.","name":"languages","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"required":false,"description":"Leaves out posts in these languages. Posts with an unknown language are kept.","name":"notLanguages","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings, from 1 to 5. Use ratings=1,2 for the unhappy ones. Posts that are not reviews are left out."},"required":false,"description":"Keeps reviews with one of these star ratings, from 1 to 5. Use ratings=1,2 for the unhappy ones. Posts that are not reviews are left out.","name":"ratings","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to hide, such as notRatings=5. Other posts are unaffected."},"required":false,"description":"Star ratings (1 to 5) to hide, such as notRatings=5. Other posts are unaffected.","name":"notRatings","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"required":false,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out.","name":"minLikes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"required":false,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out.","name":"minReposts","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"required":false,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out.","name":"minReplies","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"required":false,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out.","name":"minQuotes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"required":false,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out.","name":"minViews","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"required":false,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out.","name":"minBookmarks","in":"query"},{"schema":{"type":"string","description":"Groups of conditions joined by OR, as URL-encoded JSON. For example [{\"platforms\":[\"github\"],\"intents\":[\"bug_report\"]},{\"sentiments\":[\"negative\"]}] means \"bug reports on GitHub, or anything negative\". A group uses the fields of a view filter, where a list matches any value, a not list matches none, and all conditions are joined by AND. A mention passes when one group matches, and the other filters here still apply. Send 1 to 10 groups, none empty and none nested."},"required":false,"description":"Groups of conditions joined by OR, as URL-encoded JSON. For example [{\"platforms\":[\"github\"],\"intents\":[\"bug_report\"]},{\"sentiments\":[\"negative\"]}] means \"bug reports on GitHub, or anything negative\". A group uses the fields of a view filter, where a list matches any value, a not list matches none, and all conditions are joined by AND. A mention passes when one group matches, and the other filters here still apply. Send 1 to 10 groups, none empty and none nested.","name":"anyOf","in":"query"},{"schema":{"type":"string","description":"Searches post text and author names."},"required":false,"description":"Searches post text and author names.","name":"q","in":"query"},{"schema":{"type":"string","description":"Keeps posts published at this time or later, as ISO 8601 or epoch ms.","format":"date-time"},"required":false,"description":"Keeps posts published at this time or later, as ISO 8601 or epoch ms.","name":"since","in":"query"},{"schema":{"type":"string","description":"Keeps posts published at this time or earlier, as ISO 8601 or epoch ms.","format":"date-time"},"required":false,"description":"Keeps posts published at this time or earlier, as ISO 8601 or epoch ms.","name":"until","in":"query"},{"schema":{"type":"string","enum":["newest","priority"],"default":"newest","description":"newest orders by match time, latest first. priority orders by attention score, highest first, and only covers the past 30 days of matches. Older ones are still available with newest. A cursor only works with the sort it came from."},"required":false,"description":"newest orders by match time, latest first. priority orders by attention score, highest first, and only covers the past 30 days of matches. Older ones are still available with newest. A cursor only works with the sort it came from.","name":"sort","in":"query"},{"schema":{"type":"string","description":"Pass the previous page's nextCursor, with the same filters and sort."},"required":false,"description":"Pass the previous page's nextCursor, with the same filters and sort.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25,"description":"How many to return, from 1 to 100."},"required":false,"description":"How many to return, from 1 to 100.","name":"limit","in":"query"}],"responses":{"200":{"description":"A page of mentions, sorted as requested","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Mention"}},"nextCursor":{"type":"string","nullable":true,"description":"Cursor for the next page, or null when there are no more pages."}},"required":["data","nextCursor"]}}}},"400":{"description":"A query parameter or the cursor is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions/export.csv":{"get":{"operationId":"exportMentionsCsv","summary":"Export mentions as CSV","description":"Returns as CSV the mentions GET /v1/mentions lists for the same filters. Rows are ordered by match time, latest first, which is the order they reached your feed and can differ from the post date. The columns are id, published_at, platform, keyword, author, author_url, author_followers, relevance, sentiment, intents (separated by |), language, confidence, status, relevant, delivered, url, links (separated by |), text (the first 1,000 characters), group, group_external_id, rating and app_id (reviews only), and title and image_url (on platforms that have them). The file holds at most 10,000 rows, and the X-Mentions-Truncated header tells you when rows were cut. Each workspace can export 6 times a minute, and a 429 includes Retry-After.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Only this keyword's matches."},"required":false,"description":"Only this keyword's matches.","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 this platform's posts."},"required":false,"description":"Only this platform's posts.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only. Leave it out for all statuses."},"required":false,"description":"Keeps mentions with this status only. Leave it out for all statuses.","name":"status","in":"query"},{"schema":{"type":"boolean","description":"true keeps mentions the classifier scored relevant. false keeps the others, including unscored ones."},"required":false,"description":"true keeps mentions the classifier scored relevant. false keeps the others, including unscored ones.","name":"relevant","in":"query"},{"schema":{"type":"string","enum":["positive","neutral","negative"],"description":"Keeps mentions with this sentiment only."},"required":false,"description":"Keeps mentions with this sentiment only.","name":"sentiment","in":"query"},{"schema":{"type":"string","description":"Returns only mentions with this tag. One of bug_report, buy_intent, churn_intent, comparison, complaint, event, feedback, hiring, industry_insight, launch, praise, pricing, promotional, question and testimonial."},"required":false,"description":"Returns only mentions with this tag. One of bug_report, buy_intent, churn_intent, comparison, complaint, event, feedback, hiring, industry_insight, launch, praise, pricing, promotional, question and testimonial.","name":"intent","in":"query"},{"schema":{"type":"boolean","description":"true keeps mentions that look machine-made, such as bot accounts, scheduled or template posts and AI-written text. false keeps the others, including mentions scored before this flag existed. Leave it out for all."},"required":false,"description":"true keeps mentions that look machine-made, such as bot accounts, scheduled or template posts and AI-written text. false keeps the others, including mentions scored before this flag existed. Leave it out for all.","name":"automated","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Keeps mentions by this person (an id from /v1/people), including merged accounts. Turns on includeMuted."},"required":false,"description":"Keeps mentions by this person (an id from /v1/people), including merged accounts. Turns on includeMuted.","name":"personId","in":"query"},{"schema":{"type":"boolean","description":"true also returns mentions by muted people, which are hidden by default."},"required":false,"description":"true also returns mentions by muted people, which are hidden by default.","name":"includeMuted","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Member user id. Returns only mentions assigned to them."},"required":false,"description":"Member user id. Returns only mentions assigned to them.","name":"assigneeId","in":"query"},{"schema":{"type":"boolean","description":"true shows only snoozed mentions, which are otherwise hidden until they wake."},"required":false,"description":"true shows only snoozed mentions, which are otherwise hidden until they wake.","name":"snoozed","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links. Repeat the parameter or send one value with commas."},"required":false,"description":"Leaves out these authors, given as display names, handles or profile links. Repeat the parameter or send one value with commas.","name":"excludeAuthors","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Keeps mentions with this relevance score or higher. Unscored mentions are left out."},"required":false,"description":"Keeps mentions with this relevance score or higher. Unscored mentions are left out.","name":"minRelevance","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Minimum classifier confidence, 0 to 1. Mentions with no confidence are dropped."},"required":false,"description":"Minimum classifier confidence, 0 to 1. Mentions with no confidence are dropped.","name":"minConfidence","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"required":false,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts by authors with this many followers or fewer. Unknown counts are left out."},"required":false,"description":"Keeps posts by authors with this many followers or fewer. Unknown counts are left out.","name":"maxFollowers","in":"query"},{"schema":{"type":"boolean","description":"true keeps replies and comments, meaning posts that answer another post. false keeps posts that are not replies. Leave it out for both."},"required":false,"description":"true keeps replies and comments, meaning posts that answer another post. false keeps posts that are not replies. Leave it out for both.","name":"isReply","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds an alert rule's filter (an id from GET /v1/alerts) to the other filters. You get the mentions the rule would send, useful for a preview or an export in feed form. An unknown id returns 404."},"required":false,"description":"Adds an alert rule's filter (an id from GET /v1/alerts) to the other filters. You get the mentions the rule would send, useful for a preview or an export in feed form. An unknown id returns 404.","name":"alertId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds a saved view's filter (an id from GET /v1/views) to the other filters, with every condition joined by AND. You get exactly what the view shows. An unknown id returns 404."},"required":false,"description":"Adds a saved view's filter (an id from GET /v1/views) to the other filters, with every condition joined by AND. You get exactly what the view shows. An unknown id returns 404.","name":"viewId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keeps matches of keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps matches of keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags, matched exactly and by case. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps authors your workspace gave one of these tags, matched exactly and by case. Repeat the parameter or separate values with commas.","name":"tags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Repeat the parameter or separate values with commas.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"required":false,"description":"Keeps posts from these platforms only.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"required":false,"description":"Platforms to exclude.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps matches of these keywords only."},"required":false,"description":"Keeps matches of these keywords only.","name":"keywordIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps matches of keywords in these groups only (grp_...). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps matches of keywords in these groups only (grp_...). Repeat the parameter or separate values with commas.","name":"groupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Hides matches from keywords that belong to these groups."},"required":false,"description":"Hides matches from keywords that belong to these groups.","name":"notGroupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keyword ids to exclude."},"required":false,"description":"Keyword ids to exclude.","name":"notKeywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"required":false,"description":"Keeps mentions with these sentiments only.","name":"sentiments","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Leaves out these sentiments. Mentions not scored yet are kept."},"required":false,"description":"Leaves out these sentiments. Mentions not scored yet are kept.","name":"notSentiments","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"required":false,"description":"Keeps mentions tagged with one of these intents or topics.","name":"intents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Intent or topic tags to exclude."},"required":false,"description":"Intent or topic tags to exclude.","name":"notIntents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts or their subdomains."},"required":false,"description":"Leaves out posts that link to these hosts or their subdomains.","name":"notLinkHosts","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out authors your workspace gave one of these tags."},"required":false,"description":"Leaves out authors your workspace gave one of these tags.","name":"notTags","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"required":false,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out.","name":"languages","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"required":false,"description":"Leaves out posts in these languages. Posts with an unknown language are kept.","name":"notLanguages","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings, from 1 to 5. Use ratings=1,2 for the unhappy ones. Posts that are not reviews are left out."},"required":false,"description":"Keeps reviews with one of these star ratings, from 1 to 5. Use ratings=1,2 for the unhappy ones. Posts that are not reviews are left out.","name":"ratings","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to hide, such as notRatings=5. Other posts are unaffected."},"required":false,"description":"Star ratings (1 to 5) to hide, such as notRatings=5. Other posts are unaffected.","name":"notRatings","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"required":false,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out.","name":"minLikes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"required":false,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out.","name":"minReposts","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"required":false,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out.","name":"minReplies","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"required":false,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out.","name":"minQuotes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"required":false,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out.","name":"minViews","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"required":false,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out.","name":"minBookmarks","in":"query"},{"schema":{"type":"string","description":"Groups of conditions joined by OR, as URL-encoded JSON. For example [{\"platforms\":[\"github\"],\"intents\":[\"bug_report\"]},{\"sentiments\":[\"negative\"]}] means \"bug reports on GitHub, or anything negative\". A group uses the fields of a view filter, where a list matches any value, a not list matches none, and all conditions are joined by AND. A mention passes when one group matches, and the other filters here still apply. Send 1 to 10 groups, none empty and none nested."},"required":false,"description":"Groups of conditions joined by OR, as URL-encoded JSON. For example [{\"platforms\":[\"github\"],\"intents\":[\"bug_report\"]},{\"sentiments\":[\"negative\"]}] means \"bug reports on GitHub, or anything negative\". A group uses the fields of a view filter, where a list matches any value, a not list matches none, and all conditions are joined by AND. A mention passes when one group matches, and the other filters here still apply. Send 1 to 10 groups, none empty and none nested.","name":"anyOf","in":"query"},{"schema":{"type":"string","description":"Searches post text and author names."},"required":false,"description":"Searches post text and author names.","name":"q","in":"query"},{"schema":{"type":"string","description":"Keeps posts published at this time or later, as ISO 8601 or epoch ms.","format":"date-time"},"required":false,"description":"Keeps posts published at this time or later, as ISO 8601 or epoch ms.","name":"since","in":"query"},{"schema":{"type":"string","description":"Keeps posts published at this time or earlier, as ISO 8601 or epoch ms.","format":"date-time"},"required":false,"description":"Keeps posts published at this time or earlier, as ISO 8601 or epoch ms.","name":"until","in":"query"}],"responses":{"200":{"description":"A UTF-8 CSV file","content":{"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"A query parameter is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over 6 exports in this minute. Wait the Retry-After seconds and try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/mentions/export.json":{"get":{"operationId":"exportMentionsJson","summary":"Export mentions as JSON","description":"Returns in one response the mentions GET /v1/mentions lists for the same filters, latest match first, which is the order they reached your feed. Each row is the full Mention object from the list, text included. At most 10,000 mentions are returned, and `truncated` tells you when some were cut. It shares the CSV export's limit of 6 exports a minute per workspace, in either format, and a 429 includes Retry-After.","tags":["Mentions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"Only this keyword's matches."},"required":false,"description":"Only this keyword's matches.","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 this platform's posts."},"required":false,"description":"Only this platform's posts.","name":"platform","in":"query"},{"schema":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only. Leave it out for all statuses."},"required":false,"description":"Keeps mentions with this status only. Leave it out for all statuses.","name":"status","in":"query"},{"schema":{"type":"boolean","description":"true keeps mentions the classifier scored relevant. false keeps the others, including unscored ones."},"required":false,"description":"true keeps mentions the classifier scored relevant. false keeps the others, including unscored ones.","name":"relevant","in":"query"},{"schema":{"type":"string","enum":["positive","neutral","negative"],"description":"Keeps mentions with this sentiment only."},"required":false,"description":"Keeps mentions with this sentiment only.","name":"sentiment","in":"query"},{"schema":{"type":"string","description":"Returns only mentions with this tag. One of bug_report, buy_intent, churn_intent, comparison, complaint, event, feedback, hiring, industry_insight, launch, praise, pricing, promotional, question and testimonial."},"required":false,"description":"Returns only mentions with this tag. One of bug_report, buy_intent, churn_intent, comparison, complaint, event, feedback, hiring, industry_insight, launch, praise, pricing, promotional, question and testimonial.","name":"intent","in":"query"},{"schema":{"type":"boolean","description":"true keeps mentions that look machine-made, such as bot accounts, scheduled or template posts and AI-written text. false keeps the others, including mentions scored before this flag existed. Leave it out for all."},"required":false,"description":"true keeps mentions that look machine-made, such as bot accounts, scheduled or template posts and AI-written text. false keeps the others, including mentions scored before this flag existed. Leave it out for all.","name":"automated","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Keeps mentions by this person (an id from /v1/people), including merged accounts. Turns on includeMuted."},"required":false,"description":"Keeps mentions by this person (an id from /v1/people), including merged accounts. Turns on includeMuted.","name":"personId","in":"query"},{"schema":{"type":"boolean","description":"true also returns mentions by muted people, which are hidden by default."},"required":false,"description":"true also returns mentions by muted people, which are hidden by default.","name":"includeMuted","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Member user id. Returns only mentions assigned to them."},"required":false,"description":"Member user id. Returns only mentions assigned to them.","name":"assigneeId","in":"query"},{"schema":{"type":"boolean","description":"true shows only snoozed mentions, which are otherwise hidden until they wake."},"required":false,"description":"true shows only snoozed mentions, which are otherwise hidden until they wake.","name":"snoozed","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links. Repeat the parameter or send one value with commas."},"required":false,"description":"Leaves out these authors, given as display names, handles or profile links. Repeat the parameter or send one value with commas.","name":"excludeAuthors","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"maximum":100,"description":"Keeps mentions with this relevance score or higher. Unscored mentions are left out."},"required":false,"description":"Keeps mentions with this relevance score or higher. Unscored mentions are left out.","name":"minRelevance","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Minimum classifier confidence, 0 to 1. Mentions with no confidence are dropped."},"required":false,"description":"Minimum classifier confidence, 0 to 1. Mentions with no confidence are dropped.","name":"minConfidence","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"required":false,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts by authors with this many followers or fewer. Unknown counts are left out."},"required":false,"description":"Keeps posts by authors with this many followers or fewer. Unknown counts are left out.","name":"maxFollowers","in":"query"},{"schema":{"type":"boolean","description":"true keeps replies and comments, meaning posts that answer another post. false keeps posts that are not replies. Leave it out for both."},"required":false,"description":"true keeps replies and comments, meaning posts that answer another post. false keeps posts that are not replies. Leave it out for both.","name":"isReply","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds an alert rule's filter (an id from GET /v1/alerts) to the other filters. You get the mentions the rule would send, useful for a preview or an export in feed form. An unknown id returns 404."},"required":false,"description":"Adds an alert rule's filter (an id from GET /v1/alerts) to the other filters. You get the mentions the rule would send, useful for a preview or an export in feed form. An unknown id returns 404.","name":"alertId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds a saved view's filter (an id from GET /v1/views) to the other filters, with every condition joined by AND. You get exactly what the view shows. An unknown id returns 404."},"required":false,"description":"Adds a saved view's filter (an id from GET /v1/views) to the other filters, with every condition joined by AND. You get exactly what the view shows. An unknown id returns 404.","name":"viewId","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keeps matches of keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps matches of keywords of these kinds only (brand, competitor, topic). Repeat the parameter or separate values with commas.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags, matched exactly and by case. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps authors your workspace gave one of these tags, matched exactly and by case. Repeat the parameter or separate values with commas.","name":"tags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Repeat the parameter or separate values with commas.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"required":false,"description":"Keeps posts from these platforms only.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"required":false,"description":"Platforms to exclude.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps matches of these keywords only."},"required":false,"description":"Keeps matches of these keywords only.","name":"keywordIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps matches of keywords in these groups only (grp_...). Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps matches of keywords in these groups only (grp_...). Repeat the parameter or separate values with commas.","name":"groupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Hides matches from keywords that belong to these groups."},"required":false,"description":"Hides matches from keywords that belong to these groups.","name":"notGroupIds","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keyword ids to exclude."},"required":false,"description":"Keyword ids to exclude.","name":"notKeywordIds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"required":false,"description":"Keeps mentions with these sentiments only.","name":"sentiments","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Leaves out these sentiments. Mentions not scored yet are kept."},"required":false,"description":"Leaves out these sentiments. Mentions not scored yet are kept.","name":"notSentiments","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"required":false,"description":"Keeps mentions tagged with one of these intents or topics.","name":"intents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Intent or topic tags to exclude."},"required":false,"description":"Intent or topic tags to exclude.","name":"notIntents","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts or their subdomains."},"required":false,"description":"Leaves out posts that link to these hosts or their subdomains.","name":"notLinkHosts","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out authors your workspace gave one of these tags."},"required":false,"description":"Leaves out authors your workspace gave one of these tags.","name":"notTags","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"required":false,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out.","name":"languages","in":"query"},{"schema":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"required":false,"description":"Leaves out posts in these languages. Posts with an unknown language are kept.","name":"notLanguages","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings, from 1 to 5. Use ratings=1,2 for the unhappy ones. Posts that are not reviews are left out."},"required":false,"description":"Keeps reviews with one of these star ratings, from 1 to 5. Use ratings=1,2 for the unhappy ones. Posts that are not reviews are left out.","name":"ratings","in":"query"},{"schema":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to hide, such as notRatings=5. Other posts are unaffected."},"required":false,"description":"Star ratings (1 to 5) to hide, such as notRatings=5. Other posts are unaffected.","name":"notRatings","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"required":false,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out.","name":"minLikes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"required":false,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out.","name":"minReposts","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"required":false,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out.","name":"minReplies","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"required":false,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out.","name":"minQuotes","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"required":false,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out.","name":"minViews","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"required":false,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out.","name":"minBookmarks","in":"query"},{"schema":{"type":"string","description":"Groups of conditions joined by OR, as URL-encoded JSON. For example [{\"platforms\":[\"github\"],\"intents\":[\"bug_report\"]},{\"sentiments\":[\"negative\"]}] means \"bug reports on GitHub, or anything negative\". A group uses the fields of a view filter, where a list matches any value, a not list matches none, and all conditions are joined by AND. A mention passes when one group matches, and the other filters here still apply. Send 1 to 10 groups, none empty and none nested."},"required":false,"description":"Groups of conditions joined by OR, as URL-encoded JSON. For example [{\"platforms\":[\"github\"],\"intents\":[\"bug_report\"]},{\"sentiments\":[\"negative\"]}] means \"bug reports on GitHub, or anything negative\". A group uses the fields of a view filter, where a list matches any value, a not list matches none, and all conditions are joined by AND. A mention passes when one group matches, and the other filters here still apply. Send 1 to 10 groups, none empty and none nested.","name":"anyOf","in":"query"},{"schema":{"type":"string","description":"Searches post text and author names."},"required":false,"description":"Searches post text and author names.","name":"q","in":"query"},{"schema":{"type":"string","description":"Keeps posts published at this time or later, as ISO 8601 or epoch ms.","format":"date-time"},"required":false,"description":"Keeps posts published at this time or later, as ISO 8601 or epoch ms.","name":"since","in":"query"},{"schema":{"type":"string","description":"Keeps posts published at this time or earlier, as ISO 8601 or epoch ms.","format":"date-time"},"required":false,"description":"Keeps posts published at this time or earlier, as ISO 8601 or epoch ms.","name":"until","in":"query"}],"responses":{"200":{"description":"All mentions the filter selects, 10,000 at most","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Mention"},"description":"Up to 10,000 mentions, newest match first."},"truncated":{"type":"boolean","description":"More mentions matched than the export can hold. Use since and until to split it."}},"required":["data","truncated"]}}}},"400":{"description":"A query parameter is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over 6 exports in this minute. Wait the Retry-After seconds and try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/export.csv":{"get":{"operationId":"exportPeopleCsv","summary":"Export people as CSV","description":"Returns as CSV the people GET /v1/people lists for the same filters, segmentId included. Each row is one person with handle, followers, email, website, company, location and tags, then outreach stage, owner and last contacted. The file holds at most 5,000 people. Each workspace can export 6 times a minute, and a 429 includes 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":"Only people with a profile on this platform."},"required":false,"description":"Only people with a profile on this platform.","name":"platform","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Searches the display name, handle and profile link, ignoring case."},"required":false,"description":"Searches the display name, handle and profile link, ignoring case.","name":"q","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":300,"description":"Looks up a person by one of their accounts, given as a handle (@sam, u/sam, sam) or a profile or post link (https://x.com/sam). The match is exact but ignores case, and covers merged accounts. Add platform to pick one platform. A link already tells which platform it is."},"required":false,"description":"Looks up a person by one of their accounts, given as a handle (@sam, u/sam, sam) or a profile or post link (https://x.com/sam). The match is exact but ignores case, and covers merged accounts. Add platform to pick one platform. A link already tells which platform it is.","name":"handle","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":40,"description":"Keeps people with this tag, matched exactly and by case."},"required":false,"description":"Keeps people with this tag, matched exactly and by case.","name":"tag","in":"query"},{"schema":{"type":"boolean","description":"true keeps muted people and false people who are not muted. Leave it out for everyone."},"required":false,"description":"true keeps muted people and false people who are not muted. Leave it out for everyone.","name":"muted","in":"query"},{"schema":{"type":"string","description":"A time in ISO 8601 or epoch ms. Keeps people first matched then or later.","format":"date-time"},"required":false,"description":"A time in ISO 8601 or epoch ms. Keeps people first matched then or later.","name":"since","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds a saved segment's filter to all other filters here. An unknown id returns 404."},"required":false,"description":"Adds a saved segment's filter to all other filters here. An unknown id returns 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps people who have an account on one of these platforms. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people who have an account on one of these platforms. Repeat the parameter or separate values with commas.","name":"platforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps people with one of these tags. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people with one of these tags. Repeat the parameter or separate values with commas.","name":"tags","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"required":false,"description":"This many followers or more. People with an unknown count are left out.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps people with this many followers or fewer."},"required":false,"description":"Keeps people with this many followers or fewer.","name":"maxFollowers","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"required":false,"description":"Minimum number of matched mentions.","name":"minMentions","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"required":false,"description":"Minimum number of negative mentions.","name":"minNegative","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"required":false,"description":"Has a mention tagged with one 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people with an account on these platforms. Repeat the parameter or separate values with commas."},"required":false,"description":"Leaves out people with an account on these platforms. Repeat the parameter or separate values with commas.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out people with one of these tags. Repeat the parameter or separate values with commas."},"required":false,"description":"Leaves out people with one of these tags. Repeat the parameter or separate values with commas.","name":"notTags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"Leaves out people whose mentions have one of these intents. Repeat the parameter or separate values with commas."},"required":false,"description":"Leaves out people whose mentions have one of these intents. Repeat the parameter or separate values with commas.","name":"notIntents","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"required":false,"description":"Only people with a mention of these keyword kinds.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword kinds."},"required":false,"description":"Excludes people who mentioned these keyword kinds.","name":"neverKeywordKinds","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"required":false,"description":"People first seen in the past this many days.","name":"newSinceDays","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps people with a mention that links to one of these hosts or its subdomains. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people with a mention that links to one of these hosts or its subdomains. Repeat the parameter or separate values with commas.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Keeps people at one of these outreach stages. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people at one of these outreach stages. Repeat the parameter or separate values with commas.","name":"stages","in":"query"},{"schema":{"type":"boolean","description":"true keeps people whose matched posts are mostly machine-made, such as bots. false keeps the others. Leave it out for everyone."},"required":false,"description":"true keeps people whose matched posts are mostly machine-made, such as bots. false keeps the others. Leave it out for everyone.","name":"automated","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps people owned by one of these members, by user id. Use `none` for people without an owner. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people owned by one of these members, by user id. Use `none` for people without an owner. Repeat the parameter or separate values with commas.","name":"ownerIds","in":"query"},{"schema":{"type":"string","enum":["mentions","recent","reach","new"],"default":"mentions","description":"mentions puts the most matches first. recent puts the most recently seen first. reach puts the most followers first, with unknown counts at the end. new puts people seen for the first time most recently first."},"required":false,"description":"mentions puts the most matches first. recent puts the most recently seen first. reach puts the most followers first, with unknown counts at the end. new puts people seen for the first time most recently first.","name":"sort","in":"query"}],"responses":{"200":{"description":"A UTF-8 CSV file","content":{"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no segment with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Over 6 exports in this minute. Wait the Retry-After seconds and try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people":{"get":{"operationId":"listPeople","summary":"List people","description":"Returns the authors of your mentions, one row per person. Each row has their accounts, reach, public profile, stats for this workspace, your notes and tags, and your outreach status. You can filter by platform, tag, follower range, mention counts, intents, keyword kinds they did or did not mention, outreach stage, owner, automated (bots whose matched posts are mostly machine-made) or a saved segment. Pages use offset and include 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":"Only people with a profile on this platform."},"required":false,"description":"Only people with a profile on this platform.","name":"platform","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Searches the display name, handle and profile link, ignoring case."},"required":false,"description":"Searches the display name, handle and profile link, ignoring case.","name":"q","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":300,"description":"Looks up a person by one of their accounts, given as a handle (@sam, u/sam, sam) or a profile or post link (https://x.com/sam). The match is exact but ignores case, and covers merged accounts. Add platform to pick one platform. A link already tells which platform it is."},"required":false,"description":"Looks up a person by one of their accounts, given as a handle (@sam, u/sam, sam) or a profile or post link (https://x.com/sam). The match is exact but ignores case, and covers merged accounts. Add platform to pick one platform. A link already tells which platform it is.","name":"handle","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":40,"description":"Keeps people with this tag, matched exactly and by case."},"required":false,"description":"Keeps people with this tag, matched exactly and by case.","name":"tag","in":"query"},{"schema":{"type":"boolean","description":"true keeps muted people and false people who are not muted. Leave it out for everyone."},"required":false,"description":"true keeps muted people and false people who are not muted. Leave it out for everyone.","name":"muted","in":"query"},{"schema":{"type":"string","description":"A time in ISO 8601 or epoch ms. Keeps people first matched then or later.","format":"date-time"},"required":false,"description":"A time in ISO 8601 or epoch ms. Keeps people first matched then or later.","name":"since","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Adds a saved segment's filter to all other filters here. An unknown id returns 404."},"required":false,"description":"Adds a saved segment's filter to all other filters here. An unknown id returns 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps people who have an account on one of these platforms. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people who have an account on one of these platforms. Repeat the parameter or separate values with commas.","name":"platforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps people with one of these tags. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people with one of these tags. Repeat the parameter or separate values with commas.","name":"tags","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"required":false,"description":"This many followers or more. People with an unknown count are left out.","name":"minFollowers","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"description":"Keeps people with this many followers or fewer."},"required":false,"description":"Keeps people with this many followers or fewer.","name":"maxFollowers","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"required":false,"description":"Minimum number of matched mentions.","name":"minMentions","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"required":false,"description":"Minimum number of negative mentions.","name":"minNegative","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"required":false,"description":"Has a mention tagged with one 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people with an account on these platforms. Repeat the parameter or separate values with commas."},"required":false,"description":"Leaves out people with an account on these platforms. Repeat the parameter or separate values with commas.","name":"notPlatforms","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out people with one of these tags. Repeat the parameter or separate values with commas."},"required":false,"description":"Leaves out people with one of these tags. Repeat the parameter or separate values with commas.","name":"notTags","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":10,"description":"Leaves out people whose mentions have one of these intents. Repeat the parameter or separate values with commas."},"required":false,"description":"Leaves out people whose mentions have one of these intents. Repeat the parameter or separate values with commas.","name":"notIntents","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"required":false,"description":"Only people with a mention of these keyword kinds.","name":"keywordKinds","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword kinds."},"required":false,"description":"Excludes people who mentioned these keyword kinds.","name":"neverKeywordKinds","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"required":false,"description":"People first seen in the past this many days.","name":"newSinceDays","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps people with a mention that links to one of these hosts or its subdomains. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people with a mention that links to one of these hosts or its subdomains. Repeat the parameter or separate values with commas.","name":"linkHosts","in":"query"},{"schema":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Keeps people at one of these outreach stages. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people at one of these outreach stages. Repeat the parameter or separate values with commas.","name":"stages","in":"query"},{"schema":{"type":"boolean","description":"true keeps people whose matched posts are mostly machine-made, such as bots. false keeps the others. Leave it out for everyone."},"required":false,"description":"true keeps people whose matched posts are mostly machine-made, such as bots. false keeps the others. Leave it out for everyone.","name":"automated","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps people owned by one of these members, by user id. Use `none` for people without an owner. Repeat the parameter or separate values with commas."},"required":false,"description":"Keeps people owned by one of these members, by user id. Use `none` for people without an owner. Repeat the parameter or separate values with commas.","name":"ownerIds","in":"query"},{"schema":{"type":"string","enum":["mentions","recent","reach","new"],"default":"mentions","description":"mentions puts the most matches first. recent puts the most recently seen first. reach puts the most followers first, with unknown counts at the end. new puts people seen for the first time most recently first."},"required":false,"description":"mentions puts the most matches first. recent puts the most recently seen first. reach puts the most followers first, with unknown counts at the end. new puts people seen for the first time most recently first.","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"How many to return, from 1 to 100."},"required":false,"description":"How many to return, from 1 to 100.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"default":0,"description":"People to skip. Offset paging is for grouped lists of hundreds, not streams."},"required":false,"description":"People to skip. Offset paging is for grouped lists of hundreds, not streams.","name":"offset","in":"query"}],"responses":{"200":{"description":"A page of people","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The person's id (aut_...), which is the id of their main account. An account merged into a person leads to that person."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The main account's platform. See `accounts` for all of them."},"name":{"type":"string","nullable":true,"description":"The name shown on their latest post. Null if the platform has none."},"handle":{"type":"string","nullable":true,"description":"The main account's handle, written the platform's way."},"url":{"type":"string","nullable":true,"description":"Link to the main account's profile."},"avatarUrl":{"type":"string","nullable":true},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The account's id (aut_...). The main account's id is the person's id."},"platform":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"name":{"type":"string","nullable":true,"description":"The name shown on the platform."},"handle":{"type":"string","nullable":true,"description":"The handle taken from the profile link, written the platform's way."},"url":{"type":"string","nullable":true,"description":"Link to the profile."}},"required":["id","platform","name","handle","url"]},"description":"All accounts this workspace counts as this person, starting with the main one."},"reach":{"type":"object","properties":{"followers":{"type":"integer","nullable":true},"following":{"type":"integer","nullable":true},"posts":{"type":"integer","nullable":true}},"required":["followers","following","posts"],"description":"Counts from the platform, taken from their latest post. Null where a platform lacks the 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":"Filled in only for a public address 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 linked from the person's profile."},"fetchedAt":{"type":"string","description":"Last profile fetch time."}},"required":["bio","company","location","website","email","links","fetchedAt"],"description":"Details from the public profile. Null until the profile is fetched."},"stats":{"type":"object","properties":{"mentions":{"type":"integer","minimum":0,"description":"All their matches in this workspace, relevant or not."},"relevant":{"type":"integer","minimum":0,"description":"How many of them scored as 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":"Time of their first matched post."},"lastSeenAt":{"type":"string","description":"Time of their latest matched post."}},"required":["mentions","relevant","sentiment","firstSeenAt","lastSeenAt"],"description":"Counted from this workspace's matches only."},"annotations":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"notes":{"type":"string"},"muted":{"type":"boolean","description":"Their posts are kept out of the feed and all channels. Collection and billing still happen."}},"required":["tags","notes","muted"],"description":"Notes and tags your workspace added to the person."},"outreach":{"type":"object","properties":{"owner":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The member's user id."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"The teammate responsible for this contact. Null when no one is, or when that member has left the workspace."},"stage":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"lastContactedAt":{"type":"string","nullable":true,"description":"Time of the latest logged activity. Null when no contact was logged."}},"required":["owner","stage","lastContactedAt"],"description":"Your outreach to this person. Logging the first activity makes the member who reached out the owner, if there was none, 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":"How many people match the filters, over all pages."}},"required":["data","total"]}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no segment with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}":{"get":{"operationId":"getPerson","summary":"Get a person","description":"Fetches a person, with your workspace's own data on them. The id of a merged account returns the person it was merged into.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's id (aut_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The requested person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no mention by this person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updatePerson","summary":"Update a person","description":"Changes your workspace's tags, notes and mute for the person, and the outreach owner and stage. The owner must be a workspace member, and null removes it. Muting hides their posts from your feed and all channels. Collection and billing do not change.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's 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":"Sets the full new list."},"notes":{"type":"string","maxLength":2000},"muted":{"type":"boolean"},"ownerId":{"type":"string","nullable":true,"minLength":1,"description":"The user id of the member responsible for this contact. Null removes it."},"stage":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The person after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"400":{"description":"The body is not valid, or the owner is not in the workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no mention by this person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/merge":{"post":{"operationId":"mergePeople","summary":"Merge people","description":"Marks this account and another person as the same individual, in your workspace only. The person in `into` receives the mentions, tags, notes and outreach activities, and keeps its owner and stage, taking the other's where it has none.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's id (aut_...).","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"into":{"type":"string","minLength":1,"description":"The id of the person to merge this account into."}},"required":["into"]}}}},"responses":{"200":{"description":"The person who now has this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace does not know one of the two","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/split":{"post":{"operationId":"splitPerson","summary":"Split a person","description":"Reverses a merge, so the account is a separate person again.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's id (aut_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The account as a separate person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Person"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This account is not merged into another person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/activities":{"get":{"operationId":"listPersonActivities","summary":"List outreach activities","description":"Returns up to 200 logged contacts with this person over all their accounts, latest first. Each shows who reached out, the channel, the time and a short note. Check it before you reach out, so two teammates don't contact the same person unaware.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's id (aut_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The person's logged activities","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The activity's id (act_...)."},"personId":{"type":"string","description":"The person's id (aut_...)."},"channel":{"type":"string","enum":["email","x","linkedin","bluesky","reddit","github","call","meeting","other"],"description":"How the person was contacted."},"note":{"type":"string","description":"A short summary of what was sent or said. Empty if none was written."},"member":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The member's user id."},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true}},"required":["id","name","email"],"description":"Who made contact. Null for an API-key entry without memberId, or after that member leaves."},"occurredAt":{"type":"string","description":"When the contact took place."},"createdAt":{"type":"string","description":"When the activity was logged."}},"required":["id","personId","channel","note","member","occurredAt","createdAt"]},"description":"Up to 200, latest first."}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no mention by this person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"logPersonActivity","summary":"Log outreach","description":"Logs a contact with this person, such as an email, a direct message or a call. A not_contacted person moves to contacted. A person with no owner gets the contacting member as owner. A later stage or an existing owner is left alone. `memberId` falls back to the signed-in member. An API-key request without memberId logs an activity with no member, so no owner is set.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's 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 the person was contacted."},"note":{"type":"string","maxLength":2000,"default":"","description":"A short summary of what was sent or said."},"occurredAt":{"type":"string","description":"Defaults to now. Otherwise send the contact time as ISO 8601 or epoch ms.","format":"date-time"},"memberId":{"type":"string","minLength":1,"description":"The user id of the member who reached out. Defaults to the signed-in member. With an API key and no value, the activity has no member."}},"required":["channel"]}}}},"responses":{"201":{"description":"The new activity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonActivity"}}}},"400":{"description":"The body is not valid, or memberId is not in the workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no mention by this person","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/people/{id}/activities/{activityId}":{"delete":{"operationId":"deletePersonActivity","summary":"Delete outreach","description":"Deletes an activity that was logged by mistake. The person keeps the same owner and stage.","tags":["People"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The person's id (aut_...).","example":"aut_abc123"},"required":true,"description":"The person's id (aut_...).","name":"id","in":"path"},{"schema":{"type":"string","minLength":1,"description":"The activity's id (act_...).","example":"act_abc123"},"required":true,"description":"The activity's id (act_...).","name":"activityId","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This person has no activity with this id in your workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/segments":{"get":{"operationId":"listSegments","summary":"List segments","description":"Returns your saved segments with the current number of people in each, plus presets you can save as a start. Segments are counted on each read and never stored as lists. To see who is in one, send its id to GET /v1/people.","tags":["Segments"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All segments and the presets","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The segment's 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Only people with a profile on one of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People with one of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"This many followers or fewer. People with an unknown count are left out."},"minMentions":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people who have an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out people with one of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Excludes people with a mention of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with a mention that links to one of these hosts or its subdomains."},"muted":{"type":"boolean","description":"true keeps only muted people and false only people who are not muted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Only people in one of these outreach stages."},"automated":{"type":"boolean","description":"true keeps people whose matched posts are mostly automated, like bots. false keeps the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by one of these members, by user id. Use \"none\" for people without an owner."}}},"count":{"type":"integer","minimum":0,"description":"How many people are in the segment now. It is counted again on each read."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"updatedAt":{"type":"string","description":"UTC time in ISO 8601."}},"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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Only people with a profile on one of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People with one of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"This many followers or fewer. People with an unknown count are left out."},"minMentions":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people who have an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out people with one of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Excludes people with a mention of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with a mention that links to one of these hosts or its subdomains."},"muted":{"type":"boolean","description":"true keeps only muted people and false only people who are not muted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Only people in one of these outreach stages."},"automated":{"type":"boolean","description":"true keeps people whose matched posts are mostly automated, like bots. false keeps the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by one of these members, by user id. Use \"none\" for people without an owner."}}}},"required":["key","name","description","filter"]},"description":"Suggested filters, ready to save with POST /v1/segments."}},"required":["data","presets"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createSegment","summary":"Create a segment","description":"Saves a people filter under a name. Names are unique in the workspace (409). The response says how many people match now.","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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Only people with a profile on one of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People with one of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"This many followers or fewer. People with an unknown count are left out."},"minMentions":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people who have an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out people with one of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Excludes people with a mention of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with a mention that links to one of these hosts or its subdomains."},"muted":{"type":"boolean","description":"true keeps only muted people and false only people who are not muted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Only people in one of these outreach stages."},"automated":{"type":"boolean","description":"true keeps people whose matched posts are mostly automated, like bots. false keeps the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by one of these members, by user id. Use \"none\" for people without an owner."}},"default":{}}},"required":["name"]}}}},"responses":{"201":{"description":"The new segment and how many people are in it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"400":{"description":"The body is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This name is already used by a segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/segments/{id}":{"get":{"operationId":"getSegment","summary":"Get a segment","description":"Returns one segment with its filter and how many people match it now.","tags":["Segments"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The segment's id (seg_...).","example":"seg_abc123"},"required":true,"description":"The segment's id (seg_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The segment and how many people are in it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no segment with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateSegment","summary":"Update a segment","description":"Changes a segment's name, description or filter. A new filter replaces the old one completely.","tags":["Segments"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The segment's id (seg_...).","example":"seg_abc123"},"required":true,"description":"The segment's 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Only people with a profile on one of these platforms."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"People with one of these tags."},"minFollowers":{"type":"integer","minimum":0,"description":"This many followers or more. People with an unknown count are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"This many followers or fewer. People with an unknown count are left out."},"minMentions":{"type":"integer","minimum":1,"description":"Minimum number of matched mentions."},"minNegative":{"type":"integer","minimum":1,"description":"Minimum number of negative mentions."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Has a mention tagged with one of these intents."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Only people with a mention of these keyword kinds."},"neverKeywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Excludes people who mentioned these keyword 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Leaves out people who have an account on these platforms."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out people with one of these tags."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":10,"description":"Excludes people with a mention of these intents."},"newSinceDays":{"type":"integer","minimum":1,"maximum":365,"description":"People first seen in the past this many days."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People with a mention that links to one of these hosts or its subdomains."},"muted":{"type":"boolean","description":"true keeps only muted people and false only people who are not muted."},"stages":{"type":"array","items":{"type":"string","enum":["not_contacted","contacted","replied","in_talks","customer","not_a_fit"],"description":"The outreach stage your team has reached with this person."},"maxItems":6,"description":"Only people in one of these outreach stages."},"automated":{"type":"boolean","description":"true keeps people whose matched posts are mostly automated, like bots. false keeps the rest."},"ownerIds":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"People owned by one of these members, by user id. Use \"none\" for people without an owner."}},"description":"Sets the full new filter."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The segment after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Segment"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no segment with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This name is already used by a segment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteSegment","summary":"Delete a segment","description":"Deletes the segment. The people in it are not changed.","tags":["Segments"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The segment's id (seg_...).","example":"seg_abc123"},"required":true,"description":"The segment's id (seg_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Your workspace has no segment with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/views":{"get":{"operationId":"listViews","summary":"List views","description":"Lists the saved views in creation order. A view stores a mention filter under a name. GET /v1/mentions and the exports take its id as `viewId` and return what the view shows.","tags":["Views"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The workspace's views","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The view's id (vw_...)."},"name":{"type":"string"},"description":{"type":"string"},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Searches post text and author names."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keeps matches of these keywords only."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keyword ids to exclude."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keyword kinds to keep, out of brand, competitor and topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Limits to keywords from these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Hides matches from keywords that belong to 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only (open, ignored or done)."},"relevant":{"type":"boolean","description":"Filter on the classifier's verdict. true keeps relevant mentions, false the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Minimum relevance score a mention needs."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Keeps mentions whose classifier confidence is this value or higher."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Hides these sentiments. Unscored mentions stay."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Hides mentions with these tags."},"automated":{"type":"boolean","description":"true keeps posts that look machine-made. false keeps the others."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Keeps posts in these languages only, as ISO 639-1 codes."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out authors with one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or more. Unknown counts are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or fewer. Unknown counts are left out."},"isReply":{"type":"boolean","description":"true keeps replies and comments. false keeps posts that are not replies."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Hides reviews with these star ratings. Other posts are not affected."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}}},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"updatedAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["id","name","description","filter","createdAt","updatedAt"]},"description":"The views, oldest first."}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createView","summary":"Create a view","description":"Saves a named mention filter. It uses the same fields as GET /v1/mentions, where a list matches any value, a `not` list matches none, and all conditions are joined by AND. `anyOf` adds groups of such conditions, at least one of which must match. An empty filter shows all mentions. Nothing is stored ahead of time, so a view shows whatever matches when you read it.","tags":["Views"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"Must be unique in the workspace, ignoring case."},"description":{"type":"string","maxLength":500,"default":"","description":"The view's purpose, shown below its name."},"filter":{"type":"object","properties":{"q":{"type":"string","minLength":1,"maxLength":200,"description":"Searches post text and author names."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keeps matches of these keywords only."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keyword ids to exclude."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keyword kinds to keep, out of brand, competitor and topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Limits to keywords from these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Hides matches from keywords that belong to 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only (open, ignored or done)."},"relevant":{"type":"boolean","description":"Filter on the classifier's verdict. true keeps relevant mentions, false the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Minimum relevance score a mention needs."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Keeps mentions whose classifier confidence is this value or higher."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Hides these sentiments. Unscored mentions stay."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Hides mentions with these tags."},"automated":{"type":"boolean","description":"true keeps posts that look machine-made. false keeps the others."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Keeps posts in these languages only, as ISO 639-1 codes."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out authors with one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or more. Unknown counts are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or fewer. Unknown counts are left out."},"isReply":{"type":"boolean","description":"true keeps replies and comments. false keeps posts that are not replies."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Hides reviews with these star ratings. Other posts are not affected."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}},"default":{},"description":"The view's filter. Empty means all mentions."}},"required":["name"]}}}},"responses":{"201":{"description":"The new view","content":{"application/json":{"schema":{"$ref":"#/components/schemas/View"}}}},"400":{"description":"The filter is not valid, for example an empty anyOf group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This name is already used by a view (duplicate_view)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/views/{id}":{"get":{"operationId":"getView","summary":"Get a view","description":"Returns one saved view and its filter. Pass its id as `viewId` to list or export the mentions it shows.","tags":["Views"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The view's id (vw_...).","example":"vw_abc123"},"required":true,"description":"The view's id (vw_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The requested view","content":{"application/json":{"schema":{"$ref":"#/components/schemas/View"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no view with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateView","summary":"Update a view","description":"Changes a view's name, description or filter. `filter` sets the full new filter.","tags":["Views"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The view's id (vw_...).","example":"vw_abc123"},"required":true,"description":"The view's 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":"Searches post text and author names."},"keywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keeps matches of these keywords only."},"notKeywordIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Keyword ids to exclude."},"keywordKinds":{"type":"array","items":{"type":"string","enum":["brand","competitor","topic"]},"maxItems":3,"description":"Keyword kinds to keep, out of brand, competitor and topic."},"groupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Limits to keywords from these groups (grp_...)."},"notGroupIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":50,"description":"Hides matches from keywords that belong to 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":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Keeps posts from these platforms only."},"notPlatforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"maxItems":20,"description":"Platforms to exclude."},"status":{"type":"string","enum":["open","ignored","done"],"description":"Keeps mentions with this status only (open, ignored or done)."},"relevant":{"type":"boolean","description":"Filter on the classifier's verdict. true keeps relevant mentions, false the rest."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"Minimum relevance score a mention needs."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Keeps mentions whose classifier confidence is this value or higher."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Keeps mentions with these sentiments only."},"notSentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"maxItems":3,"description":"Hides these sentiments. Unscored mentions stay."},"intents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps mentions tagged with one of these intents or topics."},"notIntents":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Hides mentions with these tags."},"automated":{"type":"boolean","description":"true keeps posts that look machine-made. false keeps the others."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Keeps posts in these languages only, as ISO 639-1 codes."},"notLanguages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Leaves out posts in these languages. Posts with an unknown language are kept."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"notTags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Leaves out authors with one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Keeps posts that link to one of these hosts or its subdomains."},"notLinkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Leaves out posts that link to these hosts."},"minFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or more. Unknown counts are left out."},"maxFollowers":{"type":"integer","minimum":0,"description":"Keeps authors with this many followers or fewer. Unknown counts are left out."},"isReply":{"type":"boolean","description":"true keeps replies and comments. false keeps posts that are not replies."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Keeps reviews with one of these star ratings. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Hides reviews with these star ratings. Other posts are not affected."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}},"description":"Sets the full new filter."}}}}}},"responses":{"200":{"description":"The view after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/View"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no view with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This name is already used by a view (duplicate_view)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteView","summary":"Delete a view","description":"Deletes the view. Its mentions are unchanged.","tags":["Views"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The view's id (vw_...).","example":"vw_abc123"},"required":true,"description":"The view's id (vw_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no view with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/attention":{"get":{"operationId":"listAttention","summary":"List attention items","description":"Lists items that need a person, latest first. Kinds are mention.spike (a keyword's mentions jumped in the last hour), sentiment.negative_spike (its 24-hour negative share jumped), keyword.noisy (it turned noisy) and channel.failing (a channel's recent sends all failed). Checks run hourly. Items open when the condition starts and resolve when it ends. Open items are the default, and `status=all` adds the history. Opening an item also sends an account event of the same name to subscribed webhook, Slack, email and Telegram channels.","tags":["Attention"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["open","resolved","dismissed","all"],"default":"open","description":"Which items to list. Defaults to open."},"required":false,"description":"Which items to list. Defaults to open.","name":"status","in":"query"},{"schema":{"type":"string","description":"Filters by kind. Send a comma-separated list such as mention.spike,keyword.noisy."},"required":false,"description":"Filters by kind. Send a comma-separated list such as mention.spike,keyword.noisy.","name":"kind","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"How many items to return, latest first. 50 by default and 100 at most."},"required":false,"description":"How many items to return, latest first. 50 by default and 100 at most.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Pass the previous page's nextCursor."},"required":false,"description":"Pass the previous page's nextCursor.","name":"cursor","in":"query"}],"responses":{"200":{"description":"The attention items","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttentionItem"}},"nextCursor":{"type":"string","nullable":true,"description":"Cursor for the next page, or null when there are no more pages."}},"required":["data","nextCursor"]}}}},"400":{"description":"The kind is unknown, or the cursor did not come from this list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/attention/{id}/dismiss":{"post":{"operationId":"dismissAttention","summary":"Dismiss an attention item","description":"Dismisses an item. It leaves the open list and stays away while its condition lasts. After the condition ends, a new episode can open a new item. Calling it twice has the same effect as once.","tags":["Attention"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The attention item's id (att_...).","example":"att_abc123"},"required":true,"description":"The attention item's id (att_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The item, now dismissed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttentionItem"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no attention item with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/groups":{"get":{"operationId":"listGroups","summary":"List groups","description":"Returns the workspace's keyword groups, the default group first and then the oldest. Groups organize keywords, for example by client, campaign or product. Every keyword is in one group, a group can hold a term once, and GET /v1/usage/breakdown?by=group shows each group's cost. `externalId` looks a group up by your own id.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":128,"description":"Filters to the one group whose externalId matches exactly."},"required":false,"description":"Filters to the one group whose externalId matches exactly.","name":"externalId","in":"query"}],"responses":{"200":{"description":"The workspace's 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":"A company description just for this group, which the classifier reads. Null means the workspace profile is used."},"stats":{"type":"object","properties":{"keywords":{"type":"integer","minimum":0,"description":"Number of keywords in the group, muted or not."},"active":{"type":"integer","minimum":0,"description":"Number of unmuted keywords in the group."}},"required":["keywords","active"],"description":"Counted from the group's keywords."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"updatedAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["context","stats","createdAt","updatedAt"]}],"description":"The keyword's group."},"description":"Default group first, then the rest, oldest first."}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createGroup","summary":"Create a group","description":"Creates a keyword group. `name` must be unique in the workspace. `externalId` is optional and also unique. It is your own id, such as a client id, so you can find the group without storing ours. `context` is optional. It is a company description for this group, which the classifier reads instead of the workspace profile for the group's keywords. Then send the group's id as `groupId` when you create 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, such as a client, campaign or product. Must be unique in the workspace."},"externalId":{"type":"string","nullable":true,"minLength":1,"maxLength":128,"description":"An id from your own system, such as a client id. Must be unique in the workspace. Find the group with GET /v1/groups?externalId=."},"context":{"type":"string","nullable":true,"maxLength":4000,"description":"Up to 4000 characters the classifier treats as \"the company\" for this group's keywords. It fully replaces the workspace profile, including its relevance guidelines and competitors. Describe the business, what it sells and to whom, what it is not, and any rule for this group, such as \"ignore job posts\". With one group per client, use the client's description. Null means the workspace profile is used."}},"required":["name"]}}}},"responses":{"201":{"description":"The group that was created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This name or externalId is already used by a group (duplicate_group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/groups/{id}":{"get":{"operationId":"getGroup","summary":"Get a group","description":"Returns one keyword group with its external id and keyword counts.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The group's id (grp_...).","example":"grp_abc123"},"required":true,"description":"The group's id (grp_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The requested group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no group with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateGroup","summary":"Update a group","description":"Changes a group's name, your `externalId` for it or its company description in `context`. Null clears externalId. Null clears context too, so the workspace profile applies again. New mentions use the new context right away, and older ones are not scored again. You can rename the default group, but it takes no description, because it is the workspace itself and uses the company profile.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The group's id (grp_...).","example":"grp_abc123"},"required":true,"description":"The group's 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, such as a client, campaign or product. Must be unique in the workspace."},"externalId":{"type":"string","nullable":true,"minLength":1,"maxLength":128,"description":"Sets a new external id. Null removes it."},"context":{"type":"string","nullable":true,"maxLength":4000,"description":"Sets a new company description for the group. Null removes it, and the workspace profile applies again. New mentions use it right away, and older ones are not scored again. The default group cannot have one (400 default_group_context), because it is the workspace itself and uses the profile."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The group after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Group"}}}},"400":{"description":"The default group cannot have a company description (default_group_context)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no group with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This name or externalId is already used by a group (duplicate_group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteGroup","summary":"Delete a group","description":"Deletes the group and all of its keywords, each as DELETE /v1/keywords/{id} would. Their mentions are deleted too, alert rules that named them are updated, and past charges stay in the usage record. Read the group first, since `stats.keywords` tells you how many keywords will be deleted. Only non-default groups can be deleted.","tags":["Groups"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The group's id (grp_...).","example":"grp_abc123"},"required":true,"description":"The group's id (grp_...).","name":"id","in":"path"}],"responses":{"204":{"description":"The group and its keywords were removed"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"This workspace has no group with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Deleting the default group is not allowed (default_group)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/company":{"get":{"operationId":"getCompany","summary":"Get the company profile","description":"Returns what the classifier knows about your company. That is the name, description, use cases and your accounts, plus the context text built from them.","tags":["Company"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Your company profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Company"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"The workspace does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateCompany","summary":"Update the company profile","description":"Changing profile fields rebuilds the classifier's context. Setting `context` yourself replaces it until the next profile change. New mentions are scored with the change right away.","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":"Sets the full new 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's website. Null removes it."},"competitors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"maxItems":50,"description":"Sets the full new list. An empty list clears it."},"guidelines":{"type":"string","nullable":true,"maxLength":2000,"description":"Rules for the classifier in your own words. Null removes them."},"context":{"type":"string","maxLength":4000,"description":"Replaces the built context until the next profile change."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The profile after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Company"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"The workspace does not exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/api-keys":{"post":{"operationId":"createApiKey","summary":"Create an API key","description":"Issues a new API key in this workspace. The key is shown only in this response, and only its hash is stored. `expiresAt` makes it stop working at a set time, useful for a contractor or a one-off script. An expired key stays in the list until you revoke it.","tags":["API keys"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"A name for the key. Defaults to \"default\"."},"scope":{"type":"string","enum":["read","write"],"default":"write","description":"write can do everything. read is limited to GET."},"expiresAt":{"type":"string","description":"Expiry time in ISO 8601 or epoch ms, later than now. Set it for keys you hand to a script or contractor. Omit it or send null and the key never expires.","format":"date-time"}}}}}},"responses":{"201":{"description":"The created key, visible only now","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The key's id (key_...)."},"name":{"type":"string"},"prefix":{"type":"string","description":"The start of the key, so you can tell keys apart."},"scope":{"type":"string","enum":["read","write"],"description":"write can do everything. read is limited to GET."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"lastUsedAt":{"type":"string","nullable":true,"description":"UTC time in ISO 8601."},"expiresAt":{"type":"string","nullable":true,"description":"When the key expires. Null for a key without expiry. Expired keys stay in the list until revoked."},"key":{"type":"string","description":"The complete key. It is only shown here, so save it now."}},"required":["id","name","prefix","scope","createdAt","lastUsedAt","expiresAt","key"]}}}},"400":{"description":"expiresAt must be a future time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listApiKeys","summary":"List API keys","description":"Lists the workspace's active keys, latest first, with name, prefix, scope, expiry and last use. Revoked keys and secrets are never listed.","tags":["API keys"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All keys, latest first, without the secret","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The key's id (key_...)."},"name":{"type":"string"},"prefix":{"type":"string","description":"The start of the key, so you can tell keys apart."},"scope":{"type":"string","enum":["read","write"],"description":"write can do everything. read is limited to GET."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"lastUsedAt":{"type":"string","nullable":true,"description":"UTC time in ISO 8601."},"expiresAt":{"type":"string","nullable":true,"description":"When the key expires. Null for a key without expiry. Expired keys stay in the list until revoked."}},"required":["id","name","prefix","scope","createdAt","lastUsedAt","expiresAt"]}}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/api-keys/{id}":{"delete":{"operationId":"revokeApiKey","summary":"Revoke an API key","description":"Revokes the key. The API refuses it right away, and cached checks catch up within a few minutes.","tags":["API keys"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The API key's id (key_...).","example":"key_abc123"},"required":true,"description":"The API key's id (key_...).","name":"id","in":"path"}],"responses":{"204":{"description":"The key no longer works"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No API key with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/whoami":{"get":{"operationId":"whoami","summary":"Check the credential","description":"Call this first. It shows the workspace the credential works in, its type (API key, MCP sign-in token or dashboard session), whether it can write, and for keys the id and expiry. A read key gets 403 read_only_key on any write, and scripts often aim at the wrong workspace.","tags":["Auth"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Details of the credential","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Whoami"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members":{"get":{"operationId":"listMembers","summary":"List members","description":"Returns all workspace members, owners first. Use `userId` for a mention's assigneeId and a person's ownerId.","tags":["Members"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The workspace's members","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members/invitations":{"get":{"operationId":"listInvitations","summary":"List pending invitations","description":"Returns invitations that have not been accepted, declined or expired yet. Once accepted, the person shows up in GET /v1/members.","tags":["Members"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The pending invitations","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invitation"}}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createInvitation","summary":"Invite a member","description":"Invites an address by email as admin or member. Invitations expire after 48 hours. Repeating it for a pending address returns that invitation with 200 and sends nothing. Existing members get 409 already_member. Needs a signed-in owner or admin (dashboard session or MCP sign-in token). API keys get 403.","tags":["Members"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","maxLength":200,"format":"email","description":"Address that receives the join link."},"role":{"type":"string","enum":["admin","member"],"default":"member","description":"The role they get when they join. Ownership can only be given in the dashboard."}},"required":["email"]}}}},"responses":{"200":{"description":"The pending invitation for this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"201":{"description":"The invitation that was emailed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invitation"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"An API key was used, or the signed-in user is not an owner or admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This address belongs to a member already (already_member)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members/invitations/{id}":{"delete":{"operationId":"revokeInvitation","summary":"Revoke an invitation","description":"Cancels the invitation, and its email link stops working right away. Needs a signed-in owner or admin. An API key gets 403.","tags":["Members"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The invitation's id (inv_...).","example":"inv_abc123"},"required":true,"description":"The invitation's id (inv_...).","name":"id","in":"path"}],"responses":{"204":{"description":"The key no longer works"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"An API key was used, or the signed-in user is not an owner or admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No pending invitation with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/members/{id}":{"delete":{"operationId":"removeMember","summary":"Remove a member","description":"Needs a signed-in owner or admin. Admins can't remove owners, and the last owner can't be removed at all (409 last_owner). Access ends within a minute, at the next dashboard request or when the OAuth token's short cache expires. The member's mentions, notes and outreach records remain.","tags":["Members"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The membership's id (mem_...).","example":"mem_abc123"},"required":true,"description":"The membership's id (mem_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Needs a signed-in owner or admin, not an API key. Only an owner can remove an owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No member with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The workspace needs at least one owner (last_owner)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/usage":{"get":{"operationId":"getUsage","summary":"Get usage and balance","description":"Shows whether tracking is stopped or the balance is low. Also returns the prepaid balance (ledger total, pending mention charges, and the effective balance that decides pausing), daily spend and days left, running and paused keywords, and matches today and over 30 days. Pricing is $0.008 per matched mention, relevant or not, and $5 a month per active keyword, charged daily.","tags":["Usage"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"A summary of usage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/usage/breakdown":{"get":{"operationId":"getUsageBreakdown","summary":"Get the usage breakdown","description":"Returns what the workspace used and was charged over a period, in US cents at list price. Each call groups rows by one `by` value, day, platform or keyword, and always includes the totals. `range` reads the past UTC days up to today (30d by default). `month` reads one calendar month (YYYY-MM), which is what you match against a bill or a per-client margin. Keyword-days come from the daily run and mention charges from billed matches. So a deleted keyword keeps its charges in the keyword rows (`keyword.removed`), while its mention counts show 0. Each keyword carries the same numbers for the current month as `stats.cost`. `totals.ledgerDebitCents` is what the balance has been debited so far for the period's days. Mentions settle the morning after, so a period ending today is below `totals.totalCents` by the unsettled ones, and a finished month differs only by cumulative rounding. Rows come in pages (`limit`, `offset`, `total`). A workspace can call this 30 times a minute across all its keys and tokens.","tags":["Usage"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["day","platform","keyword","group"],"default":"keyword","description":"How to group the rows. day gives one row per UTC day, then platform, keyword (the default, used to work out margins), or group (the cost of a client or campaign)."},"required":false,"description":"How to group the rows. day gives one row per UTC day, then platform, keyword (the default, used to work out margins), or group (the cost of a client or campaign).","name":"by","in":"query"},{"schema":{"type":"string","enum":["7d","30d","90d"],"description":"How many UTC days back from today to read. One of 7d, 30d or 90d, 30d by default. Ignored when you send `month`."},"required":false,"description":"How many UTC days back from today to read. One of 7d, 30d or 90d, 30d by default. Ignored when you send `month`.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","description":"A calendar month (YYYY-MM, UTC) to read instead of a range. It covers the month's first to last day, or up to today for the current month. A future month returns 400."},"required":false,"description":"A calendar month (YYYY-MM, UTC) to read instead of a range. It covers the month's first to last day, or up to today for the current month. A future month returns 400.","name":"month","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500,"default":100,"description":"How many rows to return, from 1 to 500, 100 by default. Only by=keyword can need more than one page, since a period has at most 90 days and there are only a dozen platforms."},"required":false,"description":"How many rows to return, from 1 to 500, 100 by default. Only by=keyword can need more than one page, since a period has at most 90 days and there are only a dozen platforms.","name":"limit","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":0,"default":0,"description":"How many rows to skip."},"required":false,"description":"How many rows to skip.","name":"offset","in":"query"}],"responses":{"200":{"description":"The period's totals and a page of rows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageBreakdown"}}}},"400":{"description":"Invalid by, range, month or limit. A future month is invalid too","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"The workspace read the breakdown over 30 times in this minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/top-ups":{"post":{"operationId":"createTopUp","summary":"Start a top-up","description":"Returns a hosted checkout link with `amountCents` filled in. The buyer can change it there, from $20 to $5,000. The balance is credited within a minute of payment, and tracking paused for balance resumes right away. This call charges nothing by itself. `successUrl` must be on an origin this deployment trusts. Leave it out to return to 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":"The amount to add in US cents, from 2000 to 500000. Checkout starts with it and the buyer can change it."},"successUrl":{"type":"string","maxLength":2000,"format":"uri","description":"Page to return to after payment. It must be on an origin this deployment trusts, like the dashboard, and defaults to the dashboard's billing page."}},"required":["amountCents"]}}}},"responses":{"200":{"description":"A checkout link with the amount filled in","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"The Polar checkout link."}},"required":["url"]}}}},"400":{"description":"The amount is not valid, or successUrl is not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The credential is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"There is no workspace owner to bill","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"The workspace started too many checkouts in this minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"This deployment has no billing set up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/wallet":{"get":{"operationId":"getWallet","summary":"Get the balance","description":"Returns every detail of the prepaid balance. That covers the ledger total, pending mention charges, the effective balance used for pausing, the daily spend and days left, running and paused keywords, the cost of a day and of resuming, the welcome credit, the latest top-up, the top-up limits and the auto-recharge settings. `GET /v1/usage` gives a shorter version.","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Wallet balance, daily spend and pause state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wallet"}}}},"401":{"description":"The credential is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/ledger":{"get":{"operationId":"listLedger","summary":"List ledger entries","description":"Shows the balance's history, latest first. Entries cover the welcome credit, top-ups, refunds, adjustments, and the daily keyword-day and mention debits. Debits carry their UTC settlement day and cumulative units. Cursor pages.","tags":["Billing"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","description":"The `nextCursor` of the previous page. Do not parse it."},"required":false,"description":"The `nextCursor` of the previous page. Do not parse it.","name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"How many to return, from 1 to 100, 25 by default.","example":25},"required":false,"description":"How many to return, from 1 to 100, 25 by default.","name":"limit","in":"query"}],"responses":{"200":{"description":"Ledger entries, latest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerList"}}}},"400":{"description":"The cursor is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The credential is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/invoices":{"get":{"operationId":"listInvoices","summary":"List receipts","description":"Returns the top-up orders, latest first, as Polar, the merchant of record, stores them. You get this workspace's orders among the billing customer's latest 100. No orders exist before the first top-up.","tags":["Billing"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Receipts for paid orders. Empty before the first payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceList"}}}},"401":{"description":"The credential is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/invoices/{id}/url":{"get":{"operationId":"getInvoiceUrl","summary":"Get a receipt link","description":"For a paid order from GET /v1/billing/invoices, returns a receipt PDF URL that expires soon.","tags":["Billing"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"Which paid order. Ids come from GET /v1/billing/invoices."},"required":true,"description":"Which paid order. Ids come from GET /v1/billing/invoices.","name":"id","in":"path"}],"responses":{"200":{"description":"Receipt PDF URL, valid briefly","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Receipt PDF URL, valid briefly."}},"required":["url"]}}}},"401":{"description":"The credential is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"The receipt does not exist, or its PDF is not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"No billing is set up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}":{"get":{"operationId":"getAlert","summary":"Get an alert","description":"Returns one alert with its filter, mode, schedule, channels and delivery stats.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's id (feed_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The requested alert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateAlert","summary":"Update an alert","description":"Changes an alert. `filter` and `channelIds` replace the old values. Queued digests are cancelled, as are queued sends to a removed channel or from a disabled alert.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's 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":"Limits the rule to these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Limits the rule to keywords in these groups (grp_...), for example one rule for each client."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"description":"Limits the rule to posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The lowest relevance score the rule sends. Without it, only relevant mentions are sent, meaning a score of 40 or more. A lower value, down to 0, also sends matches the classifier rated as noise. A higher value sends fewer. Email channels always use 40, whatever the rule says. Mentions without a score are never sent."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Sends only mentions whose classifier confidence is this value or higher, from 0 to 1. Mentions without a confidence are left out."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"description":"Keeps mentions with these sentiments only."},"intents":{"type":"array","items":{"type":"string"},"description":"Sends only mentions with one or more of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"minFollowers":{"type":"integer","minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Sends only posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Posts without links are left out."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"automated":{"type":"boolean","description":"true sends only posts that look machine-made, such as bot or template posts. false sends only the others. Leave it out to send both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Sends only reviews with one of these star ratings, from 1 to 5. Use [1, 2] for the unhappy ones. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to skip, such as [5]. Other posts still go out."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}},"description":"Sets the full new 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":"The day a weekly rule sends, from 0 for Sunday to 6 for Saturday. Required when mode is weekly and ignored for daily rules."}},"required":["hour","timezone"],"description":"For daily and weekly alerts. An hourly alert ignores it, but refuses a weekday."},"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":"Sets the full new list."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The alert after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"400":{"description":"The schedule doesn't fit the mode, an hourly alert uses email (hourly_email_unsupported), or a channel id is unknown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteAlert","summary":"Delete an alert","description":"Deletes the alert and its delivery history. Its channels stay.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's id (feed_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts":{"get":{"operationId":"listAlerts","summary":"List alerts","description":"Lists the workspace's alerts, latest first, each with its filter, mode, schedule and channels.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All of the workspace's alerts, latest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The alert's id (feed_...)."},"name":{"type":"string"},"enabled":{"type":"boolean"},"mode":{"type":"string","enum":["instant","hourly","daily","weekly"],"description":"instant sends each matching mention as it arrives. hourly sends a digest of the previous full UTC hour at five past the hour, so the hour's last mentions are scored. It skips hours with no mention at or above the rule's relevance minimum, and works with Slack, Telegram and webhook channels only. daily sends one digest at the scheduled local time. weekly sends one digest a week on schedule.weekday."},"filter":{"type":"object","properties":{"keywordIds":{"type":"array","items":{"type":"string"},"description":"Limits the rule to these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Limits the rule to keywords in these groups (grp_...), for example one rule for each client."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"description":"Limits the rule to posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The lowest relevance score the rule sends. Without it, only relevant mentions are sent, meaning a score of 40 or more. A lower value, down to 0, also sends matches the classifier rated as noise. A higher value sends fewer. Email channels always use 40, whatever the rule says. Mentions without a score are never sent."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Sends only mentions whose classifier confidence is this value or higher, from 0 to 1. Mentions without a confidence are left out."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"description":"Keeps mentions with these sentiments only."},"intents":{"type":"array","items":{"type":"string"},"description":"Sends only mentions with one or more of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"minFollowers":{"type":"integer","minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Sends only posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Posts without links are left out."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"automated":{"type":"boolean","description":"true sends only posts that look machine-made, such as bot or template posts. false sends only the others. Leave it out to send both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Sends only reviews with one of these star ratings, from 1 to 5. Use [1, 2] for the unhappy ones. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to skip, such as [5]. Other posts still go out."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}}},"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":"The day a weekly rule sends, from 0 for Sunday to 6 for Saturday. Required when mode is weekly and ignored for daily rules."}},"required":["hour","timezone"],"description":"Null for instant and hourly alerts, which have no schedule."},"event":{"type":"string","description":"The event name sent in webhook payloads. Unless you set one, it is the default for the mode."},"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":"The channels the alert sends to."},"stats":{"type":"object","properties":{"sentLast7d":{"type":"integer","minimum":0,"description":"Deliveries over the past 7 days, all channels together."},"lastSentAt":{"type":"string","nullable":true,"description":"UTC time in ISO 8601."},"nextRunAt":{"type":"string","nullable":true,"description":"When the next digest is due, for hourly, daily and weekly alerts. Null when the alert is disabled or instant."}},"required":["sentLast7d","lastSentAt","nextRunAt"],"description":"Counted from this workspace's deliveries."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."}},"required":["id","name","enabled","mode","filter","schedule","event","channels","stats","createdAt"]}}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createAlert","summary":"Create an alert","description":"Creates an alert, which pairs a filter with one or more channels. instant mode sends each matching mention as it arrives. hourly sends a digest of the previous full UTC hour at five past, skips hours with no mention above the rule's minimum, takes no schedule and works with Slack, Telegram and webhook channels only. daily sends one digest at schedule.hour in schedule.timezone. weekly sends one a week on schedule.weekday, from 0 for Sunday to 6 for Saturday. filter.anyOf adds OR logic with groups of mention-list conditions. At least one group must match, as well as 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":"Limits the rule to these keywords."},"groupIds":{"type":"array","items":{"type":"string"},"description":"Limits the rule to keywords in these groups (grp_...), for example one rule for each client."},"platforms":{"type":"array","items":{"type":"string","enum":["bluesky","hackernews","github","stackoverflow","devto","reddit","x","youtube","news","linkedin","tiktok","instagram","appstore","googleplay","trustpilot","googlemaps"],"description":"The platform. Review platforms are appstore, googleplay, trustpilot and googlemaps (a place's Google reviews)."},"description":"Limits the rule to posts from these platforms."},"minRelevance":{"type":"integer","minimum":0,"maximum":100,"description":"The lowest relevance score the rule sends. Without it, only relevant mentions are sent, meaning a score of 40 or more. A lower value, down to 0, also sends matches the classifier rated as noise. A higher value sends fewer. Email channels always use 40, whatever the rule says. Mentions without a score are never sent."},"minConfidence":{"type":"number","minimum":0,"maximum":1,"description":"Sends only mentions whose classifier confidence is this value or higher, from 0 to 1. Mentions without a confidence are left out."},"sentiments":{"type":"array","items":{"type":"string","enum":["positive","neutral","negative"],"description":"The sentiment the classifier assigned."},"description":"Keeps mentions with these sentiments only."},"intents":{"type":"array","items":{"type":"string"},"description":"Sends only mentions with one or more of these intent or topic tags."},"excludeAuthors":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":200,"description":"Leaves out these authors, given as display names, handles or profile links."},"minFollowers":{"type":"integer","minimum":0,"description":"Sends only posts by authors with this many followers or more. Unknown counts are left out."},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":20,"description":"Keeps authors your workspace gave one of these tags."},"linkHosts":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":20,"description":"Sends only posts that link to one of these hosts or its subdomains, so slack.com also matches api.slack.com. Posts without links are left out."},"languages":{"type":"array","items":{"type":"string","pattern":"^[a-z]{2}$"},"maxItems":20,"description":"Sends only posts in these languages, as ISO 639-1 codes such as en, es or de. Posts with an unknown language are left out."},"automated":{"type":"boolean","description":"true sends only posts that look machine-made, such as bot or template posts. false sends only the others. Leave it out to send both."},"ratings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Sends only reviews with one of these star ratings, from 1 to 5. Use [1, 2] for the unhappy ones. Posts that are not reviews are left out."},"notRatings":{"type":"array","items":{"type":"integer","minimum":1,"maximum":5},"maxItems":5,"description":"Star ratings (1 to 5) to skip, such as [5]. Other posts still go out."},"minLikes":{"type":"integer","minimum":0,"description":"Keeps posts with this many likes (upvotes, reactions) or more, counted when the post was collected. Posts without a like count are left out."},"minReposts":{"type":"integer","minimum":0,"description":"Keeps posts with this many reposts (shares, retweets) or more, counted when the post was collected. Posts without a repost count are left out."},"minReplies":{"type":"integer","minimum":0,"description":"Keeps posts with this many replies (comments) or more, counted when the post was collected. Posts without a reply count are left out."},"minQuotes":{"type":"integer","minimum":0,"description":"Keeps posts with this many quotes or more, counted when the post was collected. Posts without a quote count are left out."},"minViews":{"type":"integer","minimum":0,"description":"Keeps posts with this many views (plays) or more, counted when the post was collected. Posts without a view count are left out."},"minBookmarks":{"type":"integer","minimum":0,"description":"Keeps posts with this many bookmarks (saves) or more, counted when the post was collected. Posts without a bookmark count are left out."},"anyOf":{"type":"array","items":{"$ref":"#/components/schemas/FilterGroup"},"minItems":1,"maxItems":10,"description":"Up to 10 OR'd groups (at least 1). A mention must meet every condition of some group, plus all other conditions, so the filter reads (other conditions) AND (group 1 OR group 2 ...). Groups take view filter fields (platforms, sentiments, intents, keywordKinds, the not lists and so on) but no nested anyOf."}},"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":"The day a weekly rule sends, from 0 for Sunday to 6 for Saturday. Required when mode is weekly and ignored for daily rules."}},"required":["hour","timezone"],"description":"Daily and weekly alerts need it, and weekly ones need schedule.weekday too. Hourly alerts send every UTC hour, ignore a time or zone, and reject a weekday."},"event":{"type":"string","nullable":true,"maxLength":60,"pattern":"^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$","description":"Custom webhook event name. Null keeps the mode's default."},"channelIds":{"type":"array","items":{"type":"string","minLength":1},"maxItems":20,"default":[],"description":"Where to send, as ids from GET /v1/channels."}},"required":["name"]}}}},"responses":{"201":{"description":"The new alert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"400":{"description":"The schedule doesn't fit the mode, an hourly alert uses email (hourly_email_unsupported), or a channel id is unknown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/test":{"post":{"operationId":"testAlert","summary":"Test an alert","description":"Sends a test message to each of the alert's channels now and returns each outcome. Webhooks receive the event `test`.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's id (feed_...).","name":"id","in":"path"}],"responses":{"200":{"description":"A test was tried on each of the alert's channels","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":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/run":{"post":{"operationId":"runAlertDigest","summary":"Send a digest now","description":"Sends the digest for the alert's last hour, day or week now and returns each channel's outcome. Works on digest alerts only, and the schedule doesn't change.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's id (feed_...).","name":"id","in":"path"}],"responses":{"200":{"description":"Sent now for the alert's last hour, day or week. The scheduled digest is unaffected","content":{"application/json":{"schema":{"type":"object","properties":{"skipped":{"type":"string","nullable":true,"enum":["already_sent","empty","expired","in_flight"],"description":"Set when nothing was sent, with the reason. The period was already sent, it had nothing to show, an hourly alert's retry window closed before it could send, or another run is sending the same period 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":"Digests exist only for hourly, daily and weekly alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/mute":{"post":{"operationId":"muteAlertAuthors","summary":"Mute authors","description":"Adds authors to the alert's muted list and leaves the rest of its filter alone. Links are handled as in the dashboard, so a post link mutes its author, twitter.com turns into x.com and a Hacker News profile keeps its id. Authors who are already muted are skipped, so retrying is safe. An entry that is not a person, such as a subreddit or a story, fails the request and the error names it.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's 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":"A profile link (x.com/name, linkedin.com/in/name, reddit.com/user/name), post link, handle (@name, u/name), Bluesky DID or display name. Links are stored as the author's profile. A bare name or handle covers every platform."}},"required":["authors"],"description":"The authors to add to the alert's muted list, or take off it."}}}},"responses":{"200":{"description":"Updated alert with the new muted list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"400":{"description":"An entry is not a person, or the alert would have over 200 muted authors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/alerts/{id}/unmute":{"post":{"operationId":"unmuteAlertAuthors","summary":"Unmute authors","description":"Takes authors off the muted list, keeping the rest of the filter. Each entry can be the stored value or any link to the person's profile or posts. Retrying is safe, because authors who aren't muted are skipped.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The alert's id (feed_...).","example":"feed_abc123"},"required":true,"description":"The alert's 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":"A profile link (x.com/name, linkedin.com/in/name, reddit.com/user/name), post link, handle (@name, u/name), Bluesky DID or display name. Links are stored as the author's profile. A bare name or handle covers every platform."}},"required":["authors"],"description":"The authors to add to the alert's muted list, or take off it."}}}},"responses":{"200":{"description":"Updated alert with the new muted list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No alert with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/summary":{"get":{"operationId":"getAnalyticsSummary","summary":"Get summary counts","description":"Returns matched and relevant mentions, unique posts and people, sentiment, buying intent and questions, estimated reach, and the triage status of the matches. Pick the period with `range` (7d, 30d, 90d or 365d up to today) or with `from` and `to`. Days follow `timezone`, UTC by default. `keywordIds` and `platforms` narrow the data, and `compare=true` adds the equally long period just before. Dates are publish dates.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"A preset period up to today, 30d by default. Ignored when you send from or to."},"required":false,"description":"A preset period up to today, 30d by default. Ignored when you send from or to.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date in `timezone`, as YYYY-MM-DD. That day is included."},"required":false,"description":"Start date in `timezone`, as YYYY-MM-DD. That day is included.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today."},"required":false,"description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords."},"required":false,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords.","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":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms."},"required":false,"description":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the equally long period just before as `previous`."},"required":false,"description":"true adds the equally long period just before as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period."},"required":false,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period.","name":"timezone","in":"query"}],"responses":{"200":{"description":"The counts, plus `previous` with compare=true","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSummary"}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/series":{"get":{"operationId":"getAnalyticsSeries","summary":"Mentions over time","description":"Returns matched, relevant and sentiment counts per day or week over the period. You get one total series, or one per platform or keyword with `by`. Pick the period with `range` (7d, 30d, 90d or 365d up to today) or with `from` and `to`. Days follow `timezone`, UTC by default. `keywordIds` and `platforms` narrow the data, and `compare=true` adds the equally long period just before. Dates are publish dates.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"A preset period up to today, 30d by default. Ignored when you send from or to."},"required":false,"description":"A preset period up to today, 30d by default. Ignored when you send from or to.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date in `timezone`, as YYYY-MM-DD. That day is included."},"required":false,"description":"Start date in `timezone`, as YYYY-MM-DD. That day is included.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today."},"required":false,"description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords."},"required":false,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords.","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":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms."},"required":false,"description":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the equally long period just before as `previous`."},"required":false,"description":"true adds the equally long period just before as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period."},"required":false,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["hour","day","week","month"],"description":"The size of each point. hour for periods up to 14 days, day, week (starting Monday) or month. By default days up to 90 days and weeks beyond."},"required":false,"description":"The size of each point. hour for periods up to 14 days, day, week (starting Monday) or month. By default days up to 90 days and weeks beyond.","name":"bucket","in":"query"},{"schema":{"type":"string","enum":["platform","keyword","sentiment"],"description":"Splits the data into a series for each platform, each keyword or each sentiment (positive, neutral, negative, unclassified). By keyword you get the top 20 by matches, with the rest combined as \"other\". Leave it out for one total series."},"required":false,"description":"Splits the data into a series for each platform, each keyword or each sentiment (positive, neutral, negative, unclassified). By keyword you get the top 20 by matches, with the rest combined as \"other\". Leave it out for one total series.","name":"by","in":"query"}],"responses":{"200":{"description":"The series with zeros for empty points, oldest first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSeries"}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/breakdown":{"get":{"operationId":"getAnalyticsBreakdown","summary":"Get a mention breakdown","description":"`by` sets the rows (platform, keyword, sentiment, intent, status, hour as weekday and hour, or person), and each row has matched, relevant and sentiment counts. Pick the period with `range` (7d, 30d, 90d or 365d up to today) or with `from` and `to`. Days follow `timezone`, UTC by default. `keywordIds` and `platforms` narrow the data, and `compare=true` adds the equally long period just before. Dates are publish dates.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"A preset period up to today, 30d by default. Ignored when you send from or to."},"required":false,"description":"A preset period up to today, 30d by default. Ignored when you send from or to.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date in `timezone`, as YYYY-MM-DD. That day is included."},"required":false,"description":"Start date in `timezone`, as YYYY-MM-DD. That day is included.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today."},"required":false,"description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords."},"required":false,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords.","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":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms."},"required":false,"description":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the equally long period just before as `previous`."},"required":false,"description":"true adds the equally long period just before as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period."},"required":false,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["platform","keyword","sentiment","intent","status","hour","person","language"],"description":"How to group the rows. platform, keyword, sentiment (unclassified included), intent (a mention can have several), status (open, ignored, done), hour (weekday and hour in `timezone`), person (the author, without anonymous posts) or language (ISO 639-1, or \"unknown\" when there is none)."},"required":true,"description":"How to group the rows. platform, keyword, sentiment (unclassified included), intent (a mention can have several), status (open, ignored, done), hour (weekday and hour in `timezone`), person (the author, without anonymous posts) or language (ISO 639-1, or \"unknown\" when there is none).","name":"by","in":"query"}],"responses":{"200":{"description":"The rows, the one with the most matches first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsBreakdown"}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/share-of-voice":{"get":{"operationId":"getShareOfVoice","summary":"Get share of voice","description":"Returns each keyword with matches in the period, its counts and its share of all brand and competitor matches. Topic keywords are counted but not part of the split. Pick the period with `range` (7d, 30d, 90d or 365d up to today) or with `from` and `to`. Days follow `timezone`, UTC by default. `keywordIds` and `platforms` narrow the data, and `compare=true` adds the equally long period just before. Dates are publish dates.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"A preset period up to today, 30d by default. Ignored when you send from or to."},"required":false,"description":"A preset period up to today, 30d by default. Ignored when you send from or to.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date in `timezone`, as YYYY-MM-DD. That day is included."},"required":false,"description":"Start date in `timezone`, as YYYY-MM-DD. That day is included.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today."},"required":false,"description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords."},"required":false,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords.","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":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms."},"required":false,"description":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the equally long period just before as `previous`."},"required":false,"description":"true adds the equally long period just before as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period."},"required":false,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period.","name":"timezone","in":"query"}],"responses":{"200":{"description":"The keywords, the one with the most matches first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareOfVoice"}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/analytics/reviews":{"get":{"operationId":"getReviewsReport","summary":"Get review stats","description":"Returns stats on reviews your keywords collect from the App Store, Google Play, Trustpilot and Google Maps. You get the count, average stars, the star distribution, replies and open 1 and 2 star reviews, for the workspace and per review page. Each page has a series of average stars per `bucket`, and the report lists the tags of unhappy reviews. Two keywords matching one review count it once. Pick the period with `range` (7d, 30d, 90d or 365d up to today) or with `from` and `to`. Days follow `timezone`, UTC by default. `keywordIds` and `platforms` narrow the data, and `compare=true` adds the equally long period just before. Dates are publish dates.","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["7d","30d","90d","365d"],"description":"A preset period up to today, 30d by default. Ignored when you send from or to."},"required":false,"description":"A preset period up to today, 30d by default. Ignored when you send from or to.","name":"range","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Start date in `timezone`, as YYYY-MM-DD. That day is included."},"required":false,"description":"Start date in `timezone`, as YYYY-MM-DD. That day is included.","name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today."},"required":false,"description":"End date in `timezone`, as YYYY-MM-DD, included. Defaults to today.","name":"to","in":"query"},{"schema":{"type":"array","nullable":true,"items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords."},"required":false,"description":"Keeps these keyword ids only. Repeat the parameter or separate values with commas. Leave it out for all keywords.","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":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms."},"required":false,"description":"Keeps these platforms only. Repeat the parameter or separate values with commas. Leave it out for all platforms.","name":"platforms","in":"query"},{"schema":{"type":"boolean","description":"true adds the equally long period just before as `previous`."},"required":false,"description":"true adds the equally long period just before as `previous`.","name":"compare","in":"query"},{"schema":{"type":"string","maxLength":64,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period."},"required":false,"description":"The IANA time zone used to split days, such as America/New_York. Defaults to UTC. The zone's offset at the end of the period is used for the whole period.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["day","week"],"description":"The step of each series, day or week. Days by default for periods up to 90 days."},"required":false,"description":"The step of each series, day or week. Days by default for periods up to 90 days.","name":"bucket","in":"query"}],"responses":{"200":{"description":"The report, plus `previous` with compare=true","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewsReport"}}}},"400":{"description":"The query is not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}":{"get":{"operationId":"getChannel","summary":"Get a channel","description":"Returns one channel with its settings, account events and delivery stats. A webhook's signing secret is never shown here.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The channel's id (dest_...).","example":"dest_abc123"},"required":true,"description":"The channel's id (dest_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The requested channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No channel with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateChannel","summary":"Update a channel","description":"Changes a channel's label and account events, and a webhook's URL and headers. `headers` and `events` replace the old values.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The channel's id (dest_...).","example":"dest_abc123"},"required":true,"description":"The channel's 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":"For webhook channels only."},"headers":{"type":"object","additionalProperties":{"type":"string","maxLength":1024},"description":"For webhook channels only. Sets the full new set of headers."},"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":"Account events are keyword.capped (hit the monthly cap, stops matching), keyword.paused_for_balance (paused when the balance ran out), keyword.resumed (matching again, cause in reason), wallet.low (effective balance down to 20% of the last credit, once per credit), wallet.paused (every keyword paused) and wallet.resumed (a credit restarted them). Attention events go out once when an item opens (GET /v1/attention). They are mention.spike (far more mentions than usual in the last hour), sentiment.negative_spike (24-hour negative share jumped), keyword.noisy (scored matches mostly noise) and channel.failing (recent sends all failed)."},"maxItems":10,"description":"Sets the full list of account events the channel gets. A webhook can take any of them. Slack, email and Telegram channels take only the attention events (mention.spike, sentiment.negative_spike, keyword.noisy, channel.failing). An empty list turns them all off."}},"description":"Fields you leave out stay as they are."}}}},"responses":{"200":{"description":"The channel after the change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"400":{"description":"The channel kind doesn't support one of the events. Slack, email and Telegram accept attention events only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No channel with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteChannel","summary":"Delete a channel","description":"Deletes the channel and takes it off its alerts. Queued sends to it are cancelled. The alerts stay.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The channel's id (dest_...).","example":"dest_abc123"},"required":true,"description":"The channel's id (dest_...).","name":"id","in":"path"}],"responses":{"204":{"description":"Done"},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No channel with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}/test":{"post":{"operationId":"testChannel","summary":"Test a channel","description":"Sends a test message to the channel now and returns the outcome. Webhooks receive the event `test`.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The channel's id (dest_...).","example":"dest_abc123"},"required":true,"description":"The channel's id (dest_...).","name":"id","in":"path"}],"responses":{"200":{"description":"Test attempt made. 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":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No channel with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","summary":"Rotate the signing secret","description":"Gives a webhook channel a new signing secret, shown only in this response. The old secret stops working at once.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The channel's id (dest_...).","example":"dest_abc123"},"required":true,"description":"The channel's id (dest_...).","name":"id","in":"path"}],"responses":{"200":{"description":"The new signing secret, shown only now. The old one stops working right away.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No webhook channel with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels/{id}/deliveries":{"get":{"operationId":"listChannelDeliveries","summary":"List a channel's deliveries","description":"Lists the mentions, digests and account events sent to the channel, latest first, with status and the last error. `limit` defaults to 50, up to 200.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"description":"The channel's id (dest_...).","example":"dest_abc123"},"required":true,"description":"The channel's id (dest_...).","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Everything sent to the channel, latest first, including instant mentions and digests, with status and the last error","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The delivery's id (dlv_...), which is also the webhook payload's id."},"kind":{"type":"string","enum":["mention","digest","event"],"description":"mention is a delivery from an instant alert. digest is a scheduled summary. event is an account event the channel subscribed to."},"event":{"type":"string","description":"The event name in the payload. For an alert it is mention.matched unless the alert set its own, or digest for a summary. For an account event it is that event's name."},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"error":{"type":"string","nullable":true,"description":"The latest error, if any."},"sentAt":{"type":"string","nullable":true,"description":"UTC time in ISO 8601."},"createdAt":{"type":"string","description":"UTC time in ISO 8601."},"alert":{"type":"object","properties":{"name":{"type":"string","nullable":true}},"required":["name"],"description":"Name of the sending alert, kept because alerts can be deleted. Null name for account events, which no alert sends."},"mention":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"url":{"type":"string"},"text":{"type":"string"}},"required":["id","url","text"],"description":"Set on mention deliveries. Holds the post, with text shortened to 160 characters."}},"required":["id","kind","event","status","attempts","error","sentAt","createdAt","alert","mention"]}}},"required":["data"]}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No channel with this id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/channels":{"get":{"operationId":"listChannels","summary":"List channels","description":"Lists the workspace's channels with their settings and delivery stats.","tags":["Alerts"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"All of the workspace's channels","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":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createChannel","summary":"Create a channel","description":"Creates a webhook (the default), email or Slack channel. Slack needs a connected workspace, otherwise 409. Telegram chats are connected in the dashboard. A webhook's signing secret appears only in this response.","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":"Created. For a webhook this is the only time the signing secret is shown.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"400":{"description":"The channel kind doesn't support one of the events. Slack, email and Telegram accept attention events only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"The API key is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"This workspace has not connected Slack","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"x-rumoro-errors":[{"code":"unauthorized","status":401,"source":"user","retryable":false,"description":"The credential is missing or does not belong 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 works but is not allowed to do this."},{"code":"read_only_key","status":403,"source":"user","retryable":false,"description":"A read-only key called an endpoint that writes.","fix":"Create a key with write scope."},{"code":"validation_error","status":400,"source":"user","retryable":false,"description":"The body or query is not valid. The message says which field."},{"code":"not_found","status":404,"source":"user","retryable":false,"description":"Your workspace has nothing with this id. An id from another workspace also returns 404, never 403."},{"code":"invalid_cursor","status":400,"source":"user","retryable":false,"description":"The cursor could not be read, or was issued for another sort. Start again from the first page."},{"code":"payload_too_large","status":413,"source":"user","retryable":false,"description":"The body exceeds the endpoint limit (128 KiB for JSON). A 409 with this code: a delivery whose payload was too large cannot be retried or replayed."},{"code":"rate_limited","status":429,"source":"user","retryable":true,"description":"The workspace sent over 600 requests in a minute across all its keys and tokens, or reached an endpoint's own limit. Retry-After and error.retryAfterSeconds tell you when to try again.","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":"This group already has the term. Each group can hold a term once, and other groups can hold it too."},{"code":"insufficient_balance","status":402,"source":"user","retryable":false,"description":"The balance cannot pay for 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 workspace already runs 500 keywords, or has 500 that are not deleted."},{"code":"billing_not_configured","status":503,"source":"system","retryable":false,"description":"No payment provider is set up on this deployment."},{"code":"unknown_channel","status":400,"source":"user","retryable":false,"description":"An alert named a channel id that is not in this workspace."},{"code":"not_a_digest","status":400,"source":"user","retryable":false,"description":"An action for digests was used on an instant alert."},{"code":"hourly_email_unsupported","status":400,"source":"user","retryable":false,"description":"An hourly alert got an email channel, which could mean 24 emails a day. Use Slack, Telegram or a webhook, or send a daily digest by email."},{"code":"slack_not_connected","status":409,"source":"user","retryable":false,"description":"Slack must be connected in Settings first. Returned as 404 by the Slack connection endpoints and 409 elsewhere."},{"code":"slack_not_configured","status":503,"source":"system","retryable":false,"description":"No Slack app is set up on this deployment."},{"code":"telegram_not_configured","status":503,"source":"system","retryable":false,"description":"No Telegram bot is set up on this deployment."},{"code":"email_not_configured","status":503,"source":"system","retryable":false,"description":"This deployment has no email sender set up, so email destinations cannot be used."},{"code":"invalid_assignee","status":400,"source":"user","retryable":false,"description":"The assignee is not in the workspace."},{"code":"classification_pending","status":409,"source":"user","retryable":true,"description":"Relevance or sentiment feedback was sent before the classifier scored the mention."},{"code":"already_member","status":409,"source":"user","retryable":false,"description":"The invited address already belongs to a member."},{"code":"last_owner","status":409,"source":"user","retryable":false,"description":"The workspace would have no owner left after this removal."},{"code":"duplicate_segment","status":409,"source":"user","retryable":false,"description":"Another segment in the workspace has this name."},{"code":"duplicate_view","status":409,"source":"user","retryable":false,"description":"Another view in the workspace has this name."},{"code":"duplicate_group","status":409,"source":"user","retryable":false,"description":"Another group in the workspace has this name or externalId."},{"code":"default_group","status":409,"source":"user","retryable":false,"description":"The default group cannot be deleted. It holds keywords created without a group."},{"code":"default_group_context","status":400,"source":"user","retryable":false,"description":"The default group uses the workspace's company profile, which you change with PATCH /v1/company. Only other groups can have their own description."},{"code":"invalid_signature","status":401,"source":"user","retryable":false,"description":"An incoming webhook had no valid signature."},{"code":"invalid_token","status":400,"source":"user","retryable":false,"description":"A signed link (unsubscribe, confirmation, preferences) was tampered with or is malformed."},{"code":"upstream_unavailable","status":502,"source":"platform","retryable":true,"description":"An outside service such as Slack or Polar failed during the request. Retry with increasing waits."},{"code":"internal_error","status":500,"source":"system","retryable":false,"description":"Something failed on our side; 502 when Telegram failed a bot lookup. The response carries a requestId; quote it to support."},{"code":"unsupported_media_type","status":415,"source":"user","retryable":false,"description":"A body was sent without Content-Type: application/json."},{"code":"request_timeout","status":408,"source":"user","retryable":true,"description":"The body did not arrive within 5 seconds."},{"code":"key_limit","status":409,"source":"user","retryable":false,"description":"The workspace already has 100 active keys. Revoke one first."},{"code":"conflict","status":409,"source":"user","retryable":false,"description":"A resource with these values already exists."},{"code":"no_billing_owner","status":404,"source":"user","retryable":false,"description":"There is no owner to bill in this workspace yet."},{"code":"rule_disabled","status":409,"source":"user","retryable":false,"description":"The rule is turned off. Enable it before a test or a run."},{"code":"no_channels","status":409,"source":"user","retryable":false,"description":"The rule has no destination to test."},{"code":"channel_disabled","status":409,"source":"user","retryable":false,"description":"A destination is turned off. Enable it first."},{"code":"no_recipients","status":409,"source":"user","retryable":false,"description":"An email destination needs a recipient before it can be turned on."},{"code":"recipient_suppressed","status":409,"source":"user","retryable":false,"description":"The address bounced or complained, so no more email goes to it."},{"code":"confirmation_rate_limited","status":429,"source":"user","retryable":true,"description":"Too many confirmation emails: wait a minute; at most three per address a day and twenty per workspace an hour."},{"code":"confirmation_requires_resend","status":409,"source":"user","retryable":false,"description":"A confirmation email is sent again with a resend, not a delivery retry."},{"code":"email_test_rate_limited","status":429,"source":"user","retryable":true,"description":"More than five email tests on this destination this hour."},{"code":"email_hourly_limit","status":409,"source":"user","retryable":false,"description":"The destination's hourly email limit is reached; the mention waits for the next daily digest."},{"code":"email_idempotency_expired","status":409,"source":"user","retryable":false,"description":"The email's safe retry window passed. Check its receipts before an explicit replay, which may send it twice."},{"code":"email_transport_unavailable","status":503,"source":"system","retryable":false,"description":"Email sending is not set up for this delivery on this deployment."},{"code":"delivery_not_configured","status":503,"source":"system","retryable":false,"description":"Destinations that need a stored secret are not set up on this deployment."},{"code":"delivery_key_unavailable","status":503,"source":"system","retryable":false,"description":"A destination's stored secret cannot be read on this deployment."},{"code":"not_retryable","status":409,"source":"user","retryable":false,"description":"Only failed or blocked deliveries can be retried."},{"code":"not_replayable","status":409,"source":"user","retryable":false,"description":"A delivery can be replayed once it has finished."},{"code":"digest_has_replay","status":409,"source":"user","retryable":false,"description":"This digest delivery has a newer replay. Recover that one."},{"code":"digest_retry_expired","status":409,"source":"user","retryable":false,"description":"The digest's six-hour retry window passed. Replay it instead."},{"code":"delivery_request_incomplete","status":500,"source":"system","retryable":true,"description":"The saved outcome of a test could not be read. Read it again; don't send a new test."},{"code":"request_conflict","status":409,"source":"user","retryable":false,"description":"This requestId was already used for another request. Retry the original, or use a new id."},{"code":"stale_version","status":409,"source":"user","retryable":false,"description":"The resource changed since you read it. Read it again before saving."},{"code":"version_conflict","status":409,"source":"user","retryable":true,"description":"The webhook's managed rules changed at the same time. Read it again and retry."},{"code":"already_classified","status":409,"source":"user","retryable":false,"description":"The mention is already scored; there is nothing to retry."},{"code":"keyword_inactive","status":409,"source":"user","retryable":false,"description":"The mention's keyword is paused. Resume it before retrying the score."},{"code":"source_unavailable","status":502,"source":"platform","retryable":true,"description":"Live search: the platform didn't answer (503 when it is rate limiting us)."},{"code":"source_timeout","status":504,"source":"platform","retryable":true,"description":"Live search: the platform didn't answer in time."},{"code":"invalid_host","status":403,"source":"user","retryable":false,"description":"MCP: the request's Host is not this server's."},{"code":"invalid_origin","status":403,"source":"user","retryable":false,"description":"MCP: the request's Origin is not allowed."},{"code":"database_unavailable","status":503,"source":"system","retryable":true,"description":"A temporary database problem. Retry with backoff."},{"code":"database_not_ready","status":503,"source":"system","retryable":false,"description":"The deployment's database needs maintenance; retrying won't help until it is done."},{"code":"not_configured","status":503,"source":"system","retryable":false,"description":"This deployment has no database configured."}],"servers":[{"url":"https://api.rumoro.dev"}]}