635 lines
25 KiB
Plaintext
635 lines
25 KiB
Plaintext
syntax = "v1"
|
||
|
||
// demand-radar: service profile / radar watches / sweeps / opportunities / replies
|
||
// spec: docs/product/demand-radar/spec.md §5.2
|
||
// 未實作能力一律回 501(radarDomain.ErrNotReady),禁止 102000 空成功。
|
||
|
||
type (
|
||
// ---------- ServiceProfile ----------
|
||
ServiceItem {
|
||
Name string `json:"name"`
|
||
PriceMin float64 `json:"price_min,optional"`
|
||
PriceMax float64 `json:"price_max,optional"`
|
||
Currency string `json:"currency,optional"`
|
||
}
|
||
|
||
ServiceCasePublic {
|
||
Title string `json:"title"`
|
||
Summary string `json:"summary,optional"`
|
||
Link string `json:"link,optional"`
|
||
}
|
||
|
||
FaqItem {
|
||
Question string `json:"question"`
|
||
Answer string `json:"answer"`
|
||
}
|
||
|
||
ServiceProfilePublic {
|
||
Exists bool `json:"exists"`
|
||
Services []ServiceItem `json:"services"`
|
||
Cases []ServiceCasePublic `json:"cases"`
|
||
Forbidden []string `json:"forbidden"`
|
||
Faq []FaqItem `json:"faq"`
|
||
ServiceAreas []string `json:"service_areas"`
|
||
RemoteOk bool `json:"remote_ok"`
|
||
Availability string `json:"availability,optional"`
|
||
ToneNote string `json:"tone_note,optional"`
|
||
UpdatedAt int64 `json:"updated_at,optional"`
|
||
}
|
||
|
||
UpsertServiceProfileReq {
|
||
Services []ServiceItem `json:"services"`
|
||
Cases []ServiceCasePublic `json:"cases,optional"`
|
||
Forbidden []string `json:"forbidden,optional"`
|
||
Faq []FaqItem `json:"faq,optional"`
|
||
ServiceAreas []string `json:"service_areas,optional"`
|
||
RemoteOk bool `json:"remote_ok,optional"`
|
||
Availability string `json:"availability,optional"`
|
||
ToneNote string `json:"tone_note,optional"`
|
||
}
|
||
|
||
// ---------- RadarWatch ----------
|
||
RadarWatchPublic {
|
||
Id string `json:"id"`
|
||
Terms []string `json:"terms"`
|
||
ExcludeTerms []string `json:"exclude_terms"`
|
||
Regions []string `json:"regions"`
|
||
Status string `json:"status"` // active | paused | archived
|
||
ContextMode string `json:"context_mode"` // generic | product
|
||
BrandId string `json:"brand_id,optional"`
|
||
ProductId string `json:"product_id,optional"`
|
||
BrandNameSnapshot string `json:"brand_name_snapshot,optional"`
|
||
ProductLabelSnapshot string `json:"product_label_snapshot,optional"`
|
||
ContextBoundAt int64 `json:"context_bound_at,optional"`
|
||
PauseReason string `json:"pause_reason,optional"`
|
||
LastSweptAt int64 `json:"last_swept_at,optional"`
|
||
CreatedAt int64 `json:"created_at"`
|
||
UpdatedAt int64 `json:"updated_at"`
|
||
// 只在建立當下這是使用者第一組訂閱、且已排入首巡時為 true;不是持久狀態,僅供前端顯示一次性提示。
|
||
FirstSweepTriggered bool `json:"first_sweep_triggered,optional"`
|
||
}
|
||
|
||
ListWatchesReq {
|
||
Page int `form:"page,default=1"`
|
||
PageSize int `form:"pageSize,default=20"`
|
||
Status string `form:"status,optional"`
|
||
ContextMode string `form:"context_mode,optional"`
|
||
BrandId string `form:"brand_id,optional"`
|
||
ProductId string `form:"product_id,optional"`
|
||
}
|
||
|
||
WatchListData {
|
||
List []RadarWatchPublic `json:"list"`
|
||
Pagination Pagination `json:"pagination"`
|
||
ActiveCount int `json:"active_count"`
|
||
MaxActive int `json:"max_active"`
|
||
ProfileExists bool `json:"profile_exists"`
|
||
}
|
||
|
||
CreateWatchReq {
|
||
Terms []string `json:"terms"`
|
||
ExcludeTerms []string `json:"exclude_terms,optional"`
|
||
Regions []string `json:"regions,optional"`
|
||
Enabled bool `json:"enabled,optional"`
|
||
BrandId string `json:"brand_id,optional"`
|
||
ProductId string `json:"product_id,optional"`
|
||
}
|
||
|
||
UpdateWatchReq {
|
||
Id string `path:"id"`
|
||
Terms []string `json:"terms,optional"`
|
||
ExcludeTerms []string `json:"exclude_terms,optional"`
|
||
Regions []string `json:"regions,optional"`
|
||
}
|
||
|
||
WatchIdReq {
|
||
Id string `path:"id"`
|
||
}
|
||
|
||
AssignProductReq {
|
||
Id string `path:"id"`
|
||
BrandId string `json:"brand_id"`
|
||
ProductId string `json:"product_id"`
|
||
}
|
||
|
||
SuggestWatchTermsReq {
|
||
Limit int `json:"limit,optional"`
|
||
BrandId string `json:"brand_id,optional"`
|
||
ProductId string `json:"product_id,optional"`
|
||
}
|
||
|
||
WatchTermSuggestion {
|
||
Term string `json:"term"`
|
||
Reason string `json:"reason"`
|
||
Usage string `json:"usage"` // include | exclude
|
||
BasisKind string `json:"basis_kind,optional"`
|
||
BasisText string `json:"basis_text,optional"`
|
||
}
|
||
|
||
WatchSuggestData {
|
||
List []WatchTermSuggestion `json:"list"`
|
||
}
|
||
|
||
TriggerSweepData {
|
||
JobId string `json:"job_id"`
|
||
SweepId string `json:"sweep_id,optional"`
|
||
}
|
||
|
||
// ---------- Opportunity ----------
|
||
OpportunityReason {
|
||
Dimension string `json:"dimension"` // authenticity | intent | region | freshness | fit
|
||
Score int `json:"score"`
|
||
Reason string `json:"reason"`
|
||
}
|
||
|
||
OpportunityOverride {
|
||
FromBand string `json:"from_band,optional"`
|
||
ToBand string `json:"to_band,optional"`
|
||
FromStatus string `json:"from_status,optional"`
|
||
ToStatus string `json:"to_status,optional"`
|
||
ActorUid int64 `json:"actor_uid"`
|
||
At int64 `json:"at"`
|
||
}
|
||
|
||
ProductFitReasonPublic {
|
||
Dimension string `json:"dimension"` // pain | scenario | audience | capability
|
||
Score int `json:"score"`
|
||
Reason string `json:"reason"`
|
||
CandidateExcerpt string `json:"candidate_excerpt,optional"`
|
||
ProductBasis string `json:"product_basis,optional"`
|
||
}
|
||
|
||
ProductMatchPublic {
|
||
BrandId string `json:"brand_id"`
|
||
ProductId string `json:"product_id"`
|
||
BrandNameSnapshot string `json:"brand_name_snapshot"`
|
||
ProductLabelSnapshot string `json:"product_label_snapshot"`
|
||
BrandUpdatedAt int64 `json:"brand_updated_at"`
|
||
ProductUpdatedAt int64 `json:"product_updated_at"`
|
||
ProductFitScore int `json:"product_fit_score"`
|
||
ProductFitBand string `json:"product_fit_band"` // strong | possible | weak
|
||
Eligible bool `json:"eligible"`
|
||
Excluded bool `json:"excluded"`
|
||
ExcludeReason string `json:"exclude_reason,optional"`
|
||
Reasons []ProductFitReasonPublic `json:"reasons"`
|
||
Risks []string `json:"risks"`
|
||
WatchIds []string `json:"watch_ids"`
|
||
MatchedTerms []string `json:"matched_terms"`
|
||
MatchedAt int64 `json:"matched_at"`
|
||
}
|
||
|
||
OpportunityPublic {
|
||
Id string `json:"id"`
|
||
WatchId string `json:"watch_id,optional"`
|
||
Source string `json:"source"` // threads | manual | scout_promote
|
||
SourceScoutPostId string `json:"source_scout_post_id,optional"`
|
||
ExternalId string `json:"external_id"`
|
||
Permalink string `json:"permalink"`
|
||
AuthorHandle string `json:"author_handle"`
|
||
Text string `json:"text"`
|
||
PostedAt int64 `json:"posted_at"`
|
||
Status string `json:"status"` // judging | qualified | rejected | accepted | dismissed
|
||
IntentScore int `json:"intent_score"`
|
||
IntentBand string `json:"intent_band"` // high | mid | low
|
||
Reasons []OpportunityReason `json:"reasons"`
|
||
RegionDetected string `json:"region_detected,optional"`
|
||
RegionMatch string `json:"region_match"` // match | mismatch | unknown
|
||
FreshnessHours int `json:"freshness_hours"`
|
||
MatchedService string `json:"matched_service,optional"`
|
||
MatchedTerms []string `json:"matched_terms"`
|
||
RejectReason string `json:"reject_reason,optional"`
|
||
Override *OpportunityOverride `json:"override,optional"`
|
||
ContactId string `json:"contact_id,optional"`
|
||
DefaultReply *ReplyVariantPublic `json:"default_reply,optional"`
|
||
PrimaryBrandId string `json:"primary_brand_id,optional"`
|
||
PrimaryProductId string `json:"primary_product_id,optional"`
|
||
PrimaryBrandName string `json:"primary_brand_name,optional"`
|
||
PrimaryProductLabel string `json:"primary_product_label,optional"`
|
||
PrimaryProductFitScore int `json:"primary_product_fit_score,optional"`
|
||
PrimaryProductFitBand string `json:"primary_product_fit_band,optional"`
|
||
PrimaryProductOverridden bool `json:"primary_product_overridden,optional"`
|
||
ProductMatches []ProductMatchPublic `json:"product_matches"`
|
||
ReviewState string `json:"review_state"` // pending | completed | removed
|
||
PreviousReviewState string `json:"previous_review_state,optional"`
|
||
RemovalReason string `json:"removal_reason,optional"`
|
||
RemovalNote string `json:"removal_note,optional"`
|
||
RemovedAt int64 `json:"removed_at,optional"`
|
||
RemovedBy int64 `json:"removed_by,optional"`
|
||
LastMatchedAt int64 `json:"last_matched_at,optional"`
|
||
PriorityScore int `json:"priority_score"`
|
||
PriorityBand string `json:"priority_band"` // high | review | low
|
||
PainFitScore int `json:"pain_fit_score,optional"`
|
||
DemandIntentScore int `json:"demand_intent_score,optional"`
|
||
EvidenceQualityScore int `json:"evidence_quality_score,optional"`
|
||
FreshnessScore int `json:"freshness_score,optional"`
|
||
DemandEvidence []string `json:"demand_evidence,optional"`
|
||
DemandInputVersion string `json:"demand_input_version,optional"`
|
||
DemandMapVersion int64 `json:"demand_map_version,optional"`
|
||
CreatedAt int64 `json:"created_at"`
|
||
}
|
||
|
||
RadarTodayStats {
|
||
Total int `json:"total"`
|
||
High int `json:"high"`
|
||
Mid int `json:"mid"`
|
||
Low int `json:"low"`
|
||
}
|
||
|
||
RadarTodayData {
|
||
Stats RadarTodayStats `json:"stats"`
|
||
High []OpportunityPublic `json:"high"`
|
||
Mid []OpportunityPublic `json:"mid"`
|
||
Low []OpportunityPublic `json:"low"`
|
||
TruncatedCount int `json:"truncated_count"`
|
||
LastSweptAt int64 `json:"last_swept_at,optional"`
|
||
// EmptyReason: not_swept_yet | all_watches_paused | no_watch | no_profile | sweep_failed | no_hit | no_eligible_product_match
|
||
EmptyReason string `json:"empty_reason,optional"`
|
||
EmptyHint string `json:"empty_hint,optional"`
|
||
}
|
||
|
||
RadarTodayReq {
|
||
BrandId string `form:"brand_id,optional"`
|
||
ProductId string `form:"product_id,optional"`
|
||
FitBand string `form:"fit_band,optional"`
|
||
}
|
||
|
||
ListOpportunitiesReq {
|
||
Page int `form:"page,default=1"`
|
||
PageSize int `form:"pageSize,default=20"`
|
||
Band string `form:"band,optional"`
|
||
Status string `form:"status,optional"`
|
||
WatchId string `form:"watch_id,optional"`
|
||
BrandId string `form:"brand_id,optional"`
|
||
ProductId string `form:"product_id,optional"`
|
||
FitBand string `form:"fit_band,optional"`
|
||
MatchState string `form:"match_state,optional"`
|
||
ReviewState string `form:"review_state,optional"`
|
||
TimeScope string `form:"time_scope,optional"` // today | 7d | all
|
||
PriorityBand string `form:"priority_band,optional"` // high | review | low
|
||
Sort string `form:"sort,optional"`
|
||
From int64 `form:"from,optional"`
|
||
To int64 `form:"to,optional"`
|
||
}
|
||
|
||
OpportunityListData {
|
||
List []OpportunityPublic `json:"list"`
|
||
Pagination Pagination `json:"pagination"`
|
||
}
|
||
|
||
OpportunityIdReq {
|
||
Id string `path:"id"`
|
||
}
|
||
|
||
AcceptOpportunityReq {
|
||
Id string `path:"id"`
|
||
}
|
||
|
||
AcceptOpportunityData {
|
||
OpportunityId string `json:"opportunity_id"`
|
||
ContactId string `json:"contact_id,optional"`
|
||
Status string `json:"status"`
|
||
}
|
||
|
||
DismissOpportunityReq {
|
||
Id string `path:"id"`
|
||
Reason string `json:"reason,optional"`
|
||
}
|
||
|
||
ReviewStateReq {
|
||
Id string `path:"id"`
|
||
State string `json:"state"` // pending | completed | removed
|
||
RemovalReason string `json:"removal_reason,optional"`
|
||
RemovalNote string `json:"removal_note,optional"`
|
||
DuplicateOpportunityId string `json:"duplicate_of_opportunity_id,optional"`
|
||
}
|
||
|
||
DemandMapProductReq {
|
||
ProductId string `path:"productId"`
|
||
}
|
||
|
||
DemandMapPhrase {
|
||
Text string `json:"text"`
|
||
Kind string `json:"kind"`
|
||
BasisKind string `json:"basis_kind,optional"`
|
||
BasisText string `json:"basis_text,optional"`
|
||
Origin string `json:"origin"` // product | user | ai
|
||
Enabled bool `json:"enabled"`
|
||
}
|
||
|
||
DemandMapPublic {
|
||
ProductId string `json:"product_id"`
|
||
DemandInputVersion string `json:"demand_input_version"`
|
||
MapVersion int64 `json:"map_version"`
|
||
State string `json:"state"` // ready | incomplete | stale
|
||
PainPhrases []DemandMapPhrase `json:"pain_phrases"`
|
||
ScenarioPhrases []DemandMapPhrase `json:"scenario_phrases"`
|
||
DesiredOutcomes []DemandMapPhrase `json:"desired_outcomes"`
|
||
SolutionSignals []DemandMapPhrase `json:"solution_signals"`
|
||
ExclusionSignals []DemandMapPhrase `json:"exclusion_signals"`
|
||
SourceBasis []string `json:"source_basis"`
|
||
CustomPhrases []DemandMapPhrase `json:"custom_phrases"`
|
||
AiEnrichedAt int64 `json:"ai_enriched_at,optional"`
|
||
UpdatedAt int64 `json:"updated_at"`
|
||
}
|
||
|
||
UpdateDemandMapReq {
|
||
ProductId string `path:"productId"`
|
||
ExpectedMapVersion int64 `json:"expected_map_version"`
|
||
PainPhrases []DemandMapPhrase `json:"pain_phrases,optional"`
|
||
ScenarioPhrases []DemandMapPhrase `json:"scenario_phrases,optional"`
|
||
DesiredOutcomes []DemandMapPhrase `json:"desired_outcomes,optional"`
|
||
SolutionSignals []DemandMapPhrase `json:"solution_signals,optional"`
|
||
ExclusionSignals []DemandMapPhrase `json:"exclusion_signals,optional"`
|
||
CustomPhrases []DemandMapPhrase `json:"custom_phrases,optional"`
|
||
}
|
||
|
||
CostPreviewReq {
|
||
Action string `form:"action"` // sweep | explore | demand_map_enrich | reply
|
||
WatchId string `form:"watch_id,optional"`
|
||
ProductId string `form:"product_id,optional"`
|
||
CandidateLimit int `form:"candidate_limit,optional"`
|
||
}
|
||
|
||
CostPreviewPublic {
|
||
PreviewId string `json:"preview_id"`
|
||
Action string `json:"action"`
|
||
KeyMode string `json:"key_mode"` // platform | byok
|
||
FixedCredits int `json:"fixed_credits"`
|
||
MinCredits int `json:"min_credits"`
|
||
MaxCredits int `json:"max_credits"`
|
||
SearchCalls int `json:"search_calls"`
|
||
MaxAiCandidates int `json:"max_ai_candidates"`
|
||
RemainingCredits int `json:"remaining_credits"`
|
||
EstimateBasis string `json:"estimate_basis"`
|
||
ExpiresAt int64 `json:"expires_at"`
|
||
}
|
||
|
||
EnrichDemandMapReq {
|
||
ProductId string `path:"productId"`
|
||
PreviewId string `json:"preview_id"`
|
||
CreditCeiling int `json:"credit_ceiling"`
|
||
ExpectedMapVersion int64 `json:"expected_map_version"`
|
||
}
|
||
|
||
OverrideOpportunityReq {
|
||
Id string `path:"id"`
|
||
Band string `json:"band,optional"`
|
||
Status string `json:"status,optional"`
|
||
Note string `json:"note,optional"`
|
||
}
|
||
|
||
SetPrimaryProductReq {
|
||
Id string `path:"id"`
|
||
ProductId string `json:"product_id"`
|
||
Reason string `json:"reason"`
|
||
}
|
||
|
||
// ---------- ReplyVariant ----------
|
||
ReplyVariantPublic {
|
||
Id string `json:"id"`
|
||
OpportunityId string `json:"opportunity_id"`
|
||
Variant string `json:"variant"` // public_comment | dm | no_sales | professional | humorous
|
||
Text string `json:"text"`
|
||
UsedAt int64 `json:"used_at,optional"`
|
||
SentChannel string `json:"sent_channel,optional"` // outbox | manual_copy
|
||
// 只在 sent_channel=outbox 且真的排入既有 Outbox 佇列時才有值。
|
||
OutboxId string `json:"outbox_id,optional"`
|
||
CreatedAt int64 `json:"created_at"`
|
||
}
|
||
|
||
ListRepliesReq {
|
||
Id string `path:"id"`
|
||
}
|
||
|
||
ReplyListData {
|
||
List []ReplyVariantPublic `json:"list"`
|
||
}
|
||
|
||
CreateReplyReq {
|
||
Id string `path:"id"`
|
||
Variant string `json:"variant"`
|
||
}
|
||
|
||
// MarkReplyUsedReq: channel=outbox|manual_copy(dm 僅 manual_copy)
|
||
MarkReplyUsedReq {
|
||
Id string `path:"id"`
|
||
ReplyId string `path:"replyId"`
|
||
Channel string `json:"channel"` // outbox | manual_copy
|
||
// channel=outbox 時必填:要用哪個 Threads 帳號送出。
|
||
AccountId string `json:"account_id,optional"`
|
||
}
|
||
|
||
MarkReplyUsedData {
|
||
Reply ReplyVariantPublic `json:"reply"`
|
||
HealthAdvice string `json:"health_advice,optional"`
|
||
}
|
||
|
||
// ---------- RadarSweep ----------
|
||
RadarSweepPublic {
|
||
Id string `json:"id"`
|
||
WatchId string `json:"watch_id"`
|
||
JobId string `json:"job_id,optional"`
|
||
Path string `json:"path"` // api | crawler
|
||
HitCount int `json:"hit_count"`
|
||
JudgedCount int `json:"judged_count"`
|
||
CreatedCount int `json:"created_count"`
|
||
TruncatedCount int `json:"truncated_count"`
|
||
MatchEvaluatedCount int `json:"match_evaluated_count"`
|
||
MatchMergedCount int `json:"match_merged_count"`
|
||
FitRejectedCount int `json:"fit_rejected_count"`
|
||
FailedReason string `json:"failed_reason,optional"`
|
||
CreditsUsed int `json:"credits_used"`
|
||
StartedAt int64 `json:"started_at"`
|
||
EndedAt int64 `json:"ended_at,optional"`
|
||
DemandInputVersion string `json:"demand_input_version,optional"`
|
||
DemandMapVersion int64 `json:"demand_map_version,optional"`
|
||
DedupedCount int `json:"deduped_count"`
|
||
PrefilterPassCount int `json:"prefilter_pass_count"`
|
||
PrefilterReviewCount int `json:"prefilter_review_count"`
|
||
PrefilterRejectedCount int `json:"prefilter_rejected_count"`
|
||
CachedJudgmentCount int `json:"cached_judgment_count"`
|
||
TombstoneMatchedCount int `json:"tombstone_matched_count"`
|
||
BudgetDeferredCount int `json:"budget_deferred_count"`
|
||
SweepStatus string `json:"status"` // complete | partial_budget | blocked_budget | failed
|
||
CreditSearch int `json:"credit_search"`
|
||
CreditDemandMap int `json:"credit_demand_map"`
|
||
CreditJudge int `json:"credit_judge"`
|
||
CreditReply int `json:"credit_reply"`
|
||
}
|
||
|
||
ListSweepsReq {
|
||
Page int `form:"page,default=1"`
|
||
PageSize int `form:"pageSize,default=20"`
|
||
WatchId string `form:"watch_id,optional"`
|
||
From int64 `form:"from,optional"`
|
||
To int64 `form:"to,optional"`
|
||
}
|
||
|
||
SweepListData {
|
||
List []RadarSweepPublic `json:"list"`
|
||
Pagination Pagination `json:"pagination"`
|
||
}
|
||
|
||
// ---------- Manual Import(P1:不承諾全平台自動抓取的合規補位) ----------
|
||
ImportOpportunityItem {
|
||
Url string `json:"url"`
|
||
// 貼文內文;沒有官方 API/爬蟲可讀任意網址,判定一律吃使用者貼上的文字。
|
||
Text string `json:"text"`
|
||
// 缺省時從 threads 網址猜 @handle,猜不到就留空。
|
||
Author string `json:"author,optional"`
|
||
// unix nanoseconds UTC;缺省用匯入當下時間(新鮮度以匯入時間計)。
|
||
PostedAt int64 `json:"posted_at,optional"`
|
||
}
|
||
|
||
ImportOpportunitiesReq {
|
||
Items []ImportOpportunityItem `json:"items"`
|
||
BrandId string `json:"brand_id,optional"`
|
||
ProductId string `json:"product_id,optional"`
|
||
}
|
||
|
||
ImportedOpportunityResult {
|
||
Url string `json:"url"`
|
||
OpportunityId string `json:"opportunity_id,optional"`
|
||
Status string `json:"status"` // qualified | rejected | skipped | failed
|
||
IntentBand string `json:"intent_band,optional"`
|
||
IntentScore int `json:"intent_score,optional"`
|
||
// skipped/failed 時的人話原因;qualified/rejected 時通常留空。
|
||
Error string `json:"error,optional"`
|
||
}
|
||
|
||
ImportOpportunitiesData {
|
||
Results []ImportedOpportunityResult `json:"results"`
|
||
}
|
||
|
||
// ---------- Explore(商機頁立即探索:短詞 fan-out → 五問判定) ----------
|
||
ExploreOpportunitiesReq {
|
||
// 1–6 組 Threads 短詞(契約 A);不合規整組擋下,不默默修正。
|
||
Terms []string `json:"terms"`
|
||
BrandId string `json:"brand_id,optional"`
|
||
ProductId string `json:"product_id,optional"`
|
||
PreviewId string `json:"preview_id,optional"`
|
||
CreditCeiling int `json:"credit_ceiling,optional"`
|
||
DemandInputVersion string `json:"demand_input_version,optional"`
|
||
DemandMapVersion int64 `json:"demand_map_version,optional"`
|
||
}
|
||
|
||
ExploreOpportunitiesData {
|
||
SweepId string `json:"sweep_id"`
|
||
HitCount int `json:"hit_count"`
|
||
JudgedCount int `json:"judged_count"`
|
||
CreatedCount int `json:"created_count"`
|
||
MatchedCount int `json:"matched_count"`
|
||
MergedCount int `json:"merged_count"`
|
||
TruncatedCount int `json:"truncated_count"`
|
||
CreditsUsed int `json:"credits_used"`
|
||
DedupedCount int `json:"deduped_count"`
|
||
PrefilterPassCount int `json:"prefilter_pass_count"`
|
||
PrefilterReviewCount int `json:"prefilter_review_count"`
|
||
PrefilterRejectedCount int `json:"prefilter_rejected_count"`
|
||
CachedJudgmentCount int `json:"cached_judgment_count"`
|
||
TombstoneMatchedCount int `json:"tombstone_matched_count"`
|
||
BudgetDeferredCount int `json:"budget_deferred_count"`
|
||
SweepStatus string `json:"status"`
|
||
}
|
||
)
|
||
|
||
@server (
|
||
group: radar
|
||
prefix: /api/v1/radar
|
||
middleware: AuthJWT
|
||
)
|
||
service gateway {
|
||
@handler GetServiceProfile
|
||
get /service-profile returns (ServiceProfilePublic)
|
||
|
||
@handler UpsertServiceProfile
|
||
put /service-profile (UpsertServiceProfileReq) returns (ServiceProfilePublic)
|
||
|
||
@handler ListWatches
|
||
get /watches (ListWatchesReq) returns (WatchListData)
|
||
|
||
@handler CreateWatch
|
||
post /watches (CreateWatchReq) returns (RadarWatchPublic)
|
||
|
||
@handler SuggestWatchTerms
|
||
post /watches/suggest (SuggestWatchTermsReq) returns (WatchSuggestData)
|
||
|
||
@handler AssignWatchProduct
|
||
post /watches/:id/assign-product (AssignProductReq) returns (RadarWatchPublic)
|
||
|
||
@handler GetWatch
|
||
get /watches/:id (WatchIdReq) returns (RadarWatchPublic)
|
||
|
||
@handler UpdateWatch
|
||
put /watches/:id (UpdateWatchReq) returns (RadarWatchPublic)
|
||
|
||
@handler ArchiveWatch
|
||
delete /watches/:id (WatchIdReq) returns (OkData)
|
||
|
||
@handler DeleteArchivedWatch
|
||
delete /watches/:id/purge (WatchIdReq) returns (OkData)
|
||
|
||
@handler PauseWatch
|
||
post /watches/:id/pause (WatchIdReq) returns (RadarWatchPublic)
|
||
|
||
@handler ResumeWatch
|
||
post /watches/:id/resume (WatchIdReq) returns (RadarWatchPublic)
|
||
|
||
@handler TriggerWatchSweep
|
||
post /watches/:id/sweep (WatchIdReq) returns (TriggerSweepData)
|
||
|
||
@handler GetRadarToday
|
||
get /today (RadarTodayReq) returns (RadarTodayData)
|
||
|
||
@handler ListOpportunities
|
||
get /opportunities (ListOpportunitiesReq) returns (OpportunityListData)
|
||
|
||
@handler GetOpportunity
|
||
get /opportunities/:id (OpportunityIdReq) returns (OpportunityPublic)
|
||
|
||
@handler AcceptOpportunity
|
||
post /opportunities/:id/accept (AcceptOpportunityReq) returns (AcceptOpportunityData)
|
||
|
||
@handler DismissOpportunity
|
||
post /opportunities/:id/dismiss (DismissOpportunityReq) returns (OpportunityPublic)
|
||
|
||
@handler UpdateOpportunityReviewState
|
||
put /opportunities/:id/review-state (ReviewStateReq) returns (OpportunityPublic)
|
||
|
||
@handler OverrideOpportunity
|
||
post /opportunities/:id/override (OverrideOpportunityReq) returns (OpportunityPublic)
|
||
|
||
@handler SetPrimaryProduct
|
||
put /opportunities/:id/primary-product (SetPrimaryProductReq) returns (OpportunityPublic)
|
||
|
||
@handler GetDemandMap
|
||
get /products/:productId/demand-map (DemandMapProductReq) returns (DemandMapPublic)
|
||
|
||
@handler UpdateDemandMap
|
||
put /products/:productId/demand-map (UpdateDemandMapReq) returns (DemandMapPublic)
|
||
|
||
@handler EnrichDemandMap
|
||
post /products/:productId/demand-map/enrich (EnrichDemandMapReq) returns (DemandMapPublic)
|
||
|
||
@handler GetRadarCostPreview
|
||
get /cost-preview (CostPreviewReq) returns (CostPreviewPublic)
|
||
|
||
@handler ListOpportunityReplies
|
||
get /opportunities/:id/replies (ListRepliesReq) returns (ReplyListData)
|
||
|
||
@handler CreateOpportunityReply
|
||
post /opportunities/:id/replies (CreateReplyReq) returns (ReplyVariantPublic)
|
||
|
||
@handler MarkOpportunityReplyUsed
|
||
post /opportunities/:id/replies/:replyId/mark-used (MarkReplyUsedReq) returns (MarkReplyUsedData)
|
||
|
||
@handler ListSweeps
|
||
get /sweeps (ListSweepsReq) returns (SweepListData)
|
||
|
||
@handler ImportOpportunities
|
||
post /import (ImportOpportunitiesReq) returns (ImportOpportunitiesData)
|
||
|
||
@handler ExploreOpportunities
|
||
post /explore (ExploreOpportunitiesReq) returns (ExploreOpportunitiesData)
|
||
}
|