{"openapi":"3.1.0","info":{"title":"TokTik Developer API","version":"v1","description":"Versioned public API for persisted LIVE intelligence. All bearer-key routes are workspace-scoped."},"servers":[{"url":"https://api.toktikhq.com"}],"x-realtime-websocket":{"path":"/v1/live/stream","authentication":"Short-lived HS256 JWT in Authorization or Sec-WebSocket-Protocol; never the URL","clientMessages":["subscribe","unsubscribe"],"serverMessages":["hello","status","event","error"],"eventTypes":["chat","gift","member","like","social","roomUser","control","envelope","goodyBag","subscribe","linkMicBattle","linkMicArmies","hourlyRank","liveStart","unknown"],"backpressure":"Per-socket bounded queue: lossy like/member/roomUser/unknown frames may drop; critical overflow closes only that socket with 1013"},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key"}},"schemas":{"Error":{"type":"object","required":["code","message","retryable"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code, e.g. insufficient_scope, module_not_entitled."},"message":{"type":"string"},"requestId":{"type":"string"},"retryable":{"type":"boolean","description":"True when retrying the same request may succeed (rate limits, transient upstream)."}}},"Provenance":{"type":"object","required":["observedAt","freshness","source","coverageStatus","methodologyVersion"],"properties":{"observedAt":{"type":"string","format":"date-time","description":"RFC 3339 instant of the newest observation in this response."},"freshness":{"type":"string","enum":["near_realtime","historical","stale"]},"source":{"type":"string","description":"Collector or persisted dataset that produced the observation."},"coverageStatus":{"type":"string","enum":["observed","partial","not-covered","not-offered","stale"]},"methodologyVersion":{"type":"string"}}},"CreatorProfileHistoryPoint":{"type":"object","properties":{"capturedAt":{"type":"string","format":"date-time"},"followerCount":{"type":["integer","null"]},"followingCount":{"type":["integer","null"]},"awemeCount":{"type":["integer","null"]},"totalFavorited":{"type":["integer","null"]},"favoritingCount":{"type":["integer","null"]},"region":{"type":["string","null"]},"displayName":{"type":["string","null"]},"verified":{"type":["boolean","null"]}}},"CreatorProfileData":{"type":"object","required":["tiktokUserId","uniqueId","firstSeenAt","lastRefreshedAt","history"],"properties":{"tiktokUserId":{"type":"string","description":"Stable numeric TikTok user id."},"uniqueId":{"type":"string","description":"Current handle (may be recycled across accounts over time)."},"secUid":{"type":["string","null"]},"displayName":{"type":["string","null"]},"region":{"type":["string","null"]},"language":{"type":["string","null"]},"signature":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"followerCount":{"type":["integer","null"]},"followingCount":{"type":["integer","null"]},"awemeCount":{"type":["integer","null"]},"totalFavorited":{"type":["integer","null"]},"favoritingCount":{"type":["integer","null"]},"verified":{"type":["boolean","null"]},"customVerify":{"type":["string","null"]},"enterpriseVerifyReason":{"type":["string","null"]},"instagramId":{"type":["string","null"]},"youtubeChannelId":{"type":["string","null"]},"twitterId":{"type":["string","null"]},"firstSeenAt":{"type":"string","format":"date-time"},"lastRefreshedAt":{"type":"string","format":"date-time"},"history":{"type":"array","items":{"$ref":"#/components/schemas/CreatorProfileHistoryPoint"}}}},"CreatorSearchResult":{"type":"object","properties":{"tiktokUserId":{"type":"string"},"uniqueId":{"type":"string"},"displayName":{"type":["string","null"]},"region":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"followerCount":{"type":["integer","null"]},"verified":{"type":["boolean","null"]},"isLive":{"type":"boolean"},"masked":{"type":"boolean"},"unmaskTier":{"type":["string","null"]}}},"CreatorProfileChange":{"type":"object","properties":{"field":{"type":"string","description":"Tracked field name, e.g. uniqueId, displayName, avatarUrl."},"oldValue":{"type":["string","null"]},"newValue":{"type":["string","null"]},"observedAt":{"type":"string","format":"date-time"},"source":{"type":"string"}}},"FollowListEntry":{"type":"object","properties":{"tiktokUserId":{"type":"string"},"uniqueId":{"type":"string"},"secUid":{"type":["string","null"]},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"region":{"type":["string","null"]},"signature":{"type":["string","null"]},"followerCount":{"type":["integer","null"]},"followingCount":{"type":["integer","null"]},"awemeCount":{"type":["integer","null"]},"verified":{"type":["boolean","null"]},"firstSeenAt":{"type":"string","format":"date-time"},"lastRefreshedAt":{"type":"string","format":"date-time"}}},"FollowListData":{"type":"object","required":["tiktokUserId","uniqueId","direction","entries","nextCursor","hasMore","storedCount","isPrivate"],"properties":{"tiktokUserId":{"type":"string"},"uniqueId":{"type":"string"},"direction":{"type":"string","enum":["following","follower"]},"entries":{"type":"array","items":{"$ref":"#/components/schemas/FollowListEntry"}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"},"totalReported":{"type":["integer","null"]},"storedCount":{"type":"integer"},"isPrivate":{"type":"boolean"}}},"VideoMetricHistoryPoint":{"type":"object","properties":{"capturedAt":{"type":"string","format":"date-time"},"playCount":{"type":["integer","null"]},"diggCount":{"type":["integer","null"]},"commentCount":{"type":["integer","null"]},"shareCount":{"type":["integer","null"]},"collectCount":{"type":["integer","null"]}}},"VideoData":{"type":"object","required":["videoId","tiktokUserId","uniqueId"],"properties":{"videoId":{"type":"string"},"tiktokUserId":{"type":"string"},"uniqueId":{"type":"string"},"description":{"type":["string","null"]},"createTime":{"type":["string","null"],"format":"date-time"},"coverUrl":{"type":["string","null"]},"durationSeconds":{"type":["number","null"]},"playCount":{"type":["integer","null"]},"diggCount":{"type":["integer","null"]},"commentCount":{"type":["integer","null"]},"shareCount":{"type":["integer","null"]},"collectCount":{"type":["integer","null"]},"firstSeenAt":{"type":"string","format":"date-time"},"lastRefreshedAt":{"type":"string","format":"date-time"}}},"VideoWithHistory":{"allOf":[{"$ref":"#/components/schemas/VideoData"},{"type":"object","required":["history"],"properties":{"history":{"type":"array","items":{"$ref":"#/components/schemas/VideoMetricHistoryPoint"}}}}]},"VideoCommentData":{"type":"object","properties":{"commentId":{"type":"string"},"videoId":{"type":"string"},"parentCommentId":{"type":["string","null"]},"authorUserId":{"type":["string","null"]},"authorSecUid":{"type":["string","null"]},"authorUniqueId":{"type":["string","null"]},"authorNickname":{"type":["string","null"]},"authorAvatarUrl":{"type":["string","null"]},"text":{"type":"string"},"likeCount":{"type":["integer","null"]},"replyCount":{"type":["integer","null"]},"commentedAt":{"type":["string","null"],"format":"date-time"},"language":{"type":["string","null"]},"pinnedByAuthor":{"type":"boolean"},"likedByAuthor":{"type":"boolean"},"firstSeenAt":{"type":"string","format":"date-time"},"lastRefreshedAt":{"type":"string","format":"date-time"}}},"Story":{"type":"object","required":["itemId","kind","viewed","isSubscriberOnly"],"properties":{"itemId":{"type":"string","description":"Stable story/aweme id (string — exceeds 2^53)."},"kind":{"type":"string","enum":["photo","video"]},"imageUrl":{"type":["string","null"]},"videoUrl":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"viewed":{"type":"boolean"},"isSubscriberOnly":{"type":"boolean"}}},"CreatorAnalysisSubject":{"type":"object","properties":{"tiktokUserId":{"type":"string"},"uniqueId":{"type":"string"},"displayName":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"region":{"type":["string","null"]},"verified":{"type":["boolean","null"]},"followerCount":{"type":["integer","null"]},"followingCount":{"type":["integer","null"]},"awemeCount":{"type":["integer","null"]},"totalFavorited":{"type":["integer","null"]},"firstSeenAt":{"type":"string","format":"date-time"},"lastRefreshedAt":{"type":"string","format":"date-time"}}},"CreatorAnalysisSample":{"type":"object","properties":{"videosAnalyzed":{"type":"integer"},"oldestVideoAt":{"type":["string","null"],"format":"date-time"},"newestVideoAt":{"type":["string","null"],"format":"date-time"},"spanDays":{"type":["integer","null"]},"shareOfCatalog":{"type":["number","null"]}}},"CreatorAnalysisEngagement":{"type":"object","properties":{"totalPlays":{"type":"number"},"totalLikes":{"type":"number"},"totalComments":{"type":"number"},"totalShares":{"type":"number"},"avgPlays":{"type":"number"},"medianPlays":{"type":"number"},"avgLikes":{"type":"number"},"avgComments":{"type":"number"},"avgShares":{"type":"number"},"engagementRate":{"type":["number","null"]},"likeRate":{"type":["number","null"]},"commentRate":{"type":["number","null"]},"shareRate":{"type":["number","null"]},"viewsPerFollower":{"type":["number","null"]}}},"CreatorAnalysisCadence":{"type":"object","properties":{"postsPerWeek":{"type":["number","null"]},"avgDaysBetweenPosts":{"type":["number","null"]},"longestGapDays":{"type":["number","null"]},"busiestWeekday":{"type":["integer","null"]},"postsByWeekday":{"type":"array","items":{"type":"integer"}}}},"CreatorAnalysisVideo":{"type":"object","properties":{"videoId":{"type":"string"},"description":{"type":["string","null"]},"createTime":{"type":["string","null"],"format":"date-time"},"playCount":{"type":["integer","null"]},"diggCount":{"type":["integer","null"]},"commentCount":{"type":["integer","null"]},"shareCount":{"type":["integer","null"]},"engagementRate":{"type":["number","null"]}}},"CreatorAnalysisAudience":{"type":"object","properties":{"commentsAnalyzed":{"type":"integer"},"videosWithComments":{"type":"integer"},"distinctCommenters":{"type":"integer"},"avgLikesPerComment":{"type":["number","null"]},"topCommenters":{"type":"array","items":{"type":"object","properties":{"uniqueId":{"type":["string","null"]},"nickname":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"comments":{"type":"integer"},"likes":{"type":"integer"}}}},"languages":{"type":"array","items":{"type":"object","properties":{"language":{"type":"string"},"share":{"type":"number"}}}}}},"CreatorAnalysisGrowth":{"type":"object","properties":{"fromObservedAt":{"type":"string","format":"date-time"},"toObservedAt":{"type":"string","format":"date-time"},"days":{"type":"integer"},"startFollowers":{"type":"integer"},"endFollowers":{"type":"integer"},"followerDelta":{"type":"integer"},"followerDeltaRate":{"type":["number","null"]}}},"CreatorAnalysisLimit":{"type":"object","properties":{"code":{"type":"string","enum":["thin-video-sample","no-videos","no-play-counts","undated-videos","single-observation","no-comments"]},"message":{"type":"string"}}},"CreatorAnalysisData":{"type":"object","required":["creator","sample","topByPlays","topByEngagement","limits"],"properties":{"creator":{"$ref":"#/components/schemas/CreatorAnalysisSubject"},"sample":{"$ref":"#/components/schemas/CreatorAnalysisSample"},"engagement":{"oneOf":[{"$ref":"#/components/schemas/CreatorAnalysisEngagement"},{"type":"null"}]},"cadence":{"oneOf":[{"$ref":"#/components/schemas/CreatorAnalysisCadence"},{"type":"null"}]},"topByPlays":{"type":"array","items":{"$ref":"#/components/schemas/CreatorAnalysisVideo"}},"topByEngagement":{"type":"array","items":{"$ref":"#/components/schemas/CreatorAnalysisVideo"}},"audience":{"oneOf":[{"$ref":"#/components/schemas/CreatorAnalysisAudience"},{"type":"null"}]},"growth":{"oneOf":[{"$ref":"#/components/schemas/CreatorAnalysisGrowth"},{"type":"null"}]},"limits":{"type":"array","items":{"$ref":"#/components/schemas/CreatorAnalysisLimit"}}}},"GifterSummary":{"type":"object","properties":{"gifterKey":{"type":"string","description":"TikTok sec_uid, or a uid:<userId> fallback — see `identity`."},"identity":{"type":"string","enum":["sec_uid","user_id_fallback"]},"secUid":{"type":["string","null"]},"uniqueId":{"type":["string","null"]},"nickname":{"type":["string","null"]},"avatarUrl":{"type":["string","null"],"description":"PD4 — resolved gifter avatar (best-effort, cached); null → gradient fallback, never an invented image."},"observedDiamonds":{"type":"integer","description":"Coins (\"Xu\") observed from the gifter within the requested window — per-poll deltas summed, exact to the hour; not a lifetime total. The name is historical."},"estimatedValueUsd":{"type":["number","null"],"description":"PD5 — `observedDiamonds` as an 'est.' USD value at DIAMOND_USD_RATE (creator-received). Null when not estimable."},"sessionCount":{"type":"integer","description":"Distinct live sessions (rooms) the gifter gave coins in within the window."},"creatorCount":{"type":"integer"},"segment":{"type":"string","enum":["whale","one_time","rising","dormant","regular"],"description":"LT3.1 archetype derived from observed figures."},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"gifterLevel":{"type":["integer","null"],"description":"GL.2 — the gifter's GLOBAL TikTok wealth/gift grade (1–50): their grade badge level, same wherever they gift, not a per-creator fan-club level. Read per-uid from webcast/user (not on the board). A per-gifter attribute (highest grade ever observed), not windowed — reads the same across 24h/7d/30d. Null when not yet looked up or the grade is hidden (fills forward as the collector backfills)."},"fansLevel":{"type":["integer","null"],"description":"GL.2 — the gifter's FAN/community level (1–50): the fan badge (scene_type=10) level from the contribution board, distinct from the global grade. Per-gifter, not windowed. Null when not shown."},"currentRoom":{"oneOf":[{"$ref":"#/components/schemas/GifterRoom"},{"type":"null"}],"description":"GU.2 — the creator this gifter gave to most recently (last 7 days); `live` when that gift was <= 10 min ago. Null when none in 7 days and ALWAYS null on a masked row."},"masked":{"type":"boolean","description":"True when identity (nickname/uniqueId/secUid/gifterKey) is masked below the caller's unlock tier. Reuses the standard rankings board rule: unmask at Pro, top-3 teaser. Avatar/diamonds/segment still show."},"unmaskTier":{"type":["string","null"],"description":"When masked, the plan tier that unlocks the real identity (for an Unlock CTA); else null."}}},"GifterRoom":{"type":"object","properties":{"creatorUniqueId":{"type":"string"},"creatorDisplayName":{"type":["string","null"]},"creatorAvatarUrl":{"type":["string","null"]},"lastGiftAt":{"type":"string","format":"date-time"},"live":{"type":"boolean","description":"lastGiftAt is within 10 minutes of the response — 'gifting now'. Gift recency, not proof the room is still live."}}},"FundedCreator":{"type":"object","properties":{"creatorUniqueId":{"type":"string"},"creatorDisplayName":{"type":["string","null"]},"creatorAvatarUrl":{"type":["string","null"]},"observedDiamonds":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"],"description":"PD5 — `observedDiamonds` as an 'est.' USD value at DIAMOND_USD_RATE. Null when not estimable."},"sessionCount":{"type":"integer"},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"live":{"type":"boolean","description":"GU.2 — lastSeenAt is within 10 minutes of the response: the gifter is gifting this creator now."}}},"CreatorGifter":{"type":"object","properties":{"gifterKey":{"type":"string"},"identity":{"type":"string","enum":["sec_uid","user_id_fallback"]},"secUid":{"type":["string","null"]},"uniqueId":{"type":["string","null"]},"nickname":{"type":["string","null"]},"avatarUrl":{"type":["string","null"],"description":"PD4 — resolved gifter avatar (best-effort, cached); null → gradient fallback."},"observedDiamonds":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"],"description":"PD5 — `observedDiamonds` as an 'est.' USD value at DIAMOND_USD_RATE. Null when not estimable."},"sessionCount":{"type":"integer"},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"gifterLevel":{"type":["integer","null"],"description":"GL.2/GL.3 — the gifter's GLOBAL wealth/gift grade (1–50, scene_type=8), same as GifterSummary.gifterLevel; per-gifter (not windowed). Null until the grade collector has looked the gifter up."},"masked":{"type":"boolean","description":"True when identity is masked below the caller's unlock tier (top-3 teaser per creator, then masked)."},"unmaskTier":{"type":["string","null"],"description":"When masked, the plan tier that unlocks the real identity; else null."}}},"CreatorGiftersAccess":{"type":"object","required":["topN","moreWithheld","unlockTier","totalsWithheld","totalsUnlockTier"],"properties":{"topN":{"type":["integer","null"]},"moreWithheld":{"type":"boolean"},"unlockTier":{"type":["string","null"]},"totalsWithheld":{"type":"boolean"},"totalsUnlockTier":{"type":["string","null"]}}},"CreatorGifterTotals":{"type":"object","required":["observedDiamonds","gifterCount","estimatedValueUsd"],"properties":{"observedDiamonds":{"type":"integer"},"gifterCount":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"],"description":"`observedDiamonds` as an 'est.' USD value at DIAMOND_USD_RATE. Null when not estimable."},"smallGifters":{"type":"object","required":["coins","gifterCount"],"properties":{"coins":{"type":"integer"},"gifterCount":{"type":"integer"}},"description":"The share given by gifters below the store's naming rule (by default under 100 coins in a session and outside the room's top 10): counted in the totals, not listed by name; never negative. Absent on the live board."}}},"CreatorLiveSession":{"type":"object","properties":{"roomId":{"type":"string"},"isLive":{"type":"boolean","description":"False = the creator is offline and this is their most recent session (kept ~2 h after it ends)."},"firstObservedAt":{"type":["string","null"],"format":"date-time","description":"First time a gifter of this session was observed; null while no gift has been seen."},"lastObservedAt":{"type":["string","null"],"format":"date-time","description":"Latest change observed (a gift, or a present gifter's periodic refresh); null while no gift has been seen."}}},"RankingEntry":{"type":"object","properties":{"rank":{"type":"integer"},"creatorUid":{"type":"string"},"uniqueId":{"type":["string","null"]},"nickname":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"isLive":{"type":"boolean"},"roomId":{"type":["string","null"]},"score":{"type":"number"},"leagueClass":{"type":["string","null"]},"leagueClassSource":{"type":["string","null"],"enum":["observed","last_phase",null]},"leagueClassAsOf":{"type":["string","null"],"format":"date-time"},"movement":{"type":"string","enum":["up","down","same","new"]},"previousRank":{"type":["integer","null"]},"masked":{"type":"boolean","description":"True when identity is masked below the caller's unlock tier."},"unmaskTier":{"type":["string","null"]},"sourceRegion":{"type":["string","null"],"description":"GLOBAL board only — the region (bucket key) this creator's score came from; null on a single-region board."},"isLivePro":{"type":["boolean","null"],"description":"LP.4 — TikTok LIVE Pro (✦) member: true = member, false = not, null = unknown/withheld (withheld on a masked row and when the chip is disabled server-side)."}}},"RankingCoverage":{"type":"object","properties":{"completeBoards":{"type":"integer"},"expectedBoards":{"type":"integer"},"ratio":{"type":"number"},"threshold":{"type":"number"}}},"OfficialRankingBoard":{"type":"object","properties":{"kind":{"type":"string","enum":["official"]},"board":{"type":"string"},"region":{"type":"string"},"periodKey":{"type":"string"},"resetAt":{"type":["string","null"],"format":"date-time"},"publishable":{"type":"boolean"},"coverage":{"$ref":"#/components/schemas/RankingCoverage"},"game":{"type":"object","required":["gameKey","gameTitle"],"properties":{"gameKey":{"type":"string"},"gameTitle":{"type":["string","null"]}}},"entries":{"type":"array","items":{"$ref":"#/components/schemas/RankingEntry"}}}},"TeamRankingEntry":{"type":"object","properties":{"rank":{"type":"integer"},"clubName":{"type":["string","null"],"description":"Community display name (masked below the unlock tier)."},"communityLevel":{"type":["integer","null"]},"contributorNum":{"type":["integer","null"]},"communityImageUrl":{"type":["string","null"]},"hostCreatorUid":{"type":"string","description":"Opaque numeric anchor of the community's host (not identity), always shown."},"hostUniqueId":{"type":["string","null"],"description":"Host handle (masked below the unlock tier)."},"hostNickname":{"type":["string","null"],"description":"Host display name (masked below the unlock tier)."},"hostAvatarUrl":{"type":["string","null"],"description":"Host avatar URL — always shown, even on a masked row."},"score":{"type":"number","description":"Combined diamonds of the community's members this period."},"estEarningsUsd":{"type":["number","null"],"description":"Est. creator earnings (USD) from score — observed proxy, not a payout."},"masked":{"type":"boolean"},"unmaskTier":{"type":["string","null"]},"sourceRegion":{"type":["string","null"],"description":"GLOBAL board only — the region this community's winning score came from (shown on masked rows too)."}}},"TeamRankingBoard":{"type":"object","properties":{"kind":{"type":"string","enum":["teams"]},"region":{"type":"string"},"periodKey":{"type":"string"},"resetAt":{"type":["string","null"],"format":"date-time"},"publishable":{"type":"boolean"},"coverage":{"$ref":"#/components/schemas/RankingCoverage"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/TeamRankingEntry"}}}},"TeamRosterMember":{"type":"object","properties":{"rank":{"type":"integer"},"userId":{"type":"string","description":"Opaque numeric anchor of the member (not identity), always shown."},"uniqueId":{"type":["string","null"],"description":"Member handle (masked below the unlock tier)."},"nickname":{"type":["string","null"],"description":"Member display name (masked below the unlock tier)."},"avatarUrl":{"type":["string","null"],"description":"Avatar URL — always shown, even on a masked row."},"fansLevel":{"type":["integer","null"]},"score":{"type":"number","description":"Diamonds/points this member contributed for the list's window."},"estEarningsUsd":{"type":["number","null"],"description":"Est. creator earnings (USD) the host got from this member — observed proxy."},"masked":{"type":"boolean"},"unmaskTier":{"type":["string","null"]}}},"TeamRoster":{"type":"object","properties":{"host":{"type":"object","required":["creatorUid","uniqueId","nickname","avatarUrl"],"properties":{"creatorUid":{"type":"string","description":"Opaque numeric anchor of the host (the board row's hostCreatorUid), always shown."},"uniqueId":{"type":["string","null"],"description":"Host handle (masked below the unlock tier)."},"nickname":{"type":["string","null"],"description":"Host display name (masked below the unlock tier)."},"avatarUrl":{"type":["string","null"]}}},"fanClub":{"type":"object","required":["activeCount","totalCount","hasNext","members"],"properties":{"activeCount":{"type":["integer","null"]},"totalCount":{"type":["integer","null"]},"hasNext":{"type":"boolean"},"members":{"type":"array","items":{"$ref":"#/components/schemas/TeamRosterMember"}}}},"today":{"type":"object","required":["contributorsNum","countdownSeconds","hasNext","contributors"],"properties":{"contributorsNum":{"type":["integer","null"]},"countdownSeconds":{"type":["integer","null"]},"hasNext":{"type":"boolean"},"contributors":{"type":"array","items":{"$ref":"#/components/schemas/TeamRosterMember"}}}}}},"GamingGame":{"type":"object","required":["gameKey","gameTitle","status","resetAt"],"properties":{"gameKey":{"type":"string"},"gameTitle":{"type":["string","null"]},"status":{"type":"string","enum":["offered","not_offered"]},"resetAt":{"type":["string","null"],"format":"date-time"}}},"RankMoversBoard":{"type":"object","required":["board","region","periodKey","gainers","losers"],"properties":{"board":{"type":"string"},"region":{"type":"string"},"periodKey":{"type":"string"},"gainers":{"type":"array","items":{"$ref":"#/components/schemas/RankingEntry"}},"losers":{"type":"array","items":{"$ref":"#/components/schemas/RankingEntry"}}}},"RankingHistoryPeriod":{"type":"object","properties":{"periodKey":{"type":"string"},"observedAt":{"type":"string","format":"date-time"},"coverageStatus":{"type":"string","enum":["observed","partial","not-covered","not-offered","stale"]},"publishable":{"type":"boolean"},"entries":{"type":"array","items":{"$ref":"#/components/schemas/RankingEntry"}}}},"RankingRegion":{"type":"object","properties":{"region":{"type":"string"},"label":{"type":"string"},"coverage":{"$ref":"#/components/schemas/RankingCoverage"},"boards":{"type":"array","items":{"type":"string"}},"notOfferedBoards":{"type":"array","items":{"type":"string"}}}},"AgencyOfficialAccount":{"type":"object","required":["uid","handle","nickname","avatarUrl","followers"],"properties":{"uid":{"type":"string","description":"Numeric TikTok user id as a string."},"handle":{"type":["string","null"]},"nickname":{"type":["string","null"]},"avatarUrl":{"type":["string","null"],"description":"Signed CDN url — it EXPIRES; render with an initials fallback."},"followers":{"type":["integer","null"]}}},"AgencySizeBands":{"type":"object","required":["hosts","agents","monthlyDiamonds","healthScore"],"properties":{"hosts":{"type":["string","null"],"description":"TikTok's band string, verbatim (e.g. \"500+\", \"11-50\")."},"agents":{"type":["string","null"]},"monthlyDiamonds":{"type":["string","null"],"description":"TikTok's band string, verbatim (e.g. \"3000k+\")."},"healthScore":{"type":["string","null"]}}},"AgencyContact":{"type":"object","required":["email","phone","address"],"properties":{"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"address":{"type":["string","null"]}}},"AgencyListItem":{"type":"object","required":["agencyId","name","slug","regionBucket","regionBuckets","onboardedOn","official","hasPublicProfile","serviceTypes","size","applyUrl","lastSeenAt"],"properties":{"agencyId":{"type":"string","description":"TikTok's numeric agency id as a string — the stable key."},"name":{"type":"string"},"slug":{"type":"string","description":"Cosmetic URL segment derived from the name; the id is authoritative."},"regionBucket":{"type":["string","null"],"description":"The primary region bucket (MENA, US+, …) — not an ISO country. TikTok's own value unless the owner recorded regions for the agency (then `regionBuckets[0]`)."},"regionBuckets":{"type":"array","items":{"type":"string"},"description":"Every region the agency is listed under, primary first. Owner-recorded regions replace TikTok's single bucket (AR.1)."},"onboardedOn":{"type":["string","null"],"description":"YYYY-MM-DD."},"official":{"oneOf":[{"$ref":"#/components/schemas/AgencyOfficialAccount"},{"type":"null"}]},"hasPublicProfile":{"type":"boolean"},"serviceTypes":{"type":"array","items":{"type":"string"}},"size":{"oneOf":[{"$ref":"#/components/schemas/AgencySizeBands"},{"type":"null"}]},"applyUrl":{"type":["string","null"],"description":"TikTok's own apply deep link (snssdk1233://webview?…ttba_uid=), or null without an official account."},"lastSeenAt":{"type":"string","format":"date-time"}}},"AgencyListResponse":{"type":"object","required":["agencies","hasMore"],"properties":{"agencies":{"type":"array","items":{"$ref":"#/components/schemas/AgencyListItem"}},"hasMore":{"type":"boolean"}}},"AgencyLinks":{"type":"object","required":["websiteUrl","recruitmentUrl","discordUrl"],"properties":{"websiteUrl":{"type":["string","null"]},"recruitmentUrl":{"type":["string","null"]},"discordUrl":{"type":["string","null"]}}},"AgencyDetail":{"type":"object","required":["agencyId","name","slug","regionBucket","regionBuckets","onboardedOn","official","hasPublicProfile","serviceTypes","size","applyUrl","lastSeenAt","intro","firstSeenAt","contactAvailable","contact","links","editedByRequest"],"properties":{"agencyId":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"regionBucket":{"type":["string","null"]},"regionBuckets":{"type":"array","items":{"type":"string"}},"onboardedOn":{"type":["string","null"]},"official":{"oneOf":[{"$ref":"#/components/schemas/AgencyOfficialAccount"},{"type":"null"}]},"hasPublicProfile":{"type":"boolean"},"serviceTypes":{"type":"array","items":{"type":"string"}},"size":{"oneOf":[{"$ref":"#/components/schemas/AgencySizeBands"},{"type":"null"}]},"applyUrl":{"type":["string","null"]},"lastSeenAt":{"type":"string","format":"date-time"},"intro":{"type":["string","null"],"description":"The agency's published introduction (free text, any language)."},"firstSeenAt":{"type":"string","format":"date-time"},"contactAvailable":{"type":"boolean","description":"True when the agency published contact details."},"contact":{"oneOf":[{"$ref":"#/components/schemas/AgencyContact"},{"type":"null"}],"description":"AD.9 — the agency's published email / phone / address; public on every plan. null when the agency published none."},"links":{"oneOf":[{"$ref":"#/components/schemas/AgencyLinks"},{"type":"null"}],"description":"https links (website / recruitment / Discord): the owner's override per field (AD.5), else a URL the agency pasted into its own TikTok introduction or address (AD.9). null when none."},"editedByRequest":{"type":"boolean","description":"AD.5 — true when the owner set at least one of name / introduction / contact / links at the agency's request (the value may coincide with TikTok's)."}}},"AgencyRegionSummary":{"type":"object","required":["regionBucket","agencies","withPublicProfile","newestOnboardedOn"],"properties":{"regionBucket":{"type":["string","null"],"description":"A region bucket (TikTok's verbatim, or one the owner recorded for an agency — AR.1); null = agencies with no region. An agency listed under several regions counts in each."},"agencies":{"type":"integer"},"withPublicProfile":{"type":"integer"},"newestOnboardedOn":{"type":["string","null"]}}},"AgencyRegionsResponse":{"type":"object","required":["regions","totals"],"properties":{"regions":{"type":"array","items":{"$ref":"#/components/schemas/AgencyRegionSummary"}},"totals":{"type":"object","required":["agencies","withPublicProfile","regions"],"properties":{"agencies":{"type":"integer"},"withPublicProfile":{"type":"integer"},"regions":{"type":"integer"}}}}},"LiveProDirectoryMember":{"type":"object","required":["uniqueId","nickname","avatarUrl","isLive","roomId","region","firstSeenAt","lastSeenAt","masked","unmaskTier"],"properties":{"uniqueId":{"type":["string","null"],"description":"Handle (masked below the unlock tier)."},"nickname":{"type":["string","null"],"description":"Display name (masked below the unlock tier)."},"avatarUrl":{"type":["string","null"],"description":"Avatar URL — public data, shown even on a masked row."},"isLive":{"type":"boolean"},"roomId":{"type":["string","null"],"description":"Live room id when isLive; withheld (null) on a masked row (it resolves to the handle)."},"region":{"type":"string"},"firstSeenAt":{"type":"string","format":"date-time"},"lastSeenAt":{"type":"string","format":"date-time"},"masked":{"type":"boolean","description":"True when uniqueId/nickname are masked below the caller's unlock tier."},"unmaskTier":{"type":["string","null"]}}},"LiveProDirectoryResponse":{"type":"object","required":["region","members"],"properties":{"region":{"type":"string"},"members":{"type":"array","items":{"$ref":"#/components/schemas/LiveProDirectoryMember"}}}},"LiveProRegion":{"type":"object","required":["region","members","liveNow","lastSeenAt"],"properties":{"region":{"type":"string","description":"ISO country code — pass verbatim as `region` to GET /v1/live-pro (rankings bucket keys such as US+ match no directory)."},"members":{"type":"integer"},"liveNow":{"type":"integer","description":"Members whose newest sighting was live."},"lastSeenAt":{"type":"string","format":"date-time"}}},"LiveProRegionsResponse":{"type":"object","required":["regions"],"properties":{"regions":{"type":"array","items":{"$ref":"#/components/schemas/LiveProRegion"}}}},"RecruitCandidate":{"type":"object","required":["creatorUid","uniqueId","nickname","avatarUrl","region","rank","movement","scoreToday","coins30d","coins30dSince","followerCount","verified","isLive","liveState","daysOnBoard","windowScore","roomId","isLivePro","mark","markNote","masked","unmaskTier"],"properties":{"creatorUid":{"type":"string"},"uniqueId":{"type":["string","null"],"description":"Handle (masked below the Agency unlock tier)."},"nickname":{"type":["string","null"],"description":"Display name (masked below the unlock tier)."},"avatarUrl":{"type":["string","null"],"description":"Avatar URL (masked below the unlock tier — recruit hides the photo too)."},"region":{"type":"string","description":"Resolved per creator: home region (ISO) when profiled, else the board bucket. Approximate."},"rank":{"type":"integer"},"movement":{"type":"string","enum":["up","down","same","new"]},"scoreToday":{"type":"number"},"coins30d":{"type":["number","null"],"description":"Diamonds observed over ~30 days (coins↔💎 1:1); a lower bound. null when none observed."},"coins30dSince":{"type":["string","null"],"format":"date-time","description":"Start of the covered window; null when no data."},"followerCount":{"type":["integer","null"]},"verified":{"type":"boolean"},"isLive":{"type":"boolean"},"liveState":{"type":"string","enum":["live","offline","unknown"],"description":"EC.7 — live | offline (a live check ran and found them not live) | unknown (no live check — the tracker only follows creators on a current board). Always `live` on a live-only read."},"daysOnBoard":{"type":["integer","null"],"description":"EC.7 — days in the requested Period (local board days) the creator was on a Daily board; null on a live-only read."},"windowScore":{"type":["number","null"],"description":"EC.7 — the creator's Daily-board score summed over the Period (best bucket per day); null on a live-only read."},"roomId":{"type":["string","null"],"description":"Live room id when isLive; withheld (null) on a masked row."},"isLivePro":{"type":"boolean"},"mark":{"type":["string","null"],"enum":["checked","eligible","ineligible","contacted","signed",null],"description":"Caller workspace's mark (EC.2); null when unmarked."},"markNote":{"type":["string","null"],"maxLength":500,"description":"Caller workspace's note on the mark (EC.2); null when none."},"markAssigneeUserId":{"type":["string","null"],"format":"uuid","description":"AO.5 — owner on the caller workspace's mark; null when none. Absent on a pre-AO.5 server."},"markFollowUpOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","description":"AO.5 — follow-up day on the caller workspace's mark; null when none."},"masked":{"type":"boolean","description":"True when identity (handle/nickname/avatar/roomId) is masked below the unlock tier."},"unmaskTier":{"type":["string","null"]}}},"RecruitMark":{"type":"object","required":["creatorUid","status","note","markedAt","updatedAt","assigneeUserId","assigneeName","followUpOn"],"properties":{"creatorUid":{"type":"string"},"status":{"type":"string","enum":["checked","eligible","ineligible","contacted","signed"]},"note":{"type":["string","null"],"maxLength":500},"markedAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"assigneeUserId":{"type":["string","null"],"format":"uuid","description":"AO.5 — the workspace member who owns this candidate (users.id); null when unassigned."},"assigneeName":{"type":["string","null"],"description":"AO.5 — owner's display name, else email local part; null when unassigned or no longer a member."},"followUpOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","description":"AO.5 — the agency's next follow-up, a UTC calendar day; null when not set."}}},"CrmEvent":{"type":"object","required":["id","at","kind","text","subject","actorUserId","actorName"],"properties":{"id":{"type":"string","description":"Opaque, strictly increasing within a workspace."},"at":{"type":"string","format":"date-time"},"kind":{"type":"string","enum":["status","note","assignee","follow_up","contract_end","roster"]},"text":{"type":"string","description":"Final human wording, e.g. 'Status → Contacted', 'Follow-up set for Oct 9'. Never about money."},"subject":{"type":"string","enum":["recruit","host"],"description":"Where the line was recorded: a host's history also carries its recruit-stage lines."},"actorUserId":{"type":["string","null"],"format":"uuid"},"actorName":{"type":["string","null"],"description":"Display name, else email local part; null for an API-key write or a deleted user."}}},"CrmEventsResponse":{"type":"object","required":["events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/CrmEvent"}}}},"RecruitDigestConditions":{"type":"object","required":["excludeLivePro","newlyRankedOnly","maxCoins30d","minFollowers","includeOffline","periodDays","daysInTop"],"properties":{"excludeLivePro":{"type":"boolean","description":"Leave out current LIVE Pro badge-holders (default true)."},"newlyRankedOnly":{"type":"boolean","description":"Keep only creators whose board movement is `new` (the Recruit page's 'New only'; distinct from the digest mode `new_only`)."},"maxCoins30d":{"type":["integer","null"],"minimum":0,"maximum":1000000000000,"description":"'Not yet graduated' ceiling on observed 30-day diamonds; null = no ceiling."},"minFollowers":{"type":["integer","null"],"minimum":0,"maximum":10000000000,"description":"Minimum followers; null = any."},"includeOffline":{"type":"boolean","description":"EC.8 — also read the Daily-board history (creators not live now), like the Recruit page's 'Include not-live'. Default false."},"periodDays":{"type":"integer","enum":[7,14,30],"description":"EC.8 — the Period a not-live digest reads, counted back from the run. Default 30. Only used with includeOffline."},"daysInTop":{"type":"string","enum":["any","regular","every"],"description":"EC.8 — 'Days in top' for a not-live digest (any | regular | every). Default regular. Only used with includeOffline."}}},"RecruitDigestSubscription":{"type":"object","required":["enabled","countries","cadence","mode","skipMarked","conditions","sendToAccountEmail","emailRecipientStatus","emailRecipientMasked","pendingEmailRecipientMasked","channelIds","lastRunAt","nextRunAt","createdAt","updatedAt"],"properties":{"enabled":{"type":"boolean"},"countries":{"type":"array","items":{"type":"string"},"description":"Resolved-country codes; empty = every country."},"cadence":{"type":"string","enum":["6h","12h","daily","weekly"]},"mode":{"type":"string","enum":["full","new_only"]},"skipMarked":{"type":"boolean"},"conditions":{"$ref":"#/components/schemas/RecruitDigestConditions"},"topCount":{"type":"integer","enum":[5,10,25],"description":"EC.8 — names listed in the message body; the full list is in the CSV attachment (email) / the webhook's `creators`."},"sendToAccountEmail":{"type":"boolean","description":"The built-in email delivery (independent of alert channels)."},"emailRecipientStatus":{"type":"string","enum":["account","verified","pending"],"description":"account = the account email of the member who turned it on; verified = a confirmed custom address; pending = a NEW address awaiting confirmation (digests keep going to the previous recipient)."},"emailRecipientMasked":{"type":["string","null"],"description":"MASKED address digests are mailed to right now (j***@x.com); null when none can be resolved."},"pendingEmailRecipientMasked":{"type":["string","null"],"description":"MASKED address awaiting confirmation."},"channelIds":{"type":"array","items":{"type":"string"},"description":"Existing alert channels (AlertChannelView.id) the digest is delivered to."},"lastRunAt":{"type":["string","null"],"format":"date-time"},"nextRunAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"RecruitDigestResponse":{"type":"object","required":["subscription","minCadenceHours","cadences","accountEmailMasked"],"properties":{"subscription":{"oneOf":[{"$ref":"#/components/schemas/RecruitDigestSubscription"},{"type":"null"}]},"minCadenceHours":{"type":"integer"},"cadences":{"type":"array","items":{"type":"string","enum":["6h","12h","daily","weekly"]}},"accountEmailMasked":{"type":["string","null"],"description":"The CALLER's own account email, masked; null for an API key."}}},"RecruitMarksResponse":{"type":"object","required":["marks","nextCursor"],"properties":{"marks":{"type":"array","items":{"$ref":"#/components/schemas/RecruitMark"}},"nextCursor":{"type":["string","null"]}}},"RecruitStats":{"type":"object","required":["liveNow","regions","earnedToday","observedAt","window"],"properties":{"liveNow":{"type":"integer","description":"Creators live on a current board right now."},"regions":{"type":"integer","description":"Distinct resolved regions represented in the pool."},"earnedToday":{"type":"number","description":"Sum of today's board scores across the current snapshots."},"observedAt":{"type":"string","format":"date-time"},"window":{"oneOf":[{"$ref":"#/components/schemas/RecruitWindow"},{"type":"null"}],"description":"EC.7 — the Period an includeOffline read covered; null on a live-only read."}}},"RecruitWindow":{"type":"object","required":["from","to","daysWithData","historySince","matching","capped"],"properties":{"from":{"type":"string","description":"First local board date covered (YYYY-MM-DD, inclusive)."},"to":{"type":"string","description":"Last local board date covered (YYYY-MM-DD, inclusive)."},"daysWithData":{"type":"integer","description":"Days inside [from, to] that have Daily-board data — the denominator of daysOnBoard."},"historySince":{"type":["string","null"],"description":"First local board date with continuous Daily history (the data depth)."},"matching":{"type":"integer","description":"Creators on a Daily board in the Period that match the history filters, before the enrichment cap."},"capped":{"type":"boolean","description":"True when `matching` exceeded the enrichment cap, so only the best-ranked are returned."}}},"RecruitResponse":{"type":"object","required":["stats","candidates","nextCursor"],"properties":{"stats":{"$ref":"#/components/schemas/RecruitStats"},"candidates":{"type":"array","items":{"$ref":"#/components/schemas/RecruitCandidate"}},"nextCursor":{"type":["string","null"]}}},"LiveCreatorPerformanceRecord":{"type":"object","properties":{"sessionId":{"type":"string"},"sessionStartedAt":{"type":"string","format":"date-time"},"creatorUniqueId":{"type":"string"},"roomKey":{"type":"string"},"durationSeconds":{"type":"integer"},"peakViewerCount":{"type":"integer"},"eventCount":{"type":"integer"},"chatCount":{"type":"integer"},"giftCount":{"type":"integer"},"totalGiftDiamonds":{"type":"integer"},"distinctGifterCount":{"type":"integer"}}},"LivePlayback":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["live","no_playback","offline"],"description":"`live` carries the fields below; `no_playback`/`offline` carry only status + message."},"roomId":{"type":["string","null"]},"title":{"type":["string","null"]},"nickname":{"type":["string","null"]},"hlsUrl":{"type":["string","null"],"description":"null for FLV-only rooms; prefer HLS when both are present."},"flvUrl":{"type":["string","null"]},"expiresAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"renditions":{"type":"array","items":{"type":"object"}},"avatarUrl":{"type":["string","null"]},"verified":{"type":"boolean"},"followerCount":{"type":["integer","null"]},"region":{"type":["string","null"]},"source":{"type":"string","description":"Always tiktok-cdn: the customer's browser fetches the video directly from TikTok."},"cached":{"type":"boolean"},"message":{"type":["string","null"]}}},"TrendData":{"type":"object","properties":{"trendType":{"type":"string","enum":["hashtag","sound"]},"trendId":{"type":"string"},"region":{"type":"string"},"title":{"type":["string","null"]},"rank":{"type":["integer","null"]},"videoCount":{"type":["integer","null"]},"viewCount":{"type":["integer","null"]},"firstSeenAt":{"type":"string","format":"date-time"},"lastRefreshedAt":{"type":"string","format":"date-time"}}},"WatchlistEntry":{"type":"object","required":["id","creatorUniqueId","creatorDisplayName","creatorAvatarUrl","region","isLive","roomId","rank","ranks","topGifter","note","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"creatorUniqueId":{"type":"string"},"creatorDisplayName":{"type":["string","null"]},"creatorAvatarUrl":{"type":["string","null"]},"creatorFollowerCount":{"type":["integer","null"]},"verified":{"type":["boolean","null"]},"region":{"type":["string","null"]},"isLive":{"type":"boolean"},"roomId":{"type":["string","null"]},"rank":{"type":["integer","null"]},"ranks":{"type":"array","items":{"type":"object","required":["board","rank","gameTitle"],"properties":{"board":{"type":"string"},"rank":{"type":"integer"},"gameTitle":{"type":["string","null"]}}}},"topGifter":{"type":["object","null"],"properties":{"gifterUniqueId":{"type":["string","null"]},"gifterNickname":{"type":["string","null"]},"diamondTotal":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"]}},"required":["gifterUniqueId","gifterNickname","diamondTotal","estimatedValueUsd"]},"giftTotals":{"type":["object","null"],"properties":{"24h":{"type":"object","required":["observedDiamonds","gifterCount","estimatedValueUsd"],"properties":{"observedDiamonds":{"type":"integer"},"gifterCount":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"]}}},"7d":{"type":"object","required":["observedDiamonds","gifterCount","estimatedValueUsd"],"properties":{"observedDiamonds":{"type":"integer"},"gifterCount":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"]}}},"30d":{"type":"object","required":["observedDiamonds","gifterCount","estimatedValueUsd"],"properties":{"observedDiamonds":{"type":"integer"},"gifterCount":{"type":"integer"},"estimatedValueUsd":{"type":["number","null"]}}}},"required":["24h","7d","30d"]},"note":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"rosterStatus":{"type":["string","null"],"enum":["active","paused","left",null]},"signedOn":{"type":["string","null"]},"leftOn":{"type":["string","null"]},"rosterNote":{"type":["string","null"]},"splitPct":{"type":["number","null"]},"creatorUid":{"type":["string","null"]},"assigneeUserId":{"type":["string","null"],"format":"uuid","description":"AO.5 — the workspace member who owns this host (users.id; `userId` in GET /v1/workspace/members). Roster fields only."},"assigneeName":{"type":["string","null"],"description":"AO.5 — owner's display name, else email local part; null when unassigned or no longer a member."},"followUpOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","description":"AO.5 — next follow-up, a UTC day."},"contractEndsOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","description":"AO.5 — the contract end the agency typed (a UTC day); never read from a contract."}}},"AlertChannelView":{"type":"object","properties":{"id":{"type":"string"},"channelType":{"type":"string","enum":["webhook","email","in_app","telegram","discord"]},"target":{"type":["string","null"]},"enabled":{"type":"boolean"},"hasSigningSecret":{"type":"boolean"}}},"AlertRuleView":{"type":"object","required":["id","name","scope","eventTypes","enabled","channels"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"scope":{"type":"string","enum":["watchlist","creator","any","gifter_watchlist"]},"creatorUniqueId":{"type":["string","null"]},"region":{"type":["string","null"]},"eventTypes":{"type":"array","items":{"type":"string"}},"minDiamondCount":{"type":["integer","null"]},"minFollowerMilestone":{"type":["integer","null"]},"enabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"channels":{"type":"array","items":{"$ref":"#/components/schemas/AlertChannelView"}}}},"GifterWatchlistEntry":{"type":"object","required":["id","gifterKey","status","alert","addedAt"],"properties":{"id":{"type":"string"},"gifterKey":{"type":"string","description":"Stable gifter key (sec_uid, else uid:<id>) — also the id of the gifter's page."},"uniqueId":{"type":["string","null"]},"nickname":{"type":["string","null"]},"avatarUrl":{"type":["string","null"]},"gifterLevel":{"type":["integer","null"],"description":"Global gifter level 1–50, when known and not hidden by the gifter."},"status":{"type":"string","enum":["gifting_now","seen","not_seen","unknown"],"description":"gifting_now = observed gifting in a live room in the last few minutes; seen = observed gifting in the window; not_seen = never observed in the window; unknown = the history lookup did not finish in time (the next refresh fills it)."},"liveInCreator":{"type":["string","null"],"description":"Host handle whose live the gifter is gifting in (status gifting_now)."},"lastSeenAt":{"type":["string","null"],"format":"date-time"},"observedDiamonds":{"type":["integer","null"],"description":"Coins (Xu) observed from the gifter over the response `window`."},"creatorCount":{"type":["integer","null"],"description":"Distinct creators funded in that window."},"estimatedValueUsd":{"type":["number","null"],"description":"Estimated creator-received value of the window's coins (est.; revenue is about 2x, earnings = this)."},"sessionCount":{"type":["integer","null"]},"region":{"type":["string","null"]},"regionCount":{"type":["integer","null"]},"segment":{"type":["string","null"],"description":"whale | rising | regular | one_time | dormant — the Gifters board archetype over the window."},"firstSeenAt":{"type":["string","null"],"format":"date-time"},"fansLevel":{"type":["integer","null"]},"alert":{"type":"object","required":["enabled","minCoins","channels"],"properties":{"enabled":{"type":"boolean"},"minCoins":{"type":["integer","null"]},"channels":{"type":["array","null"],"items":{"type":"string"}}}},"addedAt":{"type":"string","format":"date-time"}}},"GifterWatchlistAccess":{"type":"object","required":["allowed","unlockTier","limit"],"properties":{"allowed":{"type":"boolean"},"unlockTier":{"type":["string","null"]},"limit":{"type":"integer"}}},"WebhookSecretReveal":{"type":"object","required":["channelId","signingSecret"],"properties":{"channelId":{"type":"string"},"signingSecret":{"type":"string","description":"The signing secret, shown ONCE at creation. Store it now — it is never returned again."}}},"ExportJob":{"type":"object","required":["id","dataset","format","status","filename","createdAt"],"properties":{"id":{"type":"string"},"dataset":{"type":"string","enum":["rankings","gifters","creator_roster","creator_gifters","gifter_funded_creators","teams","team_roster","live_pro","recruit","agencies","gifter_watchlist","live_sessions"]},"format":{"type":"string","enum":["csv","xlsx"]},"status":{"type":"string","enum":["pending","ready","failed"]},"rowCount":{"type":"integer"},"filename":{"type":"string"},"downloadUrl":{"type":["string","null"]},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"}}},"ApiKey":{"type":"object","required":["id","label","keyPrefix","scopes","status","createdAt"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"keyPrefix":{"type":"string","description":"The public prefix; the secret is NEVER returned by a list."},"scopes":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"expiresAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreatedApiKey":{"type":"object","required":["item","token"],"properties":{"item":{"$ref":"#/components/schemas/ApiKey"},"token":{"type":"string","description":"The full secret token, shown ONCE. Store it now — it is never returned again."}}},"UsageLedgerItem":{"type":"object","properties":{"id":{"type":"string"},"apiKeyId":{"type":["string","null"]},"apiKeyPrefix":{"type":["string","null"]},"apiKeyLabel":{"type":["string","null"]},"operation":{"type":"string"},"creditDelta":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}},"Usage":{"type":"object","required":["period","balance","items"],"properties":{"period":{"type":"string","description":"The UTC billing-month bucket, e.g. 2026-08-01."},"balance":{"type":"object","required":["remaining","spent"],"properties":{"remaining":{"type":"integer"},"spent":{"type":"integer"}}},"items":{"type":"array","items":{"$ref":"#/components/schemas/UsageLedgerItem"}}}},"EntitlementLimits":{"type":"object","properties":{"requestsPerWindow":{"type":"integer"},"rateWindowMs":{"type":"integer"},"apiRequestsPerSecond":{"type":"integer"},"requestsPerDay":{"type":"integer"},"maxApiKeys":{"type":"integer"},"wsConcurrencyCap":{"type":"integer"},"maxRoomMinutesPerMonth":{"type":"integer"},"historyWindowDays":{"type":["integer","null"]},"maxSeats":{"type":"integer"},"seatsUsed":{"type":"integer"},"exportFormats":{"type":"array","items":{"type":"string","enum":["csv","xlsx"]}}}},"EntitlementCredits":{"type":"object","properties":{"period":{"type":"string"},"monthlyAllotment":{"type":"integer"},"hardCap":{"type":"integer"},"spent":{"type":"integer"},"remaining":{"type":"integer"}}},"Entitlement":{"type":"object","required":["workspaceId","tier","modules","freeFallbackModules","limits","credits"],"properties":{"workspaceId":{"type":"string"},"planCode":{"type":["string","null"]},"tier":{"type":"string","enum":["free","starter","pro","scale","agency","enterprise"]},"modules":{"type":"array","items":{"type":"string","enum":["live","lookup"]}},"freeFallbackModules":{"type":"array","items":{"type":"string","enum":["live","lookup"]}},"limits":{"$ref":"#/components/schemas/EntitlementLimits"},"credits":{"$ref":"#/components/schemas/EntitlementCredits"}}}}},"paths":{"/v1/rankings/regions":{"get":{"summary":"List the regions a rank board can be read for, each with its coverage, its currently offered captured board keys, and `notOfferedBoards` — the boards proven absent from TikTok's product there. Disable only what `notOfferedBoards` names: a board missing from `boards` may simply be one we have not captured yet. Regions are BUCKET keys (US+, MENA, LATAM, DE+) — not ISO country codes, which match no board — and the list is built from captured availability, not from the crawl configuration.","security":[{"bearerAuth":["rank:read"]}],"parameters":[],"responses":{"200":{"description":"Provenance-wrapped region list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["regions"],"properties":{"regions":{"type":"array","items":{"$ref":"#/components/schemas/RankingRegion"}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agencies":{"get":{"summary":"AD.2 — the TikTok LIVE agency directory (TikTok's own LIVE Creator Network registry, swept by id): name, TikTok region bucket, onboarding date, official account, services, TikTok's size bands and TikTok's apply deep link. Filter by `region` (TikTok's bucket verbatim — see /v1/agencies/regions), `q` (name or official handle contains), `serviceType`, `publicProfileOnly`; `sort` size (default) | newest | name; page with `limit` (1..100, default 24) + `offset`. List rows never carry contact details — read one agency for those. Reads collected data only — never reaches TikTok.","security":[{"bearerAuth":["agencies:read"]}],"parameters":[{"name":"region","in":"query","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"}},{"name":"serviceType","in":"query","schema":{"type":"string"}},{"name":"publicProfileOnly","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"sort","in":"query","schema":{"type":"string","enum":["size","newest","name"]}},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"offset","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped agency list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/AgencyListResponse"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agencies/regions":{"get":{"summary":"AD.2 — the region buckets the agency directory holds, each with its agency count, how many published a public profile and its newest onboarding, largest first, plus whole-directory totals. Buckets are TikTok's own agency regions verbatim (MENA, US+, …) — NOT the rankings bucket keys or ISO codes; `null` groups agencies that left the region empty. No parameters.","security":[{"bearerAuth":["agencies:read"]}],"parameters":[],"responses":{"200":{"description":"Provenance-wrapped agency region list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/AgencyRegionsResponse"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/agencies/{agencyId}":{"get":{"summary":"AD.2 — one agency in full: everything in the list row plus its published introduction, its contact details (email / phone / address — public on every plan) and its website / apply / Discord links when known. 404 `agency_not_found` when TikTok's catalog holds no such id.","security":[{"bearerAuth":["agencies:read"]}],"parameters":[{"name":"agencyId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped agency detail","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/AgencyDetail"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live-pro":{"get":{"summary":"LP.4 — the TikTok LIVE Pro creator directory for a region: creators TikTok surfaces with the ✦ LIVE Pro badge (from the signed anchor/top_creator/list feed, collected over time into a membership union), freshest sighting first, with who is live right now. Handle/nickname mask below the unlock tier (avatar shown even when masked, like the rank boards); a masked row's live roomId is withheld. `region` is an ISO country code (call /v1/live-pro/regions for the live list — rankings bucket keys such as US+ match no directory); `liveOnly=true` restricts to currently-live members; `limit` caps the page (1..1000, default 100). Reads collected directory data only — never reaches TikTok.","security":[{"bearerAuth":["live-pro:read"]}],"parameters":[{"name":"region","in":"query","schema":{"type":"string"}},{"name":"liveOnly","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"limit","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped LIVE Pro directory","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/LiveProDirectoryResponse"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live-pro/regions":{"get":{"summary":"LP.7 — the regions the LIVE Pro directory can be read for, each with its member count, how many are live now and its newest sighting. Built from collected directory data (never from the collector configuration), sorted by region code; ISO country codes, NOT the rankings bucket keys. Call this before guessing a region for /v1/live-pro. No parameters.","security":[{"bearerAuth":["live-pro:read"]}],"parameters":[],"responses":{"200":{"description":"Provenance-wrapped LIVE Pro region list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/LiveProRegionsResponse"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit":{"get":{"summary":"EC.1 — the recruiting pool: creators live now on the current board, enriched with today's score, a 30-day diamond band (observed on boards we poll — a lower bound), followers/verified, and the ✦ LIVE Pro badge, so an agency can find who is worth recruiting. It never computes eligibility (the agency checks that in TikTok's backstage). Identity (handle/nickname/avatar/roomId) masks below the Agency unlock tier. `region` is a board bucket (empty = every bucket); `excludeLivePro` (default true) hides current LIVE Pro badge-holders; `maxCoins30d` caps the 'not yet graduated' diamond band; `newOnly` keeps movement=new; `minFollowers`/`minScoreToday` filter; `sort` = score|coins30d|followers|rank (default score); `limit` 1..200; `cursor` pages. EC.7 — `includeOffline=true` widens the pool from creators live NOW to everyone who was on a Daily board during a Period (`from`/`to`, inclusive local board dates YYYY-MM-DD, at most 31 days; default = the last 30 days ending today, clamped to the data we hold): each row then carries `liveState`, `daysOnBoard` and `windowScore`, `minDaysOnBoard`/`minWindowScore`/`maxWindowScore` filter on them, and `sort` also accepts windowScore|liveFirst (live first, then windowScore). Without `includeOffline` the read is live-only and unchanged. Reads collected data only — never reaches TikTok.","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"region","in":"query","schema":{"type":"string"}},{"name":"includeOffline","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"from","in":"query","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}},{"name":"to","in":"query","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}},{"name":"minDaysOnBoard","in":"query","schema":{"type":"string","pattern":"^([0-9]{1,3}|all)$"},"description":"Minimum days on a Daily board in the Period; `all` = every day the Period has data for."},{"name":"minWindowScore","in":"query","schema":{"type":"string"}},{"name":"maxWindowScore","in":"query","schema":{"type":"string"}},{"name":"excludeLivePro","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"newOnly","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"minFollowers","in":"query","schema":{"type":"string"}},{"name":"maxCoins30d","in":"query","schema":{"type":"string"}},{"name":"minScoreToday","in":"query","schema":{"type":"string"}},{"name":"country","in":"query","schema":{"type":"string"},"description":"Keep only creators whose RESOLVED country (profile home region, else the board bucket — the `region` field of each row) equals this code (ISO like RO, or a bucket code like US+); case-insensitive. Distinct from `region`, which selects the BOARD bucket; applied after resolution, so `stats` stay pool-wide."},{"name":"sort","in":"query","schema":{"type":"string","enum":["score","coins30d","followers","rank","windowScore","liveFirst"]}},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped recruiting pool","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/RecruitResponse"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/marks":{"get":{"summary":"EC.2 — this workspace's recruiting marks (the agency's own status per creator: checked | eligible | ineligible | contacted | signed), newest change first, optionally one `status`; `limit` 1..200 (default 50) and `cursor` page. Private to the workspace — never another's. Agency plan or above (403 plan_required below it). Workspace-owned data, not credit-metered.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["checked","eligible","ineligible","contacted","signed"]}},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"The workspace's marks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecruitMarksResponse"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/marks/{creatorUid}":{"put":{"summary":"EC.2 — set (or overwrite) this workspace's mark for a creator; idempotent. Body `{ status, note?, assigneeUserId?, followUpOn? }` (note ≤ 500 chars). AO.5 — `assigneeUserId` (a CURRENT member's users.id, else `422 assignee_not_member`; `null` unassigns) and `followUpOn` (a real UTC day `YYYY-MM-DD`, 2000–2100, else `400 invalid_follow_up_on`; `null` clears) are optional: OMITTED keeps the stored value. Each changed field (status, note, owner, follow-up) appends one line to the mark's history; an unchanged re-PUT appends none. `creatorUid` is the TikTok user id a /v1/recruit row carries. The agency's own call — we never auto-mark. Agency plan or above (403 plan_required below it).","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["checked","eligible","ineligible","contacted","signed"]},"note":{"type":["string","null"],"maxLength":500},"assigneeUserId":{"type":["string","null"],"format":"uuid"},"followUpOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}}}}}},"responses":{"200":{"description":"The stored mark","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecruitMark"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"EC.2 — clear this workspace's mark for a creator. `removed` is false when there was no mark (idempotent). Agency plan or above.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Removal result","content":{"application/json":{"schema":{"type":"object","required":["removed"],"properties":{"removed":{"type":"boolean"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/marks/{creatorUid}/events":{"get":{"summary":"AO.5 — the history of this workspace's mark for a creator (status, note, owner and follow-up changes), newest first, at most 50. Never another workspace's. Agency plan or above (403 plan_required below it). Workspace-owned data, not credit-metered.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"creatorUid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The mark's history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEventsResponse"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/digest":{"get":{"summary":"EC.5 — this workspace's Recruit Creator Digest subscription (or null), plus the cadence floor in force (`minCadenceHours`) and the cadences a client may pick. One subscription per workspace, delivered through the workspace's EXISTING alert channels. Agency plan or above (403 plan_required below it). Workspace-owned config, not credit-metered. 404 while the digest flag is off.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[],"responses":{"200":{"description":"The subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecruitDigestResponse"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"summary":"EC.5 — create or replace this workspace's digest subscription; idempotent. Body `{ cadence: 6h|12h|daily|weekly (6h only when the floor allows), mode?: full|new_only (default new_only), countries?: string[] (resolved-country codes; empty = all), skipMarked? (default true), conditions?: { excludeLivePro? (default true), newlyRankedOnly? (default false), maxCoins30d? (int 0..1e12 or null = no ceiling; a NEW subscription defaults to 500000), minFollowers? (int 0..1e10 or null), includeOffline? (EC.8, default false — also read the Daily history), periodDays? (7|14|30, default 30), daysInTop? (any|regular|every, default regular) } — the Recruit-page filters as digest conditions; topCount? (EC.8: 5|10|25, default 10 — names listed in the message, the full list is in the CSV attachment); omitted keeps the current values, and each delivered digest states them (webhook: `digest.conditions`), channelIds: string[] (0..10 enabled channels that belong to THIS workspace's alert rules — may be empty when sendToAccountEmail is true), sendToAccountEmail? (the built-in email delivery, independent of alert channels; omitted keeps the current value, off for a new subscription via the API; needs a signed-in session or an `emailRecipient`), emailRecipient? (string = a NEW address that must be CONFIRMED by an emailed link before it receives anything — digests keep going to the previous recipient meanwhile; null = back to the account email; omitted = unchanged), enabled? (default true) }`. A digest needs at least one of the built-in email or an enabled channel. A channel of another workspace, or a disabled one, is refused (400 invalid_recruit_digest_input). A new/changed cadence schedules the next run one cadence from now. Agency plan or above.","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["cadence","channelIds"],"properties":{"enabled":{"type":"boolean"},"countries":{"type":"array","items":{"type":"string"},"maxItems":40},"cadence":{"type":"string","enum":["6h","12h","daily","weekly"]},"mode":{"type":"string","enum":["full","new_only"]},"skipMarked":{"type":"boolean"},"sendToAccountEmail":{"type":"boolean"},"emailRecipient":{"type":["string","null"],"maxLength":254},"conditions":{"type":"object","properties":{"excludeLivePro":{"type":"boolean"},"newlyRankedOnly":{"type":"boolean"},"maxCoins30d":{"type":["integer","null"],"minimum":0,"maximum":1000000000000},"minFollowers":{"type":["integer","null"],"minimum":0,"maximum":10000000000},"includeOffline":{"type":"boolean"},"periodDays":{"type":"integer","enum":[7,14,30]},"daysInTop":{"type":"string","enum":["any","regular","every"]}}},"topCount":{"type":"integer","enum":[5,10,25]},"channelIds":{"type":"array","items":{"type":"string"},"minItems":0,"maxItems":10}}}}}},"responses":{"200":{"description":"The stored subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecruitDigestResponse"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"EC.5 — delete this workspace's digest subscription (and its 'sent' memory). `removed` is false when there was none. Agency plan or above.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Removal result","content":{"application/json":{"schema":{"type":"object","required":["removed"],"properties":{"removed":{"type":"boolean"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/digest/email/resend":{"post":{"summary":"EC.5b — mail the confirmation link again for the address awaiting confirmation (rate-limited to 3 confirmation emails per subscription per UTC day, drawn from the daily digest-email budget). 409 when nothing is pending. Agency plan or above.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"The subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecruitDigestResponse"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/digest/email/cancel":{"post":{"summary":"EC.5b — drop the address awaiting confirmation (its emailed link stops working). Digests are untouched. Agency plan or above.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"The subscription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecruitDigestResponse"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recruit/digest/email/confirm":{"get":{"summary":"EC.5b — PUBLIC (token only): the page an emailed confirmation link opens. It shows a Confirm button and changes nothing (a mail scanner prefetching the link cannot confirm for the recipient). HTML.","security":[],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Confirmation page (HTML)"},"400":{"description":"Invalid or expired link (HTML)"},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"EC.5b — PUBLIC (token only): confirm the address named by the signed, 48-hour token; from then on digests go to it. The token binds the subscription, its workspace and the exact address, so it cannot confirm anything else, and it stops working once the pending address changes or is cancelled. HTML.","security":[],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Confirmed (HTML)"},"400":{"description":"Invalid, expired or no-longer-pending link (HTML)"},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/weekly-report/unsubscribe":{"get":{"summary":"AO.7b — PUBLIC (token only): the page the weekly owner report's unsubscribe link opens. It shows an Unsubscribe button and changes NOTHING (a mail scanner prefetching the link cannot unsubscribe the owner); if the owner is already unsubscribed it offers Resubscribe instead. HTML. No email address or workspace is printed.","security":[],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Confirmation page (HTML)"},"400":{"description":"Invalid link (HTML)"},"503":{"description":"Link verification not configured (HTML)"}}},"post":{"summary":"AO.7b — PUBLIC (token only): opt the owner named by the signed `weekly-report-unsub` token out of the weekly owner report, idempotently, whatever their current role. The token comes from the form body (`token=`) or the query string (the RFC 8058 one-click request: `application/x-www-form-urlencoded` body `List-Unsubscribe=One-Click`, token in the URL). The response page carries a Resubscribe button. HTML.","security":[],"parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"token":{"type":"string"},"List-Unsubscribe":{"type":"string"}}}}}},"responses":{"200":{"description":"Unsubscribed (HTML)"},"400":{"description":"Invalid link (HTML)"},"503":{"description":"Link verification not configured (HTML)"}}}},"/v1/weekly-report/resubscribe":{"post":{"summary":"AO.7b — PUBLIC (token only): turn the weekly owner report back on for the owner named by the token — only while they are STILL an owner of that workspace (403 otherwise). Idempotent. Token in the form body or the query string. HTML.","security":[],"parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Resubscribed (HTML)"},"400":{"description":"Invalid link (HTML)"},"403":{"description":"No longer an owner of the workspace (HTML)"},"503":{"description":"Link verification not configured (HTML)"}}}},"/v1/product-updates/unsubscribe":{"get":{"summary":"PUBLIC (token only): the page the product-update emails' unsubscribe link opens. It shows an Unsubscribe button and changes NOTHING (a mail scanner prefetching the link cannot unsubscribe anyone); if the user is already unsubscribed it offers Resubscribe instead. HTML. No email address is printed.","security":[],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Confirmation page (HTML)"},"400":{"description":"Invalid link (HTML)"},"503":{"description":"Link verification not configured (HTML)"}}},"post":{"summary":"PUBLIC (token only): opt the user named by the signed `product-updates-unsub` token out of product-update emails, idempotently. The token comes from the form body (`token=`) or the query string (the RFC 8058 one-click request: `application/x-www-form-urlencoded` body `List-Unsubscribe=One-Click`, token in the URL). The response page carries a Resubscribe button. HTML.","security":[],"parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"token":{"type":"string"},"List-Unsubscribe":{"type":"string"}}}}}},"responses":{"200":{"description":"Unsubscribed (HTML)"},"400":{"description":"Invalid link (HTML)"},"503":{"description":"Link verification not configured (HTML)"}}}},"/v1/product-updates/resubscribe":{"post":{"summary":"PUBLIC (token only): turn product-update emails back on for the user named by the token. Idempotent. Token in the form body or the query string. HTML.","security":[],"parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Resubscribed (HTML)"},"400":{"description":"Invalid link (HTML)"},"503":{"description":"Link verification not configured (HTML)"}}}},"/v1/recruit/digest/test":{"post":{"summary":"EC.5 — 'send me a test digest now': enqueues one small sample digest (≤ 10 creators, subject-prefixed [TEST]) to the subscription's selected, enabled channels. Never advances the schedule and never records 'sent' memory. Rate-limited to one per minute per workspace (429). 404 when there is no subscription. Agency plan or above.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Jobs enqueued","content":{"application/json":{"schema":{"type":"object","required":["enqueued"],"properties":{"enqueued":{"type":"integer"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rankings/gaming/games":{"get":{"summary":"List the per-game gaming boards a region offers — the source for the `game` parameter of board=gaming_game reads, built from captured switcher evidence, never a hardcoded list. `offered` games are readable now; `not_offered` names games TikTok has pulled. An empty list means the region runs only the aggregate gaming board (TikTok has not enabled per-game tabs there). Exposes no creator identity, so no masking applies.","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"region","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped game list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["region","games"],"properties":{"region":{"type":"string"},"games":{"type":"array","items":{"$ref":"#/components/schemas/GamingGame"}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rankings/official":{"get":{"summary":"Get an official (TikTok-observed) rank board with avatar, live status, movement, and honest coverage. Gated boards distinguish incomplete collection (not-covered) from boards TikTok does not publish in that region (not-offered). Creator identity (handle/nickname/avatar) is masked below the unlock tier; rank/score/movement/live always show. Board keys include `hourly`, `daily`, `popular_live`, `gaming_daily`, `gaming_weekly`, the per-game gaming board `gaming_game` (requires the `game` parameter — a game_key from /v1/rankings/gaming/games; the `game` parameter is refused on every other board), the `league_a1`..`league_d5` league boards, and the LIVE Shopping boards `shopping_daily` (rank_type 29, daily, SEA incl. SG) and `shopping_weekly` (rank_type 6, weekly Mon-reset, US/UK/BR/JP). Shopping score is ranking POINTS (not GMV/currency) and its two cadences are not comparable as one unit. The two shopping boards additionally require the `shop:read` scope (on top of `rank:read`).","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"board","in":"query","required":true,"schema":{"type":"string"}},{"name":"region","in":"query","schema":{"type":"string"}},{"name":"game","in":"query","description":"game_key for board=gaming_game (required there, refused elsewhere)","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"string","pattern":"^(?:[1-9][0-9]?|1[0-9][0-9]|200)$"}},{"name":"leagueTier","in":"query","description":"League class filter A1..D5 (league boards only)","schema":{"type":"string","pattern":"^[A-Da-d][1-5]$"}},{"name":"period","in":"query","description":"current (default, live board) or history (the prior published period)","schema":{"type":"string","enum":["current","history"]}},{"name":"liveOnly","in":"query","description":"Only creators live right now in a room the platform observes","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Provenance-wrapped official board","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["board"],"properties":{"board":{"$ref":"#/components/schemas/OfficialRankingBoard"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rankings/teams":{"get":{"summary":"Get the Teams & Clubs board (rank_type=18) for a region: TikTok LIVE fan-club COMMUNITIES ranked by combined diamonds, not creators. Each row carries the community (name, level, member count, image) + its representative host and score. Gated on the board's own capture like every board. The club name and host handle/name mask below the unlock tier; level/members/image/score always show.","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"region","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped teams board","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["board"],"properties":{"board":{"$ref":"#/components/schemas/TeamRankingBoard"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rankings/teams/{hostUid}/roster":{"get":{"summary":"Get the on-demand roster for one Teams & Clubs community host, keyed on the opaque hostCreatorUid the board row exposes: the persistent fan-club member list (\"thành viên hàng đầu\", ranked by lifetime member diamonds, with active/total counts) plus today's contributors (\"người đóng góp hôm nay\", with the next-reset countdown). Live-fetched from TikTok on request (never crawled/stored) and works whether or not the host is currently live. Member + host handle/name mask below the unlock tier (full roster unmasked at Agency); level/score/avatar always show. `section` (members|today) + `offset` page ONE list for load-more (absent = both lists, first page). 404 when the roster feature is disabled or the host does not resolve.","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"hostUid","in":"path","required":true,"schema":{"type":"string"}},{"name":"section","in":"query","description":"Page one list for load-more: members | today (absent = both, first page)","schema":{"type":"string","enum":["members","today"]}},{"name":"offset","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped team host roster","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["roster"],"properties":{"roster":{"$ref":"#/components/schemas/TeamRoster"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rankings/movers":{"get":{"summary":"Region movers (LT1.3): the creators whose rank changed most since the board's previous period, split into `gainers` (moved up) and `losers` (moved down), each biggest-move-first and capped by `limit` (1..99, default 20). Derived from the same official board read, so identity is masked by the caller's plan tier exactly as /v1/rankings/official — never an unmask backdoor. A gated/unpublished board returns empty lists. Shopping boards additionally require `shop:read`; `board=gaming_game` requires `game`.","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"board","in":"query","required":true,"schema":{"type":"string"}},{"name":"region","in":"query","schema":{"type":"string"}},{"name":"game","in":"query","description":"game_key for board=gaming_game (required there, refused elsewhere)","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped movers board","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["board"],"properties":{"board":{"$ref":"#/components/schemas/RankMoversBoard"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rankings/history":{"get":{"summary":"List retained periods of an official rank board, newest first, with cursor pagination. Each period carries its own coverage status — partially captured periods are shown, not hidden. Identity masking follows the caller's plan tier, never the public teaser rule. The `shopping_daily`/`shopping_weekly` boards additionally require the `shop:read` scope (on top of `rank:read`); `board=gaming_game` requires `game`.","security":[{"bearerAuth":["rank:read"]}],"parameters":[{"name":"board","in":"query","required":true,"schema":{"type":"string"}},{"name":"region","in":"query","schema":{"type":"string"}},{"name":"game","in":"query","description":"game_key for board=gaming_game (required there, refused elsewhere)","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Periods per page (not rows)","schema":{"type":"integer","minimum":1,"maximum":24}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"leagueTier","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped retained period page","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["board","region","periods","nextCursor","hasMore"],"properties":{"board":{"type":"string"},"region":{"type":"string"},"periods":{"type":"array","items":{"$ref":"#/components/schemas/RankingHistoryPeriod"}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"},"historyWindowDays":{"type":["integer","null"]},"historyTruncated":{"type":"boolean"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gifters":{"get":{"summary":"List top observed gifters (whales) by diamonds in a window (24h/7d/30d), optionally for one creator","security":[{"bearerAuth":["gifter:read"]}],"parameters":[{"name":"creator","in":"query","schema":{"type":"string"}},{"name":"window","in":"query","schema":{"type":"string","enum":["24h","7d","30d"]},"description":"Observation window (default 7d). Every figure is observed diamonds in this window, not a lifetime total."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Provenance-wrapped gifter list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["gifters","filter"],"properties":{"gifters":{"type":"array","items":{"$ref":"#/components/schemas/GifterSummary"}},"filter":{"type":"object","properties":{"window":{"type":"string"},"creatorUniqueId":{"type":["string","null"]}}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gifters/{gifterKey}":{"get":{"summary":"Get one gifter's observed totals in a window and the creators they fund (who-funds-whom)","security":[{"bearerAuth":["gifter:read"]}],"parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["24h","7d","30d"]},"description":"Observation window (default 7d)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Provenance-wrapped gifter profile","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["gifter","fundedCreators","filter"],"properties":{"gifter":{"$ref":"#/components/schemas/GifterSummary"},"fundedCreators":{"type":"array","items":{"$ref":"#/components/schemas/FundedCreator"}},"filter":{"type":"object","properties":{"window":{"type":"string"}}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{handle}/gifters":{"get":{"summary":"List the gifters funding one creator in a window, ranked by diamonds given to them","security":[{"bearerAuth":["gifter:read"]}],"parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["24h","7d","30d"]},"description":"Observation window (default 7d)."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"Provenance-wrapped creator gifter list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["creatorUniqueId","gifters","totals","filter"],"properties":{"creatorUniqueId":{"type":"string"},"gifters":{"type":"array","items":{"$ref":"#/components/schemas/CreatorGifter"}},"totals":{"oneOf":[{"$ref":"#/components/schemas/CreatorGifterTotals"},{"type":"null"}]},"filter":{"type":"object","properties":{"window":{"type":"string"}}},"access":{"$ref":"#/components/schemas/CreatorGiftersAccess"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{handle}/gifters/live":{"get":{"summary":"List the gifters of one creator's current LIVE session by their cumulative coins in it (TikTok's in-room ranking); offline → their last session for ~2 h (session.isLive false); session null = no live or recent session tracked","security":[{"bearerAuth":["gifter:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200},"description":"Rows to return (default 99, like TikTok's list)."}],"responses":{"200":{"description":"Provenance-wrapped creator live-session gifter board","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["creatorUniqueId","session","gifters","totals"],"properties":{"creatorUniqueId":{"type":"string"},"session":{"oneOf":[{"$ref":"#/components/schemas/CreatorLiveSession"},{"type":"null"}]},"gifters":{"type":"array","items":{"$ref":"#/components/schemas/CreatorGifter"}},"totals":{"oneOf":[{"$ref":"#/components/schemas/CreatorGifterTotals"},{"type":"null"}]},"access":{"$ref":"#/components/schemas/CreatorGiftersAccess"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live/sessions":{"get":{"summary":"REMOVED 2026-09-24 — answers 410 endpoint_removed. Use /v1/live/creators/{uid}/performance.","deprecated":true,"security":[{"bearerAuth":["live:read"]}],"responses":{"410":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live/sessions/{id}":{"get":{"summary":"REMOVED 2026-09-24 — answers 410 endpoint_removed.","deprecated":true,"security":[{"bearerAuth":["live:read"]}],"responses":{"410":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live/creators/{uid}/performance":{"get":{"summary":"List creator LIVE performance","security":[{"bearerAuth":["live:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Provenance-wrapped performance page","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["items","nextCursor"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/LiveCreatorPerformanceRecord"}},"nextCursor":{"type":["string","null"]},"historyWindowDays":{"type":["integer","null"]},"historyTruncated":{"type":"boolean"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live/creators/{uid}/refresh":{"post":{"summary":"Queue an asynchronous LIVE refresh","security":[{"bearerAuth":["live:read"]}],"responses":{"202":{"description":"Refresh accepted","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string"},"jobId":{"type":"string"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live/creators/{uid}/playback":{"get":{"summary":"Get the LIVE video playback sources (HLS/FLV) for a creator who is live now (D2.12). `live:stream`, not `live:read` — this is the video, not the metrics. The customer's browser fetches the stream directly from TikTok's CDN (`source: tiktok-cdn`). Answers `200` with `status: no_playback`/`offline` when there is nothing to play, and `202` (poll the same URL) while a room is being resolved.","security":[{"bearerAuth":["live:stream"]}],"responses":{"200":{"description":"Playback sources (status live) or a no_playback/offline marker","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LivePlayback"}}}},"202":{"description":"Room resolve in progress; poll this URL","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"retryAfterSeconds":{"type":"integer"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/live/stream/token":{"post":{"summary":"Mint a short-lived realtime WS handshake token (present it via the Authorization header or the Sec-WebSocket-Protocol subprotocol when dialing wss://<host>/v1/live/stream — never in the URL)","security":[{"bearerAuth":["live:stream"]}],"responses":{"201":{"description":"Realtime handshake token","content":{"application/json":{"schema":{"type":"object","required":["token","tokenType","expiresIn","wsUrl"],"properties":{"token":{"type":"string"},"tokenType":{"type":"string"},"expiresIn":{"type":"integer"},"wsUrl":{"type":"string"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators":{"get":{"summary":"Search/browse the already-observed creator set, most-followed first (never a live TikTok search). An empty `q` browses the most-followed observed creators; a `q` filters by handle/display-name substring (case-insensitive). Suppressed creators are excluded. **LT2.1 recruiting finder:** without `q`, the filters `region`, `minFollowers`, `liveNow` and `sort` (`followers` default | `rank` = the region's current Daily board order) browse the pool with `cursor`/`nextCursor` pagination. Creator identity (handle/name/avatar) is masked below the `agency` tier (`masked:true`, `unmaskTier`); `region`/`followerCount`/`isLive`/`verified` always show. A `q` search is never masked.","security":[{"bearerAuth":["creator:read"]}],"parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":128}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"region","in":"query","schema":{"type":"string","maxLength":32}},{"name":"minFollowers","in":"query","schema":{"type":"integer","minimum":0}},{"name":"liveNow","in":"query","schema":{"type":"boolean"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["followers","rank"]}},{"name":"cursor","in":"query","schema":{"type":"string","maxLength":128}}],"responses":{"200":{"description":"Provenance-wrapped search/finder result page","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["query","results","nextCursor"],"properties":{"query":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/CreatorSearchResult"}},"nextCursor":{"type":["string","null"]}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}":{"get":{"summary":"Get a public creator profile with metric history. An account we have no fresh copy of is resolved from TikTok on demand (billed `profile-resolve`); a store hit is billed `cached-read`. A resolve that exceeds the synchronous budget answers 202 — poll this same URL.","security":[{"bearerAuth":["creator:read"]}],"responses":{"200":{"description":"Provenance-wrapped creator profile","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["creator"],"properties":{"creator":{"$ref":"#/components/schemas/CreatorProfileData"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"202":{"description":"Resolve in progress; poll this URL","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string"},"jobId":{"type":"string"},"handle":{"type":"string"},"retryAfterSeconds":{"type":"integer"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}/changes":{"get":{"summary":"Timeline of observed identity changes (handle, display name, avatar, bio, region, verification) for one creator","security":[{"bearerAuth":["creator:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Provenance-wrapped change timeline","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["tiktokUserId","uniqueId","changes"],"properties":{"tiktokUserId":{"type":"string"},"uniqueId":{"type":"string"},"changes":{"type":"array","items":{"$ref":"#/components/schemas/CreatorProfileChange"}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}/following":{"get":{"summary":"List the accounts a creator follows (R4.5). Collected on demand through the signed mobile list API when we hold nothing fresh (billed `follow-list-resolve`); a store hit is `cached-read`. The first call for an uncollected account normally answers 202 — poll this same URL. Paginate with the opaque `cursor`.","security":[{"bearerAuth":["creator:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped following page","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/FollowListData"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"202":{"description":"Collection in progress; poll this URL","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"direction":{"type":"string"},"retryAfterSeconds":{"type":"integer"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}/followers":{"get":{"summary":"List a creator's followers (R4.5). Same collection path as `/following`, but TikTok streams followers newest-first and never declares an end, so the response is always a SAMPLE of the most recent followers — compare `storedCount` with `totalReported`.","security":[{"bearerAuth":["creator:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped follower sample","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/FollowListData"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"202":{"description":"Collection in progress; poll this URL","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"direction":{"type":"string"},"retryAfterSeconds":{"type":"integer"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}/analysis":{"get":{"summary":"Full-analysis report for one creator (R4.4): engagement rates, posting cadence, top videos, audience signal from collected comments and follower growth — all derived from stored observations, never fetched at read time. Coverage is always `partial` and `limits` names each gap.","security":[{"bearerAuth":["creator:read"]}],"responses":{"200":{"description":"Provenance-wrapped analysis report","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/CreatorAnalysisData"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}/videos":{"get":{"summary":"List a creator's public videos with current metrics","security":[{"bearerAuth":["content:read"]}],"responses":{"200":{"description":"Provenance-wrapped video list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["uniqueId","tiktokUserId","videos"],"properties":{"uniqueId":{"type":"string"},"tiktokUserId":{"type":"string"},"videos":{"type":"array","items":{"$ref":"#/components/schemas/VideoData"}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/creators/{uid}/stories":{"get":{"summary":"Get a creator's active story tray (D6.1). Content, so it is `content:read` (grouped with videos, not the profile read). Resolves store-first like the profile read, then fetches the tray FRESH through the signed mobile path — stories are ephemeral and never stored. Degrades to an empty tray when no signed credential is configured. Metered `cached-read`.","security":[{"bearerAuth":["content:read"]}],"responses":{"200":{"description":"Provenance-wrapped story tray","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["uniqueId","stories"],"properties":{"uniqueId":{"type":"string"},"stories":{"type":"array","items":{"$ref":"#/components/schemas/Story"}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/videos/{videoId}":{"get":{"summary":"Get one public video with per-video metric history","security":[{"bearerAuth":["content:read"]}],"responses":{"200":{"description":"Provenance-wrapped video + history","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["video"],"properties":{"video":{"$ref":"#/components/schemas/VideoWithHistory"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/videos/{videoId}/comments":{"get":{"summary":"List a public video's comments (R4.3). Collected anonymously from TikTok on demand when we hold nothing fresh (billed `comments-collect`); a store hit is billed `cached-read`. Paginate with the opaque `cursor` returned by the previous page, and pass `parentCommentId` to page one comment's replies.","security":[{"bearerAuth":["content:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"parentCommentId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Provenance-wrapped comment page","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["videoId","comments","nextCursor","hasMore"],"properties":{"videoId":{"type":"string"},"parentCommentId":{"type":["string","null"]},"comments":{"type":"array","items":{"$ref":"#/components/schemas/VideoCommentData"}},"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"},"totalReported":{"type":["integer","null"]},"storedCount":{"type":"integer"}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/trends":{"get":{"summary":"List public trending hashtags/sounds for a region (honest coverage)","security":[{"bearerAuth":["trend:read"]}],"parameters":[{"name":"region","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string","enum":["hashtag","sound"]}}],"responses":{"200":{"description":"Provenance-wrapped trend list","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"type":"object","required":["region","trends"],"properties":{"region":{"type":"string"},"trends":{"type":"array","items":{"$ref":"#/components/schemas/TrendData"}}}},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist":{"get":{"summary":"List the workspace's watchlist creators (D6.1). Sold under `watchlist:manage`; not credit-metered. `?roster=1` (AO.1) lists only the signed hosts: `404` while the roster is not enabled on this deployment, `403 plan_required` below Agency.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"roster","in":"query","required":false,"schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Watchlist entries (newest-first), the per-workspace cap, (EX.1) whether this plan sees the gift totals, and (AO.1) whether the Roster tab is enabled / unlocked","content":{"application/json":{"schema":{"type":"object","required":["items","limit"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WatchlistEntry"}},"limit":{"type":"integer"},"giftTotalsAccess":{"type":"object","required":["withheld","unlockTier"],"properties":{"withheld":{"type":"boolean"},"unlockTier":{"type":["string","null"]}}},"rosterAccess":{"type":"object","required":["enabled","allowed","unlockTier"],"properties":{"enabled":{"type":"boolean"},"allowed":{"type":"boolean"},"unlockTier":{"type":["string","null"]}}}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Add a creator to the workspace watchlist (D6.1). `409 watchlist_full` at the 25-entry cap; `409` on a duplicate handle (case-insensitive).","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["creatorUniqueId"],"properties":{"creatorUniqueId":{"type":"string","minLength":1,"maxLength":64},"note":{"type":["string","null"],"maxLength":200}}}}}},"responses":{"201":{"description":"The created entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistEntry"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/import":{"post":{"summary":"Bulk-import creators to the workspace watchlist (WL.8): add up to 500 handles at once (paste / CSV). Returns a per-input outcome (`added` / `duplicate` / `invalid` / `limit_reached`) plus counts; a repeated handle collapses to one result, and new creators beyond the tier's pin cap are `limit_reached` rather than an error. With `asRoster: true` (Agency plan, roster enabled) the creators become signed hosts: new ones take a watchlist slot (same cap as a single add), already-watched non-hosts are `promoted` (no slot), existing hosts are `duplicate` and left untouched, and `assigneeUserId` assigns every host created; the response then also carries `summary.promoted` and `roster`. Sold under `watchlist:manage`; not credit-metered.","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["creatorUniqueIds"],"properties":{"creatorUniqueIds":{"type":"array","minItems":1,"maxItems":500,"items":{"type":"string","minLength":1,"maxLength":64}},"note":{"type":["string","null"],"maxLength":200},"asRoster":{"type":"boolean","description":"Import the creators as signed HOSTS (roster status `active`). Needs the roster enabled (`404` otherwise) and the Agency plan (`403 plan_required`); a manager is refused. Omitted/false = the plain watchlist import, unchanged."},"assigneeUserId":{"type":["string","null"],"format":"uuid","description":"Only with `asRoster`: assign every host this import adds or promotes to this CURRENT member of THIS workspace (else `422 assignee_not_member`); omitted/`null` = unassigned. Sending it without `asRoster` is `400 assignee_requires_roster`."}}}}}},"responses":{"200":{"description":"Per-input import outcomes and counts","content":{"application/json":{"schema":{"type":"object","required":["results","summary","limit","count"],"properties":{"results":{"type":"array","items":{"type":"object","required":["input","handle","outcome"],"properties":{"input":{"type":"string"},"handle":{"type":["string","null"]},"outcome":{"type":"string","enum":["added","duplicate","invalid","limit_reached","promoted"]}}}},"summary":{"type":"object","required":["requested","added","duplicate","invalid","limitReached"],"properties":{"requested":{"type":"integer"},"added":{"type":"integer"},"duplicate":{"type":"integer"},"invalid":{"type":"integer"},"limitReached":{"type":"integer"},"promoted":{"type":"integer"}}},"limit":{"type":"integer"},"count":{"type":"integer"},"roster":{"type":"object","required":["hosts","assigned","assigneeUserId"],"properties":{"hosts":{"type":"integer"},"assigned":{"type":"integer"},"assigneeUserId":{"type":["string","null"]}}}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/live-check":{"post":{"summary":"Bulk live check (LC.1): paste up to 200 @handles and get who is live RIGHT NOW (a fresh read from TikTok per handle, about 2 s for 30 handles). Each result is `live` (with the current `roomId`), `offline`, `unknown` (no such account or the check failed after one retry) or `invalid`; repeats collapse. Nothing is saved to the watchlist. Sold under `watchlist:manage`; not credit-metered; limited to 30 checks per workspace per hour, one at a time (`429 live_check_rate_limited` / `live_check_busy`).","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["handles"],"properties":{"handles":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"string","minLength":1,"maxLength":64}}}}}}},"responses":{"200":{"description":"Per-input live status and counts","content":{"application/json":{"schema":{"type":"object","required":["results","summary","checkedAt"],"properties":{"results":{"type":"array","items":{"type":"object","required":["input","handle","status","roomId","displayName"],"properties":{"input":{"type":"string"},"handle":{"type":["string","null"]},"status":{"type":"string","enum":["live","offline","unknown","invalid"]},"roomId":{"type":["string","null"]},"displayName":{"type":["string","null"]}}}},"summary":{"type":"object","required":["requested","live","offline","unknown","invalid"],"properties":{"requested":{"type":"integer"},"live":{"type":"integer"},"offline":{"type":"integer"},"unknown":{"type":"integer"},"invalid":{"type":"integer"}}},"checkedAt":{"type":"string"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/liveness":{"get":{"summary":"Poll each watched creator's current live state (WL.1). The same `isLive` the list computes, minus enrichment, for a lightweight in-place refresh. Sold under `watchlist:manage`; not credit-metered.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Per-entry liveness for the workspace's watchlist","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"type":"object","required":["id","isLive"],"properties":{"id":{"type":"string"},"isLive":{"type":"boolean"}}}}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/roster/bulk":{"post":{"summary":"Bulk roster action on up to 100 hosts in ONE transaction (owner / member / API key; a manager is refused `403 forbidden_role`). `assign` sets (or, with `assigneeUserId: null`, clears) the owner of every listed host that is on the roster; `remove` unflags them with exactly the single `DELETE /v1/watchlist/{handle}/roster` semantics (the creator stays on the watchlist; signed / left dates, roster note, owner, follow-up, contract end and commission % are cleared). Handles are normalised (lowercase, `@` stripped) and de-duplicated. A handle that is not on THIS workspace's roster (or not a valid handle) is never created or touched and is returned in `skipped` — the answer does not reveal whether another workspace has it. `assign` is idempotent: a host that already has that owner counts as `unchanged` and writes no history line; each changed host appends the same history line the single PUT would. The assignee must be a CURRENT member of this workspace (`422 assignee_not_member`). Agency plan only (`403 plan_required`); `404` while the roster is not enabled. 0 handles or more than 100 is `400`.","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["action","handles","assigneeUserId"],"properties":{"action":{"type":"string","enum":["assign"]},"handles":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","minLength":1,"maxLength":64}},"assigneeUserId":{"type":["string","null"],"format":"uuid"}}},{"type":"object","required":["action","handles"],"properties":{"action":{"type":"string","enum":["remove"]},"handles":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","minLength":1,"maxLength":64}}}}]}}}},"responses":{"200":{"description":"Counts and the skipped handles","content":{"application/json":{"schema":{"type":"object","required":["applied","unchanged","skipped"],"properties":{"applied":{"type":"integer"},"unchanged":{"type":"integer"},"skipped":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/roster/health":{"get":{"summary":"Health band + reasons for every roster host (AO.3). Always the host's last 7 CLOSED UTC days against its own preceding 28 (never the KPI window selector). Bands: healthy | watch | at_risk | new (under 14 baseline days or a partly-covered recent week — not judged) | unscored (paused, left, or the handle is not matched). Every band carries at least one reason with a stable `code`; `evaluated` lists the signals that had enough data (league needs about a week of snapshots). Judged only from gifts the platform observed in the rooms it polls: 'no gifts observed' is never 'not live', and a host with no observed gifts in its baseline is `watch`, not `at_risk`. Agency plan only (`403 plan_required` below it); `404` while the roster is not enabled on this deployment.","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Roster health","content":{"application/json":{"schema":{"type":"object","required":["throughDay","hosts"],"properties":{"throughDay":{"type":["string","null"]},"hosts":{"type":"array","items":{"type":"object","required":["creatorUniqueId","creatorUid","rosterStatus","health"],"properties":{"creatorUniqueId":{"type":"string"},"creatorUid":{"type":["string","null"]},"rosterStatus":{"type":"string","enum":["active","paused","left"]},"health":{"type":"object","required":["band","reasons","evaluated"],"properties":{"band":{"type":"string","enum":["healthy","watch","at_risk","new","unscored"]},"reasons":{"type":"array","items":{"type":"object","required":["code","severity","params"],"properties":{"code":{"type":"string"},"severity":{"type":"string","enum":["info","watch","at_risk"]},"params":{"type":"object","additionalProperties":{"type":["number","string"]}}}}},"evaluated":{"type":"array","items":{"type":"string","enum":["diamonds_drop","gift_gap","league_drop","league_gone"]}}}}}}}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/roster/kpi":{"get":{"summary":"Per-host KPIs for the workspace's roster (AO.2): observed diamonds over the last 7/30/90 CLOSED UTC days, the change against the previous equal window, days with gifts, a daily series, followers and the newest league standing. Every figure is a LOWER BOUND observed from the rooms the platform polls (coins = diamonds 1:1) — never TikTok's number and never earnings. Each host also carries the agency's own `splitPct` and a `commission` ESTIMATE (observed diamonds x `diamondUsdRate` x that %), with `commissionTotals` over active hosts. A window reports `coverageDays`: `ok` when every day has data, `partial` (>= 7 days) with the real count, else `insufficient_history` with no number; a day without data is `null`, never 0, and nothing is interpolated. Agency plan only (`403 plan_required` below it); `404` while the roster is not enabled on this deployment.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"window","in":"query","required":false,"description":"7d (default) | 30d | 90d","schema":{"type":"string","enum":["7d","30d","90d"]}}],"responses":{"200":{"description":"Roster KPIs","content":{"application/json":{"schema":{"type":"object","required":["window","basis","unit","throughDay","historyStart","diamondUsdRate","commissionTotals","hosts"],"properties":{"window":{"type":"string","enum":["7d","30d","90d"]},"basis":{"type":"string","enum":["observed_lower_bound"]},"unit":{"type":"string","enum":["diamonds"]},"throughDay":{"type":["string","null"]},"historyStart":{"type":["string","null"]},"hosts":{"type":"array","items":{"type":"object","required":["creatorUniqueId","creatorUid","rosterStatus","kpi","followers","league","splitPct","commission"],"properties":{"creatorUniqueId":{"type":"string"},"creatorUid":{"type":["string","null"]},"rosterStatus":{"type":"string","enum":["active","paused","left"]},"kpi":{"oneOf":[{"type":"object","required":["window","windowDays","status","coverageDays","from","to","observedDiamonds","prevObservedDiamonds","deltaPct","daysWithGifts","series","readyOn"],"properties":{"window":{"type":"string","enum":["7d","30d","90d"]},"windowDays":{"type":"integer"},"status":{"type":"string","enum":["ok","partial","insufficient_history"]},"coverageDays":{"type":"integer"},"from":{"type":"string"},"to":{"type":"string"},"observedDiamonds":{"type":["integer","null"]},"prevObservedDiamonds":{"type":["integer","null"]},"deltaPct":{"type":["number","null"]},"daysWithGifts":{"type":"integer"},"series":{"type":"array","items":{"type":"object","required":["day","diamonds"],"properties":{"day":{"type":"string"},"diamonds":{"type":["integer","null"]}}}},"readyOn":{"type":["string","null"]}}},{"type":"null"}]},"followers":{"type":"object","required":["current","delta"],"properties":{"current":{"type":["integer","null"]},"delta":{"type":["integer","null"]}}},"league":{"oneOf":[{"type":"object","required":["class","rank","country","observedAt"],"properties":{"class":{"type":"string"},"rank":{"type":"integer"},"country":{"type":"string"},"observedAt":{"type":"string"}}},{"type":"null"}]},"splitPct":{"type":["number","null"]},"commission":{"oneOf":[{"type":"object","required":["splitPct","estimatedUsd","agencyUsd","hostUsd"],"properties":{"splitPct":{"type":"number"},"estimatedUsd":{"type":"number"},"agencyUsd":{"type":"number"},"hostUsd":{"type":"number"}}},{"type":"null"}],"description":"AO.8 — an ESTIMATE, never a payout: observed diamonds x diamondUsdRate (creator-received value), split by the % the agency typed. A minimum, because the diamonds are a lower bound. Null when no % was entered, the host has left, or the window has no observed figure."}}}},"diamondUsdRate":{"type":"number"},"commissionTotals":{"oneOf":[{"type":"object","required":["agencyUsd","activeHosts","hostsWithSplit","hostsCounted"],"properties":{"agencyUsd":{"type":"number"},"activeHosts":{"type":"integer"},"hostsWithSplit":{"type":"integer"},"hostsCounted":{"type":"integer"}}},{"type":"null"}],"description":"AO.8 — the agency's estimated share summed over ACTIVE hosts that have a % and an observed figure; the counts say how many hosts are inside the sum. Null when no active host has a %."}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/{handle}/roster":{"put":{"summary":"Flag a watched creator as a signed host (AO.1). Agency plan only (`403 plan_required` below it); `404` while the roster is not enabled on this deployment. A creator not yet watched is added first and takes one slot (`409 watchlist_full` at the cap); an already-watched creator takes none. `status` defaults to `active`, `signedOn` to today (UTC); omitted fields keep their value. AO.5 — also accepts the owner / follow-up / contract-end fields below; each changed field appends one line to the host's history (an unchanged re-PUT appends none). Returns the entry with its roster fields.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["active","paused","left"]},"signedOn":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"note":{"type":["string","null"],"maxLength":500},"splitPct":{"type":["number","null"],"minimum":0,"maximum":100,"description":"AO.8 — the % of the host's estimated value the AGENCY keeps (0–100, at most two decimals), typed by the agency; `null` clears it; omitted keeps it. There is no default. Anything else answers `400 invalid_split_pct`."},"assigneeUserId":{"type":["string","null"],"format":"uuid","description":"AO.5 — the member who owns this host: a CURRENT member's users.id of THIS workspace (else `422 assignee_not_member`); `null` unassigns; omitted keeps."},"followUpOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","description":"AO.5 — next follow-up, a real UTC day 2000–2100 (else `400 invalid_follow_up_on`); `null` clears; omitted keeps."},"contractEndsOn":{"type":["string","null"],"pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$","description":"AO.5 — the contract end the agency typed, a real UTC day 2000–2100 (else `400 invalid_contract_ends_on`); `null` clears; omitted keeps. Never read from a contract."}}}}}},"responses":{"200":{"description":"The entry, with its roster state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistEntry"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Remove a host from the roster (AO.1). The creator STAYS on the watchlist. `404 not_on_roster` when it was not a host; Agency plan only.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Roster removal result","content":{"application/json":{"schema":{"type":"object","required":["cleared"],"properties":{"cleared":{"type":"boolean"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/{handle}/roster/events":{"get":{"summary":"AO.5 — the history of a roster host (roster status, owner, follow-up, contract-end and note changes), newest first, at most 50; it also carries the lines recorded while the same creator was a recruit mark (`subject: recruit`, matched through the host's pinned creator uid). Never another workspace's. Agency plan only (`403 plan_required` below it); `404` while the roster is not enabled, or when the handle is not on the roster.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"handle","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The host's history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEventsResponse"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/watchlist/{id}":{"delete":{"summary":"Remove a creator from the workspace watchlist (D6.1)","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Removal result","content":{"application/json":{"schema":{"type":"object","required":["removed"],"properties":{"removed":{"type":"boolean"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gifter-watchlist":{"get":{"summary":"GA.2 — the workspace's GIFTER watchlist: gifters (any @handle) you watch, each with live status and the Gifters-board figures (diamonds, est. value, sessions, region, segment…) over `?window=24h|7d|30d` (default 7d), plus its own alert settings. Pro plan or above uses it (below Pro returns 200 with `access.allowed: false` and an empty list). Cap: Pro 50 · Scale 100 · Agency 200. The alert that fires when a listed gifter is gifting in a covered live is ONE alert rule with scope `gifter_watchlist` (POST /v1/alerts/rules). Sold under `watchlist:manage`; not credit-metered.","security":[{"bearerAuth":["watchlist:manage"]}],"parameters":[{"name":"window","in":"query","schema":{"type":"string","enum":["24h","7d","30d"]}}],"responses":{"200":{"description":"Entries (newest-first), the plan access and cap","content":{"application/json":{"schema":{"type":"object","required":["items","count","access","window"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/GifterWatchlistEntry"}},"count":{"type":"integer"},"access":{"$ref":"#/components/schemas/GifterWatchlistAccess"},"window":{"type":"string","enum":["24h","7d","30d"]}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"GA.2 — add gifters to the workspace's gifter watchlist. Each item is `{ gifterKey }` (picked from observed data) or `{ handle }` (any @handle; unseen handles are resolved via TikTok and watched anyway). Up to 10 per request; per-item outcome `added` / `exists` / `not_found` / `limit_reached` / `invalid` / `unavailable`. 403 gifter_watchlist_upgrade_required below Pro. Sold under `watchlist:manage`; not credit-metered.","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"object","properties":{"gifterKey":{"type":["string","null"],"maxLength":200},"handle":{"type":["string","null"],"maxLength":64}}}}}}}}},"responses":{"200":{"description":"Per-item outcomes, the list size and the plan access","content":{"application/json":{"schema":{"type":"object","required":["results","count","access"],"properties":{"results":{"type":"array","items":{"type":"object","required":["input","outcome","entry"],"properties":{"input":{"type":"string"},"outcome":{"type":"string","enum":["added","exists","not_found","limit_reached","invalid","unavailable"]},"entry":{"anyOf":[{"$ref":"#/components/schemas/GifterWatchlistEntry"},{"type":"null"}]}}}},"count":{"type":"integer"},"access":{"$ref":"#/components/schemas/GifterWatchlistAccess"}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/gifter-watchlist/{id}":{"patch":{"summary":"GA.2b — change ONE listed gifter's alert settings: `alertEnabled` (mute), `alertMinCoins` (fire only once the gifter has given at least this many coins in the live; null clears), `alertChannels` (narrow to a subset of the shared alert rule's channel types; null = all of them). Pro plan or above (403 gifter_watchlist_upgrade_required below it). Returns the updated entry.","security":[{"bearerAuth":["watchlist:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"alertEnabled":{"type":"boolean"},"alertMinCoins":{"type":["integer","null"],"minimum":0,"maximum":1000000000},"alertChannels":{"type":["array","null"],"items":{"type":"string","enum":["webhook","email","in_app","telegram","discord"]},"maxItems":5}}}}}},"responses":{"200":{"description":"The updated entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GifterWatchlistEntry"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"GA.2 — remove a gifter from the workspace's gifter watchlist","security":[{"bearerAuth":["watchlist:manage"]}],"responses":{"200":{"description":"Removal result","content":{"application/json":{"schema":{"type":"object","required":["removed"],"properties":{"removed":{"type":"boolean"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/api-keys":{"get":{"summary":"List workspace API keys (metadata only — never a secret)","security":[{"bearerAuth":["keys:manage"]}],"responses":{"200":{"description":"Key metadata; never a token","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create an API key. The full secret token is returned ONCE in `token` — store it now.","security":[{"bearerAuth":["keys:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["label"],"properties":{"label":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":["string","null"],"format":"date-time"}}}}}},"responses":{"201":{"description":"Key metadata and one-time token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedApiKey"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/api-keys/{id}":{"delete":{"summary":"Revoke a workspace API key","security":[{"bearerAuth":["keys:manage"]}],"responses":{"200":{"description":"Revocation result","content":{"application/json":{"schema":{"type":"object","required":["revoked"],"properties":{"revoked":{"type":"boolean"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/usage":{"get":{"summary":"List workspace usage and per-key request charges for a billing period","security":[{"bearerAuth":["keys:manage"]}],"parameters":[{"name":"period","in":"query","description":"UTC month bucket YYYY-MM-01 (defaults to the current period)","schema":{"type":"string","pattern":"^\\d{4}-(?:0[1-9]|1[0-2])-01$"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"Usage summary and ledger entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/entitlements":{"get":{"summary":"Get the workspace's plan tier, modules, limits (incl. exportFormats) and credit position","security":[{"bearerAuth":["keys:manage"]}],"responses":{"200":{"description":"Provenance-wrapped entitlement","content":{"application/json":{"schema":{"type":"object","required":["data","provenance"],"properties":{"data":{"$ref":"#/components/schemas/Entitlement"},"provenance":{"$ref":"#/components/schemas/Provenance"}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/exports":{"get":{"summary":"List workspace exports","security":[{"bearerAuth":["export"]}],"responses":{"200":{"description":"Export jobs","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExportJob"}}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create an export (format csv|xlsx). Datasets: rankings (needs board+region; optional game for a per-game gaming board and period=current|history), gifters (optional region + segment: the board on screen), creator_roster (the watchlist as a file; with rosterOnly=true just the signed hosts + roster/KPI/commission-estimate columns over rosterWindow 7d|30d|90d), creator_gifters (needs creatorUniqueId; window=24h|7d|30d|live, default 7d; Live module only; capped by plan like the read: Free top 3 / Starter top 3 / Pro+ all), gifter_funded_creators (the whale drill-in's funded-creators list; needs gifterKey; window=24h|7d|30d default 7d; Live module only), teams (the Teams & Clubs board; needs region), team_roster (one community's roster; needs hostUid; optional section=members|today), live_pro (one region's LIVE Pro creator directory; needs region; Live-module data), agencies (the TikTok LIVE agency directory — optional region = TikTok's agency region bucket verbatim, optional query = name/handle search; biggest agencies first; Live-module data; the contact_email/contact_phone/contact_address columns are in the file ONLY on the Agency plan or above — below it the file carries a contact_available flag and no contact columns; 400 export_too_large past 50000 rows), gifter_watchlist (GA.2b — the workspace's gifter watchlist as a file: the board columns over window=24h|7d|30d default 7d, plus live status and each gifter's alert settings; Pro+, 403 gifter_watchlist_upgrade_required below it), recruit (the recruiting pool of GET /v1/recruit as a file, up to 1000 rows; optional region + excludeLivePro/newOnly/minFollowers/maxCoins30d — the same filters as the read; the mark/mark_note columns are this workspace's own marks). Rankings/teams/live_pro/recruit honour the caller's tier identity-mask (export is not an unmask backdoor). 400 invalid_format/invalid_request; 403 export_format_not_entitled if the plan lacks the format; rankings/gifters/creator_gifters/gifter_funded_creators/live_pro/recruit/agencies are Live-module data: 403 module_not_entitled without Live, 503 entitlement_unavailable when the entitlement cannot be resolved; team_roster: 404 team_roster_unavailable when the roster feature is off","security":[{"bearerAuth":["export"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dataset","format"],"properties":{"dataset":{"type":"string","enum":["rankings","gifters","creator_roster","creator_gifters","gifter_funded_creators","teams","team_roster","live_pro","recruit","agencies","gifter_watchlist"]},"format":{"type":"string","enum":["csv","xlsx"]},"rangeDays":{"type":"integer","minimum":1},"board":{"type":"string","description":"Board key for dataset:rankings (e.g. daily, gaming_game, league_a1)."},"region":{"type":"string","description":"Region bucket for dataset:rankings or dataset:teams (e.g. VN); the whale board's region filter for dataset:gifters; TikTok's agency region bucket (MENA, US+) for dataset:agencies (optional there); the optional board bucket for dataset:recruit (absent = every bucket)."},"query":{"type":"string","description":"Name / official-handle search for dataset:agencies; ignored otherwise."},"game":{"type":"string","description":"game_key for a per-game gaming board (board:gaming_game); ignored otherwise."},"period":{"type":"string","enum":["current","history"]},"creatorUniqueId":{"type":"string","description":"Creator handle for dataset:creator_gifters; ignored otherwise."},"gifterKey":{"type":"string","description":"gifterKey for dataset:gifter_funded_creators (the whale drill-in's funded-creators list); ignored otherwise."},"window":{"type":"string","enum":["24h","7d","30d","live"]},"segment":{"type":"string","enum":["whale","one_time","rising","dormant","regular"]},"hostUid":{"type":"string","description":"Community host anchor (hostCreatorUid) for dataset:team_roster; ignored otherwise."},"section":{"type":"string","enum":["members","today"]},"excludeLivePro":{"type":"boolean","description":"dataset:recruit — hide current LIVE Pro badge holders (default true); ignored otherwise."},"newOnly":{"type":"boolean","description":"dataset:recruit — keep only creators new to this period; ignored otherwise."},"minFollowers":{"type":"integer","minimum":0,"description":"dataset:recruit — minimum follower count; ignored otherwise."},"maxCoins30d":{"type":"integer","minimum":0,"description":"dataset:recruit — the 'not yet graduated' 30-day diamond ceiling; ignored otherwise."},"country":{"type":"string","description":"dataset:recruit — keep only creators whose RESOLVED country (row `region`) is this code (ISO RO / bucket US+; case-insensitive); distinct from the board-bucket `region`; ignored otherwise."},"rosterOnly":{"type":"boolean","description":"AO.8d — dataset:creator_roster only: export just the signed hosts with roster columns (status, dates, health band, observed diamonds + delta over rosterWindow, league, agency split %, ESTIMATED agency/host share — blank when not estimable, never 0). Same gate as GET /v1/watchlist?roster=1 (403 plan_required below Agency, 404 while the roster is off). Ignored for other datasets."},"rosterWindow":{"type":"string","enum":["7d","30d","90d"],"description":"AO.8d — the KPI window of a rosterOnly export; default 30d. Ignored otherwise."}}}}}},"responses":{"201":{"description":"Export job (poll it, then download)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportJob"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/exports/{id}":{"get":{"summary":"Get one export job","security":[{"bearerAuth":["export"]}],"responses":{"200":{"description":"Export job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportJob"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/exports/{id}/download":{"get":{"summary":"Download a completed export (CSV or XLSX, with a format-appropriate content-type)","security":[{"bearerAuth":["export"]}],"responses":{"200":{"description":"The export payload","content":{"text/csv":{"schema":{"type":"string"}},"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/alerts/rules":{"get":{"summary":"List webhook/alert rules","security":[{"bearerAuth":["webhook:manage"]}],"responses":{"200":{"description":"Alert rules","content":{"application/json":{"schema":{"type":"object","required":["rules"],"properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/AlertRuleView"}}}}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a webhook/alert rule. Any webhook channel's signing secret is returned ONCE in `webhookSecrets` — store it now.","security":[{"bearerAuth":["webhook:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"scope":{"type":"string","enum":["watchlist","creator","any","gifter_watchlist"],"description":"Subject. `watchlist` (default) matches only creators on the workspace watchlist; `creator` matches the one `creatorUniqueId`; `any` matches every creator; `gifter_watchlist` fires `gifter_live` when any gifter on the workspace's GIFTER watchlist (/v1/gifter-watchlist) is gifting in a covered live — Pro+ only (403 gifter_alert_upgrade_required), ONE per workspace (409 gifter_watchlist_rule_exists), event type forced to gifter_live. Omit to let the server infer it — `creator` when a `creatorUniqueId` is supplied, else `watchlist`. `region` stays an orthogonal filter for the creator scopes."},"creatorUniqueId":{"type":["string","null"]},"region":{"type":["string","null"]},"eventTypes":{"type":"array","items":{"type":"string"}},"minDiamondCount":{"type":["integer","null"]},"minFollowerMilestone":{"type":["integer","null"]},"enabled":{"type":"boolean"},"channels":{"type":"array","items":{"type":"object","properties":{"channelType":{"type":"string","enum":["webhook","email","in_app","telegram","discord"]},"target":{"type":["string","null"]},"enabled":{"type":"boolean"}}}}}}}}},"responses":{"201":{"description":"Created rule and any one-time webhook secrets","content":{"application/json":{"schema":{"type":"object","required":["rule","webhookSecrets"],"properties":{"rule":{"$ref":"#/components/schemas/AlertRuleView"},"webhookSecrets":{"type":"array","items":{"$ref":"#/components/schemas/WebhookSecretReveal"}}}}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/alerts/rules/{id}":{"patch":{"summary":"Update a webhook/alert rule (partial). Returns the updated rule. `scope`+`creatorUniqueId` are coupled — moving to `watchlist`/`any` drops the handle; `creator` requires one. A `gifter_watchlist` rule stays gifter-scoped (only name / channels / enabled are editable); re-enabling one is Pro+.","security":[{"bearerAuth":["webhook:manage"]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"scope":{"type":"string","enum":["watchlist","creator","any","gifter_watchlist"]},"creatorUniqueId":{"type":["string","null"]},"region":{"type":["string","null"]},"enabled":{"type":"boolean"},"eventTypes":{"type":"array","items":{"type":"string"}},"minDiamondCount":{"type":["integer","null"]},"minFollowerMilestone":{"type":["integer","null"]}}}}}},"responses":{"200":{"description":"Updated rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleView"}}}},"400":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a webhook/alert rule","security":[{"bearerAuth":["webhook:manage"]}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/alerts/rules/{id}/test":{"post":{"summary":"Fire a synthetic test event through a rule's channels to verify delivery (does not consume the live event stream)","security":[{"bearerAuth":["webhook:manage"]}],"responses":{"200":{"description":"Test delivery result","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}