syntax = "v1" type ( ResearchItemData { Title string `json:"title,omitempty"` URL string `json:"url,omitempty"` Snippet string `json:"snippet,omitempty"` Query string `json:"query,omitempty"` } ResearchMapData { AudienceSummary string `json:"audience_summary,omitempty"` ContentGoal string `json:"content_goal,omitempty"` Questions []string `json:"questions,omitempty"` Pillars []string `json:"pillars,omitempty"` Exclusions []string `json:"exclusions,omitempty"` ResearchItems []ResearchItemData `json:"research_items,omitempty"` ExpandStrategy string `json:"expand_strategy,omitempty"` PatrolKeywords []string `json:"patrol_keywords,omitempty"` } KnowledgeGraphEvidenceData { URL string `json:"url,omitempty"` Snippet string `json:"snippet,omitempty"` Query string `json:"query,omitempty"` } BraveSourceData { Query string `json:"query,omitempty"` Title string `json:"title,omitempty"` URL string `json:"url,omitempty"` Snippet string `json:"snippet,omitempty"` } BrandProductData { ID string `json:"id"` Label string `json:"label"` ProductContext string `json:"product_context"` MatchTags []string `json:"match_tags,omitempty"` CreateAt int64 `json:"create_at"` UpdateAt int64 `json:"update_at"` } BrandData { ID string `json:"id"` DisplayName string `json:"display_name,omitempty"` TopicName string `json:"topic_name,omitempty"` SeedQuery string `json:"seed_query,omitempty"` Brief string `json:"brief,omitempty"` ProductBrief string `json:"product_brief,omitempty"` ProductContext string `json:"product_context,omitempty"` ProductID string `json:"product_id,omitempty"` Products []BrandProductData `json:"products,omitempty"` TargetAudience string `json:"target_audience,omitempty"` Goals string `json:"goals,omitempty"` ResearchMap ResearchMapData `json:"research_map,omitempty"` CreateAt int64 `json:"create_at"` UpdateAt int64 `json:"update_at"` } ListBrandProductsData { List []BrandProductData `json:"list"` } CreateBrandProductReq { Label string `json:"label" validate:"required"` ProductContext string `json:"product_context" validate:"required"` MatchTags []string `json:"match_tags,optional"` } UpdateBrandProductReq { Label *string `json:"label,optional"` ProductContext *string `json:"product_context,optional"` MatchTags []string `json:"match_tags,optional"` } BrandProductPath { ID string `path:"id" validate:"required"` ProductID string `path:"productId" validate:"required"` } CreateBrandProductHandlerReq { BrandPath CreateBrandProductReq } UpdateBrandProductHandlerReq { BrandProductPath UpdateBrandProductReq } ListBrandsData { List []BrandData `json:"list"` } CreateBrandReq { DisplayName string `json:"display_name,optional"` } BrandPath { ID string `path:"id" validate:"required"` } UpdateBrandReq { DisplayName *string `json:"display_name,optional"` TopicName *string `json:"topic_name,optional"` SeedQuery *string `json:"seed_query,optional"` Brief *string `json:"brief,optional"` ProductBrief *string `json:"product_brief,optional"` ProductContext *string `json:"product_context,optional"` ProductID *string `json:"product_id,optional"` TargetAudience *string `json:"target_audience,optional"` Goals *string `json:"goals,optional"` AudienceSummary *string `json:"audience_summary,optional"` ContentGoal *string `json:"content_goal,optional"` Questions []string `json:"questions,optional"` Pillars []string `json:"pillars,optional"` Exclusions []string `json:"exclusions,optional"` PatrolKeywords []string `json:"patrol_keywords,optional"` } KnowledgeGraphNodeData { ID string `json:"id"` Label string `json:"label"` NodeKind string `json:"node_kind"` Type string `json:"type"` Layer int `json:"layer"` Relation string `json:"relation,omitempty"` PlacementValue string `json:"placement_value,omitempty"` ProductFitScore int `json:"product_fit_score"` SelectedForScan bool `json:"selected_for_scan"` RelevanceTags []string `json:"relevance_tags"` RecencyTags []string `json:"recency_tags"` Evidence []KnowledgeGraphEvidenceData `json:"evidence,omitempty"` } KnowledgeGraphEdgeData { From string `json:"from"` To string `json:"to"` Relation string `json:"relation"` } KnowledgeGraphData { ID string `json:"id"` BrandID string `json:"brand_id"` Seed string `json:"seed"` Nodes []KnowledgeGraphNodeData `json:"nodes"` Edges []KnowledgeGraphEdgeData `json:"edges"` BraveSources []BraveSourceData `json:"brave_sources,omitempty"` ExpandStrategy string `json:"expand_strategy,omitempty"` PainTagCount int `json:"pain_tag_count"` GeneratedAt int64 `json:"generated_at"` CreateAt int64 `json:"create_at"` UpdateAt int64 `json:"update_at"` } ExpandKnowledgeGraphReq { SeedQuery string `json:"seed_query" validate:"required"` Supplemental bool `json:"supplemental,optional"` RegenerateMap bool `json:"regenerate_map,optional"` ExpandStrategy string `json:"expand_strategy,optional"` // brave | llm | hybrid } ExpandKnowledgeGraphData { JobID string `json:"job_id"` Status string `json:"status"` Message string `json:"message"` } KnowledgeGraphNodeUpdate { NodeID string `json:"node_id" validate:"required"` SelectedForScan *bool `json:"selected_for_scan,optional"` RelevanceTags []string `json:"relevance_tags,optional"` RecencyTags []string `json:"recency_tags,optional"` } PatchKnowledgeGraphNodesReq { Updates []KnowledgeGraphNodeUpdate `json:"updates" validate:"required"` } StartBrandScanJobReq { GraphID string `json:"graph_id,optional"` NodeIDs []string `json:"node_ids,optional"` DualTrack bool `json:"dual_track,optional"` PatrolMode bool `json:"patrol_mode,optional"` PatrolKeywords []string `json:"patrol_keywords,optional"` } StartBrandScanJobData { JobID string `json:"job_id"` Status string `json:"status"` Message string `json:"message"` } ListBrandScanPostsReq { Priority string `form:"priority,optional"` Recent7d bool `form:"recent_7d,optional"` ProductFitMin int `form:"product_fit_min,optional"` Limit int `form:"limit,optional"` } ScanPostData { ID string `json:"id"` GraphNodeID string `json:"graph_node_id"` SearchTag string `json:"search_tag"` QueryDimension string `json:"query_dimension"` ExternalID string `json:"external_id"` Permalink string `json:"permalink"` Author string `json:"author"` Text string `json:"text"` Priority string `json:"priority"` PlacementScore int `json:"placement_score"` ProductFitScore int `json:"product_fit_score"` SolvedByProduct bool `json:"solved_by_product"` Source string `json:"source"` ScanJobID string `json:"scan_job_id"` OutreachStatus string `json:"outreach_status,omitempty"` PublishedReplyID string `json:"published_reply_id,omitempty"` PublishedPermalink string `json:"published_permalink,omitempty"` OutreachUpdateAt int64 `json:"outreach_update_at,omitempty"` PostedAt string `json:"posted_at,omitempty"` Replies []ScanReplyData `json:"replies,omitempty"` LatestDraft *GenerateOutreachDraftsData `json:"latest_draft,omitempty"` CreateAt int64 `json:"create_at"` } ListBrandScanPostsData { List []ScanPostData `json:"list"` Total int `json:"total"` } GenerateOutreachDraftsReq { ScanPostID string `json:"scan_post_id" validate:"required"` TopicID string `json:"topic_id,optional"` Count int `json:"count,optional"` VoicePersonaID string `json:"voice_persona_id,optional"` ProductID string `json:"product_id,optional"` } OutreachDraftItemData { Text string `json:"text"` Angle string `json:"angle"` Rationale string `json:"rationale"` } GenerateOutreachDraftsData { ID string `json:"id"` ScanPostID string `json:"scan_post_id"` Relevance float64 `json:"relevance"` Reason string `json:"reason"` Drafts []OutreachDraftItemData `json:"drafts"` CreateAt int64 `json:"create_at"` } PublishOutreachDraftReq { ScanPostID string `json:"scan_post_id" validate:"required"` Text string `json:"text" validate:"required"` Confirm bool `json:"confirm"` } PublishOutreachDraftData { ScanPostID string `json:"scan_post_id"` ReplyID string `json:"reply_id"` Permalink string `json:"permalink"` OutreachStatus string `json:"outreach_status"` PublishedPermalink string `json:"published_permalink"` Message string `json:"message"` } PatchScanPostOutreachReq { OutreachStatus *string `json:"outreach_status,optional"` } ContentMatrixRowData { SortOrder int `json:"sort_order"` SearchTag string `json:"search_tag"` Angle string `json:"angle"` Hook string `json:"hook"` Text string `json:"text"` ReferenceNotes string `json:"reference_notes"` SourcePermalinks []string `json:"source_permalinks"` Rationale string `json:"rationale"` } ContentMatrixData { ID string `json:"id,omitempty"` BrandID string `json:"brand_id"` Rows []ContentMatrixRowData `json:"rows"` GeneratedAt int64 `json:"generated_at"` CreateAt int64 `json:"create_at,omitempty"` UpdateAt int64 `json:"update_at,omitempty"` } GenerateContentMatrixReq { Count int `json:"count,optional"` } ScanReplyData { ExternalID string `json:"external_id,omitempty"` Author string `json:"author,omitempty"` Text string `json:"text"` Permalink string `json:"permalink,omitempty"` LikeCount int `json:"like_count,omitempty"` PostedAt string `json:"posted_at,omitempty"` } BrandScanScheduleData { ID string `json:"id,omitempty"` BrandID string `json:"brand_id"` Cron string `json:"cron"` Timezone string `json:"timezone"` Enabled bool `json:"enabled"` NextRunAt int64 `json:"next_run_at,omitempty"` LastRunAt int64 `json:"last_run_at,omitempty"` } UpsertBrandScanScheduleReq { Cron string `json:"cron,optional"` Timezone string `json:"timezone,optional"` Enabled bool `json:"enabled"` } UpdateBrandHandlerReq { BrandPath UpdateBrandReq } ExpandKnowledgeGraphHandlerReq { BrandPath ExpandKnowledgeGraphReq } PatchKnowledgeGraphNodesHandlerReq { BrandPath PatchKnowledgeGraphNodesReq } StartBrandScanJobHandlerReq { BrandPath StartBrandScanJobReq } ListBrandScanPostsHandlerReq { BrandPath ListBrandScanPostsReq } GenerateOutreachDraftsHandlerReq { BrandPath GenerateOutreachDraftsReq } PublishOutreachDraftHandlerReq { BrandPath PublishOutreachDraftReq } PatchScanPostOutreachHandlerReq { BrandPath PostID string `path:"postId"` PatchScanPostOutreachReq } GenerateContentMatrixHandlerReq { BrandPath GenerateContentMatrixReq } UpsertBrandScanScheduleHandlerReq { BrandPath UpsertBrandScanScheduleReq } ) @server( group: brand prefix: /api/v1/brands middleware: AuthJWT tags: "Brand" summary: "Brand profiles for placement workflow. Requires Bearer JWT." ) service gateway { @handler listBrands get / returns (ListBrandsData) @handler createBrand post / (CreateBrandReq) returns (BrandData) @handler getBrand get /:id (BrandPath) returns (BrandData) @handler updateBrand patch /:id (UpdateBrandHandlerReq) returns (BrandData) @handler deleteBrand delete /:id (BrandPath) @handler listBrandProducts get /:id/products (BrandPath) returns (ListBrandProductsData) @handler createBrandProduct post /:id/products (CreateBrandProductHandlerReq) returns (BrandProductData) @handler updateBrandProduct patch /:id/products/:productId (UpdateBrandProductHandlerReq) returns (BrandProductData) @handler deleteBrandProduct delete /:id/products/:productId (BrandProductPath) @handler expandKnowledgeGraph post /:id/knowledge-graph/expand (ExpandKnowledgeGraphHandlerReq) returns (ExpandKnowledgeGraphData) @handler getKnowledgeGraph get /:id/knowledge-graph (BrandPath) returns (KnowledgeGraphData) @handler patchKnowledgeGraphNodes patch /:id/knowledge-graph/nodes (PatchKnowledgeGraphNodesHandlerReq) returns (KnowledgeGraphData) @handler startBrandScanJob post /:id/scan-jobs (StartBrandScanJobHandlerReq) returns (StartBrandScanJobData) @handler listBrandScanPosts get /:id/scan-posts (ListBrandScanPostsHandlerReq) returns (ListBrandScanPostsData) @handler generateOutreachDrafts post /:id/outreach-drafts/generate (GenerateOutreachDraftsHandlerReq) returns (GenerateOutreachDraftsData) @handler publishOutreachDraft post /:id/outreach-drafts/publish (PublishOutreachDraftHandlerReq) returns (PublishOutreachDraftData) @handler patchScanPostOutreach patch /:id/scan-posts/:postId (PatchScanPostOutreachHandlerReq) returns (ScanPostData) @handler getBrandContentMatrix get /:id/content-matrix (BrandPath) returns (ContentMatrixData) @handler generateBrandContentMatrix post /:id/content-matrix/generate (GenerateContentMatrixHandlerReq) returns (ContentMatrixData) @handler getBrandScanSchedule get /:id/scan-schedule (BrandPath) returns (BrandScanScheduleData) @handler upsertBrandScanSchedule put /:id/scan-schedule (UpsertBrandScanScheduleHandlerReq) returns (BrandScanScheduleData) }