syntax = "v1" // growth-loop P2: playbook / free tools / benchmark / utm / insights / workspace members type ( PlaybookPublic { Id string `json:"id"` Kind string `json:"kind"` // brief | persona | play Title string `json:"title"` Niche string `json:"niche"` Body string `json:"body"` Anonymous bool `json:"anonymous"` AuthorLabel string `json:"author_label"` ImportCount int `json:"import_count"` CreatedAt int64 `json:"created_at"` Mine bool `json:"mine,optional"` } PlaybookListData { List []PlaybookPublic `json:"list"` Pagination Pagination `json:"pagination"` } ListPlaybooksReq { Page int `form:"page,default=1"` PageSize int `form:"pageSize,default=20"` Kind string `form:"kind,optional"` Niche string `form:"niche,optional"` Mine bool `form:"mine,optional"` } PublishPlaybookReq { Kind string `json:"kind"` Title string `json:"title"` Niche string `json:"niche,optional"` Body string `json:"body"` Anonymous bool `json:"anonymous,optional"` } PlaybookIdPath { Id string `path:"id"` } ImportPlaybookData { Id string `json:"id"` Copied bool `json:"copied"` Message string `json:"message"` } StyleQuizReq { Samples string `json:"samples"` } StyleQuizData { Tone string `json:"tone"` Rhythm string `json:"rhythm"` Hooks string `json:"hooks"` Avoid string `json:"avoid"` Summary string `json:"summary"` Tags []string `json:"tags"` SignupHint string `json:"signup_hint"` } PainKeywordsReq { ProductBrief string `json:"product_brief"` Audience string `json:"audience,optional"` } PainKeywordsData { Keywords []string `json:"keywords"` Pains []string `json:"pains"` ScanTerms []string `json:"scan_terms"` Summary string `json:"summary"` SignupHint string `json:"signup_hint"` } BenchmarkReq { Niche string `form:"niche,optional"` AccountId string `form:"account_id,optional"` } BenchmarkData { Available bool `json:"available"` SampleSize int `json:"sample_size"` Niche string `json:"niche"` MedianEngRate float64 `json:"median_eng_rate"` MedianViews float64 `json:"median_views"` YourEngRate float64 `json:"your_eng_rate,optional"` YourViews float64 `json:"your_views,optional"` PercentileHint string `json:"percentile_hint,optional"` Message string `json:"message,optional"` } CreateUtmLinkReq { DestinationUrl string `json:"destination_url"` OutcomeId string `json:"outcome_id,optional"` Label string `json:"label,optional"` } UtmLinkPublic { Id string `json:"id"` Code string `json:"code"` // TrackPath 保留給同源前端;TrackUrl 是後端算好的絕對網址,貼到 Threads 用這個。 TrackPath string `json:"track_path"` TrackUrl string `json:"track_url"` DestinationUrl string `json:"destination_url"` OutcomeId string `json:"outcome_id,optional"` Label string `json:"label,optional"` Clicks int `json:"clicks"` CreatedAt int64 `json:"created_at"` } UtmLinkListData { List []UtmLinkPublic `json:"list"` } UtmRedirectReq { Code string `path:"code"` } InsightsSummaryReq { AccountId string `form:"account_id,optional"` Months int `form:"months,default=3"` } InsightsPostPublic { Id string `json:"id"` TextPreview string `json:"text_preview"` PublishedAt int64 `json:"published_at"` ViewCount int `json:"view_count"` LikeCount int `json:"like_count"` ReplyCount int `json:"reply_count"` EngRate float64 `json:"eng_rate"` } InsightsSummaryData { AccountId string `json:"account_id,optional"` PostCount int `json:"post_count"` TotalViews int `json:"total_views"` TotalLikes int `json:"total_likes"` TotalReplies int `json:"total_replies"` AvgEngRate float64 `json:"avg_eng_rate"` TopPosts []InsightsPostPublic `json:"top_posts"` MonthBuckets []InsightsMonthBucket `json:"month_buckets"` Conclusion string `json:"conclusion"` Suggestions []string `json:"suggestions"` } InsightsMonthBucket { MonthKey string `json:"month_key"` Posts int `json:"posts"` Views int `json:"views"` Likes int `json:"likes"` Replies int `json:"replies"` AvgEngRate float64 `json:"avg_eng_rate"` } AddWorkspaceMemberReq { WorkspaceId string `path:"id"` MemberUid int64 `json:"member_uid,optional"` Email string `json:"email,optional"` Role string `json:"role,optional"` // editor | reviewer | owner } WorkspaceMemberPublic { Uid int64 `json:"uid"` Email string `json:"email"` DisplayName string `json:"display_name"` Role string `json:"role"` JoinedAt int64 `json:"joined_at"` } WorkspaceMemberListData { List []WorkspaceMemberPublic `json:"list"` } ListWorkspaceMembersReq { Id string `path:"id"` } RemoveWorkspaceMemberReq { Id string `path:"id"` Uid int64 `path:"uid"` } WorkspaceBrandingReq { Id string `path:"id"` FooterText string `json:"footer_text,optional"` HidePoweredBy bool `json:"hide_powered_by,optional"` BrandName string `json:"brand_name,optional"` } ) @server ( group: playbooks prefix: /api/v1/playbooks middleware: AuthJWT ) service gateway { @handler ListPlaybooks get / (ListPlaybooksReq) returns (PlaybookListData) @handler PublishPlaybook post / (PublishPlaybookReq) returns (PlaybookPublic) @handler GetPlaybook get /:id (PlaybookIdPath) returns (PlaybookPublic) @handler ImportPlaybook post /:id/import (PlaybookIdPath) returns (ImportPlaybookData) @handler RemovePlaybook delete /:id (PlaybookIdPath) returns (OkData) } @server ( group: publictools prefix: /api/v1/public/tools ) service gateway { @handler PublicStyleQuiz post /style-quiz (StyleQuizReq) returns (StyleQuizData) @handler PublicPainKeywords post /pain-keywords (PainKeywordsReq) returns (PainKeywordsData) } @server ( group: benchmark prefix: /api/v1/benchmark middleware: AuthJWT ) service gateway { @handler GetBenchmark get / (BenchmarkReq) returns (BenchmarkData) } @server ( group: utm prefix: /api/v1/utm middleware: AuthJWT ) service gateway { @handler CreateUtmLink post /links (CreateUtmLinkReq) returns (UtmLinkPublic) @handler ListUtmLinks get /links returns (UtmLinkListData) } @server ( group: publicutm prefix: /api/v1/public/u ) service gateway { @handler UtmRedirect get /:code (UtmRedirectReq) returns (OkData) } @server ( group: insightsapi prefix: /api/v1/insights middleware: AuthJWT ) service gateway { @handler GetInsightsSummary get /summary (InsightsSummaryReq) returns (InsightsSummaryData) } @server ( group: workspaces prefix: /api/v1/workspaces middleware: AuthJWT ) service gateway { @handler ListWorkspaceMembers get /:id/members (ListWorkspaceMembersReq) returns (WorkspaceMemberListData) @handler AddWorkspaceMember post /:id/members (AddWorkspaceMemberReq) returns (WorkspaceMemberPublic) @handler RemoveWorkspaceMember delete /:id/members/:uid (RemoveWorkspaceMemberReq) returns (OkData) @handler UpdateWorkspaceBranding put /:id/branding (WorkspaceBrandingReq) returns (WorkspacePublic) }