2026-07-23 05:56:42 +00:00
|
|
|
|
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 {
|
2026-07-30 01:25:34 +00:00
|
|
|
|
Id string `json:"id"`
|
|
|
|
|
|
Code string `json:"code"`
|
|
|
|
|
|
// TrackPath 保留給同源前端;TrackUrl 是後端算好的絕對網址,貼到 Threads 用這個。
|
2026-07-23 05:56:42 +00:00
|
|
|
|
TrackPath string `json:"track_path"`
|
2026-07-30 01:25:34 +00:00
|
|
|
|
TrackUrl string `json:"track_url"`
|
2026-07-23 05:56:42 +00:00
|
|
|
|
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)
|
|
|
|
|
|
}
|