{"openapi":"3.0.3","info":{"title":"RedReplier Public API","version":"1.0.0","description":"REST API for monitoring Reddit, X (Twitter), Bluesky, Hacker News and Facebook for conversations that match your keywords. Register the sites you want monitored, manage the keyword set, pull scored mentions with their AI reply suggestions, mark each one approved or rejected, and configure email alert cadence. Authenticate with `Authorization: Bearer <api-key>`; create a key under API Tokens in the RedReplier dashboard. All timestamps are ISO 8601 UTC. Every response carries the RFC 9331 rate-limit fields so a client can pace itself instead of discovering the limit through a 429: `RateLimit-Policy`, `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, the seconds until the window rolls over. A 429 adds `Retry-After` with the same number of seconds. Limits are counted per API key."},"servers":[{"url":"https://ai.redreplier.com/ai-app/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Websites","description":"Sites being monitored"},{"name":"Keywords","description":"Keyword set and its billing impact"},{"name":"Mentions","description":"Matched conversations and their review state"},{"name":"Alerts","description":"Email digest settings"}],"paths":{"/websites":{"get":{"operationId":"listWebsites","summary":"List monitored websites","description":"Every website in the account, each with its keyword set.","tags":["Websites"],"responses":{"200":{"description":"Monitored websites","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteListResponse"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createWebsite","summary":"Start monitoring a website","description":"Adds a website and, unless you pass `description`, scrapes the URL to write one so mention scoring knows what the product does. That scrape uses one AI generation from the plan quota; if it fails or the quota is exhausted the website is still created with `description: null`, so set one with PATCH or `/websites/analyze-description`. Keywords supplied here are added immediately; those beyond the plan allowance land as `PENDING`.","tags":["Websites"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebsiteRequest"}}}},"responses":{"201":{"description":"Website created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Website"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/websites/{id}":{"get":{"operationId":"getWebsite","summary":"Get one monitored website","tags":["Websites"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Website id"}],"responses":{"200":{"description":"Website","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Website"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateWebsite","summary":"Rename a website or rewrite its description","description":"The description feeds mention scoring, so sharpening it changes which conversations rank as relevant.","tags":["Websites"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Website id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebsiteRequest"}}}},"responses":{"200":{"description":"Website updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Website"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteWebsite","summary":"Stop monitoring a website","description":"Removes the website and its keywords. Mentions already collected are dropped.","tags":["Websites"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Website id"}],"responses":{"200":{"description":"Website deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/websites/analyze-description":{"post":{"operationId":"analyzeWebsiteDescription","summary":"Draft a product description from a URL","description":"Scrapes the URL and returns a description suitable for `POST /websites`, without creating anything. Use it to review the wording before committing.","tags":["Websites"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeWebsiteRequest"}}}},"responses":{"201":{"description":"Generated description","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeWebsiteResponse"}}}},"400":{"description":"URL could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/websites/{id}/keywords":{"post":{"operationId":"addKeywords","summary":"Add keywords to a website","description":"Keywords that fit the plan allowance become `ACTIVE` at once; the rest are stored as `PENDING` until you activate them, which may require an upgrade.","tags":["Keywords"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Website id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddKeywordsRequest"}}}},"responses":{"201":{"description":"Website with its updated keyword set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Website"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Website not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/{id}":{"patch":{"operationId":"editKeyword","summary":"Change a keyword’s text","description":"Edits are unlimited and keep any paid slot the keyword already holds, so fixing a typo never drops it into pending payment.","tags":["Keywords"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Keyword id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditKeywordRequest"}}}},"responses":{"200":{"description":"Keyword updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteKeyword","summary":"Delete a keyword","description":"Permanent: the keyword and every mention it produced are deleted. Use disable to stop monitoring while keeping the mentions.","tags":["Keywords"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Keyword id"}],"responses":{"200":{"description":"Keyword deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedResponse"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/{id}/disable":{"post":{"operationId":"disableKeyword","summary":"Stop monitoring a keyword","description":"Frees the paid slot without deleting the keyword.","tags":["Keywords"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Keyword id"}],"responses":{"201":{"description":"Keyword disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/{id}/enable":{"post":{"operationId":"enableKeyword","summary":"Resume monitoring a keyword","description":"Takes a paid slot; lands as `PENDING` when the plan has none free. Never charges: upgrade the plan in the RedReplier app to activate it.","tags":["Keywords"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Keyword id"}],"responses":{"201":{"description":"Keyword enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Keyword not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/activate-pending":{"post":{"operationId":"activatePendingKeywords","summary":"Activate pending keywords that fit the plan","description":"Moves `PENDING` keywords to `ACTIVE` up to the free slots on the current plan. Never charges: keywords beyond the plan stay `PENDING` until the plan is upgraded in the RedReplier app.","tags":["Keywords"],"responses":{"201":{"description":"Websites with their updated keyword sets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebsiteListResponse"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/activate-pending/preview":{"get":{"operationId":"previewActivatePendingKeywords","summary":"Price activating every pending keyword","description":"What upgrading the plan to cover every pending keyword would cost, without charging anything.","tags":["Keywords"],"responses":{"200":{"description":"Billing preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeywordBillingPreview"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/billing-preview":{"get":{"operationId":"previewKeywordBilling","summary":"Price an arbitrary keyword count","description":"Which plan a given number of active keywords lands on, and what changing to it costs now.","tags":["Keywords"],"parameters":[{"name":"desiredKeywordCount","in":"query","required":true,"schema":{"type":"integer","minimum":0},"description":"Active keyword count to price."}],"responses":{"200":{"description":"Billing preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeywordBillingPreview"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/keywords/change-usage":{"get":{"operationId":"getKeywordChangeUsage","summary":"Get the keyword-change allowance for this cycle","tags":["Keywords"],"responses":{"200":{"description":"Allowance and usage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaUsage"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mentions":{"get":{"operationId":"listMentions","summary":"List matched conversations","description":"Scored mentions across Reddit, X, Bluesky, Hacker News and Facebook, each with the matched keyword, a relevance score with its reasoning, and an AI-drafted reply.","tags":["Mentions"],"parameters":[{"name":"websiteId","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Restrict to mentions for one monitored website."},{"name":"statuses","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/MentionStatus"}},"style":"form","explode":true,"description":"Review states to include. Repeat the key for several, e.g. `?statuses=NEW&statuses=APPROVED`."},{"name":"scoreBuckets","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/RelevanceBucket"}},"style":"form","explode":true,"description":"Relevance bands to include."},{"name":"includeLowRelevance","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include mentions the scorer judged unlikely to be worth a reply. Excluded by default."},{"name":"keywords","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true,"description":"Only mentions matched by these keywords."},{"name":"sources","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/MentionSource"}},"style":"form","explode":true,"description":"Platforms to include."},{"name":"sort","in":"query","required":false,"schema":{"$ref":"#/components/schemas/MentionSort"},"description":"Order results by relevance score or publish time."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Only mentions published at or after this time (ISO 8601)."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Only mentions published at or before this time (ISO 8601)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"description":"Maximum mentions to return."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0},"description":"Mentions to skip before returning results."}],"responses":{"200":{"description":"Mentions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MentionListResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mentions/count":{"get":{"operationId":"countMentions","summary":"Count matched conversations","description":"Row count for the same filters as /mentions, without fetching the rows.","tags":["Mentions"],"parameters":[{"name":"websiteId","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Restrict to mentions for one monitored website."},{"name":"statuses","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/MentionStatus"}},"style":"form","explode":true,"description":"Review states to include. Repeat the key for several, e.g. `?statuses=NEW&statuses=APPROVED`."},{"name":"scoreBuckets","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/RelevanceBucket"}},"style":"form","explode":true,"description":"Relevance bands to include."},{"name":"includeLowRelevance","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"Include mentions the scorer judged unlikely to be worth a reply. Excluded by default."},{"name":"keywords","in":"query","required":false,"schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true,"description":"Only mentions matched by these keywords."},{"name":"sources","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/MentionSource"}},"style":"form","explode":true,"description":"Platforms to include."},{"name":"sort","in":"query","required":false,"schema":{"$ref":"#/components/schemas/MentionSort"},"description":"Order results by relevance score or publish time."},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Only mentions published at or after this time (ISO 8601)."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Only mentions published at or before this time (ISO 8601)."}],"responses":{"200":{"description":"Mention count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MentionCountResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mentions/{id}/status":{"patch":{"operationId":"updateMentionStatus","summary":"Approve or reject a mention","tags":["Mentions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Mention id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMentionStatusRequest"}}}},"responses":{"200":{"description":"Mention updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mention"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Mention not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mentions/{id}/explain":{"post":{"operationId":"explainMention","summary":"Explain why a mention scored the way it did","description":"Re-runs scoring and fills in `relevanceReason`. Returns `null` when the mention is not visible to this account.","tags":["Mentions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Mention id"}],"responses":{"201":{"description":"Mention with its scoring rationale","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NullableMention"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Mention not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/alert-settings":{"get":{"operationId":"getAlertSettings","summary":"Get email alert settings","description":"Current cadence plus the cadences the plan allows. `cadenceMinutes` is never reported below the plan floor.","tags":["Alerts"],"responses":{"200":{"description":"Alert settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSettings"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"updateAlertSettings","summary":"Turn email alerts on or off and set the cadence","description":"A cadence faster than the plan allows is clamped to the plan floor.","tags":["Alerts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertSettingsRequest"}}}},"responses":{"200":{"description":"Alert settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSettings"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A RedReplier API token, sent as `Authorization: Bearer <api-key>`. Create one under API Tokens in the dashboard."}},"schemas":{"Error":{"type":"object","properties":{"statusCode":{"type":"integer"},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message"]},"DeletedResponse":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"]},"KeywordStatus":{"type":"string","enum":["PENDING","ACTIVE","DISABLED","SUSPENDED"],"description":"`PENDING` keywords are stored but not monitored until a paid slot covers them."},"MentionStatus":{"type":"string","enum":["NEW","REJECTED","APPROVED"]},"MentionSource":{"type":"string","enum":["REDDIT_POST","REDDIT_COMMENT","TWITTER","BLUESKY","HACKERNEWS","FACEBOOK","FACEBOOK_GROUP"]},"MentionSort":{"type":"string","enum":["RELEVANCE","RECENT"]},"RelevanceBucket":{"type":"string","enum":["VERY_LOW","LOW","MEDIUM","HIGH","VERY_HIGH"]},"Keyword":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"websiteId":{"type":"string","format":"uuid"},"value":{"type":"string"},"status":{"$ref":"#/components/schemas/KeywordStatus"},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","websiteId","value","status"]},"Website":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountGroupId":{"type":"string","format":"uuid"},"domain":{"type":"string"},"url":{"type":"string","format":"uri"},"name":{"type":"string","nullable":true},"description":{"type":"string","nullable":true,"description":"Feeds mention scoring."},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true},"keywords":{"type":"array","items":{"$ref":"#/components/schemas/Keyword"}}},"required":["id","domain","url","keywords"]},"WebsiteListResponse":{"type":"object","properties":{"websites":{"type":"array","items":{"$ref":"#/components/schemas/Website"}}},"required":["websites"]},"CreateWebsiteRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"name":{"type":"string"},"keywords":{"type":"array","items":{"type":"string","maxLength":255}},"description":{"type":"string","maxLength":5000,"description":"Set it yourself to skip scraping and AI generation."}}},"UpdateWebsiteRequest":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","maxLength":5000}}},"AnalyzeWebsiteRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"}}},"AnalyzeWebsiteResponse":{"type":"object","properties":{"description":{"type":"string"}},"required":["description"]},"AddKeywordsRequest":{"type":"object","required":["keywords"],"properties":{"keywords":{"type":"array","minItems":1,"items":{"type":"string","maxLength":255}}}},"EditKeywordRequest":{"type":"object","required":["value"],"properties":{"value":{"type":"string","maxLength":255}}},"KeywordBillingPreview":{"type":"object","properties":{"currentPlanName":{"type":"string","nullable":true},"currentMonthlyPrice":{"type":"number"},"targetPlanName":{"type":"string","nullable":true},"targetMonthlyPrice":{"type":"number"},"targetKeywords":{"type":"integer","description":"Active keywords the target plan allows."},"immediateCharge":{"type":"number","description":"Prorated amount charged now, 0 unless this is an upgrade."},"isUpgrade":{"type":"boolean"},"isDowngrade":{"type":"boolean"},"requiresImmediatePayment":{"type":"boolean"}}},"QuotaUsage":{"type":"object","properties":{"limit":{"type":"integer","description":"-1 when unlimited."},"used":{"type":"integer"},"remaining":{"type":"integer","description":"-1 when unlimited."},"unlimited":{"type":"boolean"}}},"Mention":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"websiteId":{"type":"string","format":"uuid"},"source":{"$ref":"#/components/schemas/MentionSource"},"keyword":{"type":"string","nullable":true,"description":"The monitored keyword this conversation matched."},"title":{"type":"string","nullable":true},"contentText":{"type":"string","nullable":true},"url":{"type":"string","format":"uri"},"author":{"type":"string","nullable":true},"subreddit":{"type":"string","nullable":true,"description":"Reddit only."},"status":{"$ref":"#/components/schemas/MentionStatus"},"relevanceScore":{"type":"number","nullable":true,"description":"Higher means more likely to be worth a reply."},"relevanceReason":{"type":"string","nullable":true,"description":"Why the scorer landed on that number."},"aiReplySuggestion":{"type":"string","nullable":true,"description":"Draft reply for a human to review before posting."},"tags":{"type":"array","items":{"type":"string"}},"publishedAt":{"type":"string","format":"date-time","nullable":true},"ingestedAt":{"type":"string","format":"date-time","nullable":true},"reviewedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"updatedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","websiteId","source","url","status"]},"NullableMention":{"allOf":[{"$ref":"#/components/schemas/Mention"}],"nullable":true},"MentionListResponse":{"type":"object","properties":{"mentions":{"type":"array","items":{"$ref":"#/components/schemas/Mention"}},"total":{"type":"integer","description":"Mentions matching the filters, before paging."},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["mentions","total","limit","offset"]},"MentionCountResponse":{"type":"object","properties":{"total":{"type":"integer"}},"required":["total"]},"UpdateMentionStatusRequest":{"type":"object","required":["status"],"properties":{"status":{"$ref":"#/components/schemas/MentionStatus"}}},"AlertSettings":{"type":"object","properties":{"enabled":{"type":"boolean"},"cadenceMinutes":{"type":"integer"},"minIntervalMinutes":{"type":"integer","description":"Fastest cadence this plan allows."},"availableCadences":{"type":"array","items":{"type":"integer"},"description":"Selectable cadences, in minutes."}},"required":["enabled","cadenceMinutes"]},"UpdateAlertSettingsRequest":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"},"cadenceMinutes":{"type":"integer","description":"Clamped up to the plan floor when it is too fast."}}}}}}