开放 API

把 QueryWin 接进你自己的流程

QueryWin 找出你的网站已经有曝光、却没有一页在承接的搜索词并把缺的那篇写出来;同时为你的产品备好投向目录、启动平台、社区与被 AI 引用站点的素材。这套接口把两条流程都交到你的脚本和 AI 助手手里。发布与投递仍用你自己的凭据与账号完成 —— QueryWin 不接你的 CMS,也不代你向任何站点投递。

Base URLhttps://www.querywin.com/api创建密钥OpenAPI 规范(JSON) →

快速开始

三步接入。下面所有调用都是普通 REST 请求,只需要一个请求头。

1

创建密钥

在工作台的「开放 API」里创建。明文只在创建那一次显示。按需勾选权限 —— 什么都不勾建出来的是一把只读密钥。

2

放进请求头

每次请求都带 Authorization: Bearer qw_live_…。只允许配置一个请求头的工具可以改用 X-API-Key。

3

读该写哪一篇,再取草稿

选题清单免费,不消耗积分。生成大纲或正文会扣积分,且要求密钥带 spend 权限。

bash
# 1. 该密钥可操作哪些网站
curl "https://www.querywin.com/api/v1/sites" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"

# 2. 本周该写哪一篇(免费,不消耗积分)
curl "https://www.querywin.com/api/v1/topics?siteId=YOUR_SITE_ID" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
bash
# 3. 取该篇的正文草稿(Markdown + 已填好数据的 JSON-LD)
curl "https://www.querywin.com/api/v1/topics/article?siteId=YOUR_SITE_ID&key=standard%20wardrobe%20depth" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"

# 4. 由你的脚本发布到自己的网站,再回写发布地址
curl -X POST https://www.querywin.com/api/v1/topics/published \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": "YOUR_SITE_ID",
    "key": "standard wardrobe depth",
    "url": "https://example.com/blog/standard-wardrobe-depth"
  }'

所有响应都带一层外壳:{"success": true, "data": …}。错误一律返回代码而不是句子 —— QueryWin 是中英双语站,后端拼的英文句子会原样印在中文页面上。

内容链

五步,其中只有两步花钱。第 4 步是你自己的:QueryWin 把正文与结构化数据交给你,由你发布。

步骤接口成本
找出有曝光但没有页面承接的词GET /v1/topics免费
生成有据可依的大纲POST /v1/topics/outline扣积分
写成可发布的正文草稿POST /v1/topics/article扣积分
发布到你自己的网站你自己的后台—
回写发布地址POST /v1/topics/published免费

QueryWin 不接你的 CMS、不持有你的网站凭据、不代你按发布键。这套接口交给你的是内容,写入发生在你自己的机器上、用你自己的凭据。这是边界本身,不是绕过边界的口子。

分发链

七步,其中只有一步花钱。第 6 步是你自己的:QueryWin 把每个渠道的投递素材交给你,由你 —— 或你的 agent,用你自己的账号 —— 投递。之后每条已上线的条目由 QueryWin 自行回查。

步骤接口成本
列出产品与各自的档案完整度GET /v1/products免费
列出可投递的入口,按匹配度排序 —— 含被 AI 答案引用的站点GET /v1/channels?productId=免费
按你选定的渠道建计划POST /v1/campaigns免费
取一条任务已备好的素材GET /v1/tasks/{id}免费
为该渠道改写素材POST /v1/tasks/{id}/materials扣积分
投递你自己的账号—
回写已提交,再回写已上线与上线地址POST /v1/tasks/{id}/status免费

published 是你回写的;verified 是 QueryWin 在约 72 小时后回查上线页面时看到的 —— 目录与 AI 工具榜看指向产品的链接,其余看品牌提及。两者是各自独立的字段。被 AI 答案引用的站点(citedByAi)值得去争取,但那不是它会收录你的承诺。

权限

每把密钥带着创建时授予的权限。GET /v1/usage 会把它们报出来,你不必靠撞 403 才发现自己没权限。

read

始终包含

全部只读接口:站点、选题清单、大纲、正文草稿、产品、渠道、分发计划、任务及其素材、用量。

publish

默认关闭

创建和更新产品档案、导入图片,以及记录发生了什么:文章的发布地址(同时推送到 Bing、Yandex、Seznam、Naver,不含 Google)、新建分发计划、把任务标为已提交或已上线。免费,但每一条都是有后果的记录:计划占用档位配额,已上线的条目会被回查。

spend

默认关闭

生成大纲与正文草稿、为渠道改写投递素材,会扣积分。只有当你希望调用方 —— 脚本或 AI 助手 —— 能自行发起扣费时才授予。

三者之间没有层级:publish 不蕴含 spend,spend 也不蕴含 publish,它们是两种不同的风险。调用密钥没有对应权限的接口会返回 403,错误码为 missing_scope_<权限名>,并带上这把密钥实际拥有的权限。

积分消耗

会扣积分的只有两个接口:POST /v1/topics/outline 与 POST /v1/topics/article。它们前面有三道闸。

闸门挡住什么
confirmSpend价格上调之后,老脚本仍然闷头扣费。
每日上限脚本写出死循环,一夜之间把余额烧光。触发后返回 429,并给出恢复时间。
输入指纹同一条选题被重复收费。输入不变时直接返回缓存结果且不收费,所以请求超时后重试是安全的。

confirmSpend 是授权上限,不是精确金额。传一个不小于当前单价的数即可,实际花多少扣多少 —— 命中缓存时往往为 0。一旦价格涨到超过你的上限,请求会以 confirm_spend_too_low 失败,而不是悄悄多扣。

通用约定

三件事在所有接口上都成立。

响应外壳

json
{ "success": true,  "data": { "...": "..." } }
{ "success": false, "error": "missing_scope_spend" }

错误一律是代码而不是句子。请读取它并映射成你自己的文案,不要原样展示给终端用户。

业务结果不是错误

生成类接口没能产出有效结果时返回 HTTP 200,把 data.ok 置为 false 并给出 data.failure —— 这样你能把它和鉴权失败、连接中断区分开。这几种情况都不收费。

json
{
  "success": true,
  "data": { "ok": false, "failure": "no_outline", "creditsSpent": 0 }
}

请求频率

每把密钥每分钟 120 次。超出返回 429 并给出恢复时间。它与上面那道每日生成上限是两回事。

给 AI 助手用(MCP)

两条链都通过 Model Context Protocol 开放,认证用同一把密钥、同一个请求头。可以加进 Claude Code、Cursor、n8n,或任何支持 HTTP 方式 MCP 的工具。

MCPhttps://www.querywin.com/api/mcp
bash
claude mcp add --transport http querywin https://www.querywin.com/api/mcp \
  --header "Authorization: Bearer $QUERYWIN_API_KEY"

共十九个工具。产品档案:create_product、get_product、update_product、import_product_image。内容链:list_sites、get_usage、list_content_gaps、get_outline、get_article_draft、generate_outline、generate_article_draft、mark_published。分发链:list_products、list_channels、create_campaign、list_tasks、get_task、write_task_materials、report_task_status。问一句「我这周该写什么」或「产品下一步该投哪里」,助手会自己去查。

提示词
用 QueryWin MCP 服务查出我网站上最值得写的三条内容缺口,
列出每条背后的真实搜索词,并告诉我把排第一的那条写成草稿要花多少积分。

工具按权限过滤。使用只读密钥时,生成类工具根本不会出现在助手的工具列表里 —— 看不见的工具,助手无从调用。建议给助手单独建一把密钥,出问题时可以只吊销它,不影响你其它的接入。

认证方式是 bearer token,MCP 规范允许这样做(授权在规范里是可选项)。允许自定义请求头的客户端 —— Claude Code、Cursor、n8n —— 可以直接连;要求走 OAuth 授权弹窗的宿主则可能连不上。

Account

GET/v1/sites

该密钥可操作的网站清单

从这里开始。其余每个接口都要用本接口返回的 siteId。别处不传 siteId 时会回落到最早接入的那个网站 —— 单站账号无所谓,多站账号迟早要出事。

响应200

字段类型说明
successenum可选值:true
dataSiteList
└sitesarray<Site>
└siteIdstring
└domainstring
└gscPropertystringSearch Console 里的资源标识,原样返回:sc-domain:example.com 或 https://example.com/。
└syncStatusenum可选值:pendingsyncingdonefailed
└syncedThrough可为空stringSearch Console 的数据有 2–3 天延迟。这个网站上的每个指标都是「截至该日期」的 —— 你要是把这些数字展示出去,请一并说明这一点。
可能的错误
401密钥缺失、格式不对、已吊销或已过期

示例

bash
curl "https://www.querywin.com/api/v1/sites" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "sites": [
      {
        "siteId": "string",
        "domain": "example.com",
        "gscProperty": "string",
        "syncStatus": "pending",
        "syncedThrough": "2026-09-01T00:00:00.000Z"
      }
    ]
  }
}
GET/v1/usage

当前单价、免费额度、积分余额与每日上限

生成任何东西之前先读它。界面上按钮该显示什么,用的就是这同一个事实源 —— 能不能用由服务端判定,🚫 不要靠「试一次、失败了再说」。

响应200

字段类型说明
successenum可选值:true
dataUsage
└scopesarray<enum>这把密钥能做什么。启动时读一次,🚫 不要靠撞 403 才发现自己没权限。可选值:readpublishspend
└creditsobject
└balanceinteger
└outlineStepUsage
└availableboolean生成引擎未配置时为 false。此时不要调用对应的 POST 接口。
└pricePerOutlineinteger每份大纲消耗的积分(仅 outline 上有)。
└pricePerArticleinteger每篇正文消耗的积分(仅 article 上有)。
└pricePerTaskinteger每次渠道改写的积分(只在 materials 上有)。
└freeRemaininginteger该账号还剩多少次免费生成,按不同选题(大纲、正文)或不同任务(素材)计数,🚫 不是按点了几次按钮。免费生成同样要求传 confirmSpend。
└dailyDailyLimit防止脚本失控的兜底闸门,在数据库里跨所有入口计数(界面上的操作同样计入)。按本地时间零点归零,🚫 不是滑动窗口。
└usedinteger
└limitinteger
└remaininginteger
└resetAtstring
└articleStepUsage
└availableboolean生成引擎未配置时为 false。此时不要调用对应的 POST 接口。
└pricePerOutlineinteger每份大纲消耗的积分(仅 outline 上有)。
└pricePerArticleinteger每篇正文消耗的积分(仅 article 上有)。
└pricePerTaskinteger每次渠道改写的积分(只在 materials 上有)。
└freeRemaininginteger该账号还剩多少次免费生成,按不同选题(大纲、正文)或不同任务(素材)计数,🚫 不是按点了几次按钮。免费生成同样要求传 confirmSpend。
└dailyDailyLimit防止脚本失控的兜底闸门,在数据库里跨所有入口计数(界面上的操作同样计入)。按本地时间零点归零,🚫 不是滑动窗口。
└usedinteger
└limitinteger
└remaininginteger
└resetAtstring
└materialsStepUsage
└availableboolean生成引擎未配置时为 false。此时不要调用对应的 POST 接口。
└pricePerOutlineinteger每份大纲消耗的积分(仅 outline 上有)。
└pricePerArticleinteger每篇正文消耗的积分(仅 article 上有)。
└pricePerTaskinteger每次渠道改写的积分(只在 materials 上有)。
└freeRemaininginteger该账号还剩多少次免费生成,按不同选题(大纲、正文)或不同任务(素材)计数,🚫 不是按点了几次按钮。免费生成同样要求传 confirmSpend。
└dailyDailyLimit防止脚本失控的兜底闸门,在数据库里跨所有入口计数(界面上的操作同样计入)。按本地时间零点归零,🚫 不是滑动窗口。
└usedinteger
└limitinteger
└remaininginteger
└resetAtstring
└distributionDistributionQuota当前档位的分发上限与已用量。上限为 null 表示不限。
└planstring
└limitsobject
└channels可为空integer单个产品可投递的不同渠道数,按 channelsPeriod 的周期计。
└channelsPeriodenummonth(付费档):按自然月(UTC)计,每个月都可投一批新渠道。total(免费版):按该产品累计计。可选值:monthtotal
└tasksPerMonth可为空integer每个自然月(UTC)可新建的任务数,各产品合计。
└activeCampaigns可为空integer同时进行中的计划数。
└usageobject
└activeCampaignsinteger
└tasksThisMonthinteger
└channels可为空integer只在请求指定了产品时有值。
可能的错误
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/usage" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "scopes": [
      "read"
    ],
    "credits": {
      "balance": 0
    },
    "outline": {
      "available": true,
      "pricePerOutline": 0,
      "pricePerArticle": 0,
      "pricePerTask": 0,
      "freeRemaining": 0,
      "daily": {
        "used": 0,
        "limit": 0,
        "remaining": 0,
        "resetAt": "2026-09-01T00:00:00.000Z"
      }
    },
    "article": {
      "available": true,
      "pricePerOutline": 0,
      "pricePerArticle": 0,
      "pricePerTask": 0,
      "freeRemaining": 0,
      "daily": {
        "used": 0,
        "limit": 0,
        "remaining": 0,
        "resetAt": "2026-09-01T00:00:00.000Z"
      }
    },
    "materials": {
      "available": true,
      "pricePerOutline": 0,
      "pricePerArticle": 0,
      "pricePerTask": 0,
      "freeRemaining": 0,
      "daily": {
        "used": 0,
        "limit": 0,
        "remaining": 0,
        "resetAt": "2026-09-01T00:00:00.000Z"
      }
    },
    "distribution": {
      "plan": "string",
      "limits": {
        "channels": 0,
        "channelsPeriod": "month",
        "tasksPerMonth": 0,
        "activeCampaigns": 0
      },
      "usage": {
        "activeCampaigns": 0,
        "tasksThisMonth": 0,
        "channels": 0
      }
    }
  }
}

Topics

GET/v1/topics

有曝光、却没有页面承接的搜索词

免费,不产生任何外部账单(开放 API 本身需要付费档位)。每次调用都从你自己的 Search Console 数据现算,不涉及任何外部关键词库 —— 这正是关键:「已经有曝光、却没有页面」这件事,关键词工具告诉不了你。

结果按机会分排序。已在界面上被忽略的选题不会出现在这里。

查询参数

字段类型说明
siteIdstring来自 GET /v1/sites。不传则用最早接入的网站。

响应200

字段类型说明
successenum可选值:true
dataTopicList
└siteId可为空string
└topicsarray<Topic>
└keystring选题标识 —— 调用其余选题类接口时把它原样作为 key 传回。它是代表性搜索词归一化之后的文本,因此可能包含空格、斜杠和非拉丁字符。请始终放在查询串或请求体里,🚫 绝不要放进 URL 路径。
└titlestring该选题簇中曝光最高的那个搜索词,原样返回。这不是生成的标题 —— 标题随大纲一起给出。
└shapeenumcomparison 表示这条选题命中了你的竞品清单。文章必须写成对比,🚫 不能去介绍竞品 —— 否则你是在替对方写内容。可选值:comparisonroundupguide
└intentstring
└membersarray<TopicMember>
└textstring用户实际输入的搜索词。
└impressionsinteger
└clicksinteger
└position可为空number
└landingUrl可为空stringSearch Console 当前为该搜索词记录的落地页,可能没有。
└impressionsinteger实测值,来自 Search Console。
└clicksinteger实测值,来自 Search Console。
└position可为空number实测值:该选题簇内按曝光加权的平均排名。
└competitorboolean
└scorenumber
└rankinteger
└upsideClicksinteger这是估算,不是实测:若新建对应页面并进入第 3 位,每月预计增加的点击数。它被刻意与 clicks、impressions 分成不同字段,你在任何地方展示它时也必须保持视觉上分开。把预测当实测数据呈现,是这个品类最常见的翻车方式。
└statusenum可选值:newdismissedplannedpublished
└outlineAt可为空string
└articleAt可为空string🚫 不要从 outlineAt 推断它。有大纲不等于有正文 —— 那是两个分别收费的步骤。
└totalQueriesinteger这些选题一共覆盖多少个不同的搜索词。
可能的错误
401鉴权失败
404site_not_found —— 该 siteId 不属于这个账号

示例

bash
curl "https://www.querywin.com/api/v1/topics" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "siteId": "string",
    "topics": [
      {
        "key": "string",
        "title": "string",
        "shape": "comparison",
        "intent": "string",
        "members": [
          {
            "text": null,
            "impressions": null,
            "clicks": null,
            "position": null,
            "landingUrl": null
          }
        ],
        "impressions": 0,
        "clicks": 0,
        "position": 0,
        "competitor": true,
        "score": 0,
        "rank": 0,
        "upsideClicks": 0,
        "status": "new",
        "outlineAt": "2026-09-01T00:00:00.000Z",
        "articleAt": "2026-09-01T00:00:00.000Z"
      }
    ],
    "totalQueries": 0
  }
}
GET/v1/topics/article

读取已生成的正文草稿

🚫 不会触发生成,也不消耗任何积分。尚未生成时 article 为 null。

查询参数

字段类型说明
key必填string来自 GET /v1/topics 的选题标识。
siteIdstring来自 GET /v1/sites。不传则用最早接入的网站。

响应200

字段类型说明
successenum可选值:true
dataArticleResult
└article可为空Article
└titlestring
└descriptionstringMeta 描述。
└markdownstring可发布的正文。
└jsonLdstring这篇文章的结构化数据,已填好内容。合法 JSON —— 发布时放进页面上 type="application/ld+json" 的 script 标签里。
└wordCountinteger
└warningsarray<ArticleWarning>读起来像 AI 写的那些句子。草稿仍然可用 —— 我们把它们报出来,而不是悄悄改掉。请记录它们。 在自动化流程里,这是唯一一个还有人能发现问题的时刻。
└kindenum可选值:banned_phrasebanned_wordem_dash_overuseno_short_sentence
└hitstring命中的那段原文。
└articleAt可为空string
└model可为空string
可能的错误
400key_required
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/topics/article?key=..." \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "article": {
      "title": "string",
      "description": "string",
      "markdown": "string",
      "jsonLd": "string",
      "wordCount": 0,
      "warnings": [
        {
          "kind": "banned_phrase",
          "hit": "string"
        }
      ]
    },
    "articleAt": "2026-09-01T00:00:00.000Z",
    "model": "string"
  }
}
POST/v1/topics/article

把大纲写成可发布的正文草稿(扣积分)

这条链上最贵的一步,也是最慢的一步:同步返回,通常 60–120 秒。

要求该选题已经有大纲 —— 正文依据大纲撰写,这样文章才与它要承接的搜索词对得上。没有大纲时返回 no_outline。

与大纲一样:输入不变返回缓存结果且不重复收费;业务结果返回 HTTP 200 带 ok: false;积分不足返回 402。

🔴 返回的 warnings 是读起来像 AI 写的那些句子。草稿仍然可用 —— 我们把它们报出来,而不是悄悄改掉。自动化流程里,这是唯一一个还有人能发现问题的时刻。

请求体

字段类型说明
key必填string来自 GET /v1/topics 的选题标识。
siteIdstring不传则用最早接入的网站。
confirmSpend必填integer授权上限,不是精确金额。 传一个不小于当前单价的数即可,实际花多少扣多少 —— 命中缓存时往往为 0。一旦价格涨到超过你的上限,请求会以 confirm_spend_too_low 失败,而不是悄悄多扣。当前单价从 GET /v1/usage 读。 🔴 这个字段是必填的:界面上那个写着价格的确认弹窗,在脚本里并不存在。 (min 0)

响应200

字段类型说明
successenum可选值:true
dataArticleOutcome
└okboolean
└failureenum仅当 ok 为 false 时出现。HTTP 仍然是 200。可选值:topic_not_foundno_outlineengine_unavailableengine_failedno_valid_article
└article可为空Article
└titlestring
└descriptionstringMeta 描述。
└markdownstring可发布的正文。
└jsonLdstring这篇文章的结构化数据,已填好内容。合法 JSON —— 发布时放进页面上 type="application/ld+json" 的 script 标签里。
└wordCountinteger
└warningsarray<ArticleWarning>读起来像 AI 写的那些句子。草稿仍然可用 —— 我们把它们报出来,而不是悄悄改掉。请记录它们。 在自动化流程里,这是唯一一个还有人能发现问题的时刻。
└kindenum可选值:banned_phrasebanned_wordem_dash_overuseno_short_sentence
└hitstring命中的那段原文。
└generatedboolean返回缓存结果时为 false —— 本次未收费。
└creditsSpentinteger
└freeUsedboolean
└rejectedarray<string>导致草稿被丢弃(且不收费)的结构性问题:missing_sections、missing_faq、invented_link、invalid_json_ld、comparison_without_contrast、body_too_short。
可能的错误
400key_required、confirm_spend_required 或 confirm_spend_too_low(响应体里带当前 price)
401鉴权失败
402insufficient_credits —— 响应体带 requiredCredits、currentBalance、shortfall
403missing_scope_spend —— 这把密钥没有 spend 权限
429rate_limited 或 daily_limit_reached(响应体带 resetAt)

示例

bash
curl -X POST https://www.querywin.com/api/v1/topics/article \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": "clx1site000",
    "key": "standard wardrobe depth",
    "confirmSpend": 80
  }'
json — 响应
{
  "success": true,
  "data": {
    "ok": true,
    "failure": "topic_not_found",
    "article": {
      "title": "string",
      "description": "string",
      "markdown": "string",
      "jsonLd": "string",
      "wordCount": 0,
      "warnings": [
        {
          "kind": "banned_phrase",
          "hit": "string"
        }
      ]
    },
    "generated": true,
    "creditsSpent": 0,
    "freeUsed": true,
    "rejected": [
      "string"
    ]
  }
}
GET/v1/topics/outline

读取已生成的大纲

🚫 不会触发生成,也不消耗任何积分。尚未生成时 outline 为 null。

查询参数

字段类型说明
key必填string来自 GET /v1/topics 的选题标识。
siteIdstring来自 GET /v1/sites。不传则用最早接入的网站。

响应200

字段类型说明
successenum可选值:true
dataOutlineResult
└outline可为空Outline
└titlestring
└slugstring
└anglestring这一页要论证的角度。
└sectionsarray<object>
└headingstring
└pointsarray<string>
└faqarray<object>页面必须回答的问题。AI 答案摘取的正是这些。
└questionstring
└answerstring
└schemaTypestring这一页适合用哪种 JSON-LD 类型。
└internalLinksarray<string>你自己网站上值得链过去的页面。从真实 URL 中挑选,🚫 绝不虚构。
└outlineAt可为空string
└model可为空string
可能的错误
400key_required
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/topics/outline?key=..." \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "outline": {
      "title": "string",
      "slug": "string",
      "angle": "string",
      "sections": [
        {
          "heading": "string",
          "points": []
        }
      ],
      "faq": [
        {
          "question": "string",
          "answer": "string"
        }
      ],
      "schemaType": "string",
      "internalLinks": [
        "string"
      ]
    },
    "outlineAt": "2026-09-01T00:00:00.000Z",
    "model": "string"
  }
}
POST/v1/topics/outline

生成大纲(扣积分)

同步返回,通常 10–20 秒。

输入不变时直接返回缓存的大纲,不再重复收费 —— 指纹覆盖选题簇及其竞品判定,所以请求失败后重试是安全的。

业务结果(引擎不可用、输出未通过校验)返回 HTTP 200,带 ok: false 与 failure 码。积分不足才是真正的 402。

请求体

字段类型说明
key必填string来自 GET /v1/topics 的选题标识。
siteIdstring不传则用最早接入的网站。
confirmSpend必填integer授权上限,不是精确金额。 传一个不小于当前单价的数即可,实际花多少扣多少 —— 命中缓存时往往为 0。一旦价格涨到超过你的上限,请求会以 confirm_spend_too_low 失败,而不是悄悄多扣。当前单价从 GET /v1/usage 读。 🔴 这个字段是必填的:界面上那个写着价格的确认弹窗,在脚本里并不存在。 (min 0)

响应200

字段类型说明
successenum可选值:true
dataOutlineOutcome
└okboolean
└failureenum仅当 ok 为 false 时出现。HTTP 仍然是 200 —— 这是业务结果,不是错误。可选值:topic_not_foundengine_unavailableengine_failedno_valid_outline
└outline可为空Outline
└titlestring
└slugstring
└anglestring这一页要论证的角度。
└sectionsarray<object>
└headingstring
└pointsarray<string>
└faqarray<object>页面必须回答的问题。AI 答案摘取的正是这些。
└questionstring
└answerstring
└schemaTypestring这一页适合用哪种 JSON-LD 类型。
└internalLinksarray<string>你自己网站上值得链过去的页面。从真实 URL 中挑选,🚫 绝不虚构。
└generatedboolean返回缓存结果时为 false —— 本次未收费。
└creditsSpentinteger
└freeUsedboolean
└rejectedarray<string>模型输出触发的校验规则。值得记录下来,作为质量信号。
可能的错误
400key_required、confirm_spend_required 或 confirm_spend_too_low(响应体里带当前 price)
401鉴权失败
402insufficient_credits —— 响应体带 requiredCredits、currentBalance、shortfall
403missing_scope_spend —— 这把密钥没有 spend 权限
429rate_limited 或 daily_limit_reached(响应体带 resetAt)

示例

bash
curl -X POST https://www.querywin.com/api/v1/topics/outline \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": "clx1site000",
    "key": "standard wardrobe depth",
    "confirmSpend": 80
  }'
json — 响应
{
  "success": true,
  "data": {
    "ok": true,
    "failure": "topic_not_found",
    "outline": {
      "title": "string",
      "slug": "string",
      "angle": "string",
      "sections": [
        {
          "heading": "string",
          "points": []
        }
      ],
      "faq": [
        {
          "question": "string",
          "answer": "string"
        }
      ],
      "schemaType": "string",
      "internalLinks": [
        "string"
      ]
    },
    "generated": true,
    "creditsSpent": 0,
    "freeUsed": true,
    "rejected": [
      "string"
    ]
  }
}
POST/v1/topics/published

回写发布地址

免费,但有对外副作用:该地址会被推送到 Bing、Yandex、Seznam、Naver。不含 Google —— Google 不支持 IndexNow,它会按自己的节奏发现这个改动。

这一步同时把这条选题标记为已发布,它之后不再出现在 GET /v1/topics 里。要求密钥带 publish 权限。

请求体

字段类型说明
key必填string
siteIdstring
url必填string你把它发布在哪里。仅支持 http/https。此时不会去抓取该地址。

响应200

字段类型说明
successenum可选值:true
dataPublishedResult
└clusterKeystring
└statusenum可选值:published
└publishedUrlstring
└publishedAtstring
└indexnowobjectBing、Yandex、Seznam、Naver。不含 Google。
└pushedboolean
└outcomestringskipped 通常表示密钥文件还没有验证通过。
└enginesstring
可能的错误
400key_required、url_required 或 invalid_url(仅支持 http/https)
401鉴权失败
403missing_scope_publish —— 这把密钥没有 publish 权限
404site_not_found

示例

bash
curl -X POST https://www.querywin.com/api/v1/topics/published \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": "clx1site000",
    "key": "standard wardrobe depth",
    "url": "https://example.com/blog/standard-wardrobe-depth"
  }'
json — 响应
{
  "success": true,
  "data": {
    "clusterKey": "string",
    "status": "published",
    "publishedUrl": "string",
    "publishedAt": "2026-09-01T00:00:00.000Z",
    "indexnow": {
      "pushed": true,
      "outcome": "string",
      "engines": "string"
    }
  }
}

Distribution

GET/v1/campaigns

分发计划与分发配额

分发计划(缺省不含已归档;includeArchived=true 才含),以及当前档位的分发上限与已用量。免费。

查询参数

字段类型说明
productIdstring只看该产品的计划。
includeArchivedboolean

响应200

字段类型说明
successenum可选值:true
dataCampaignList
└campaignsarray<Campaign>
└campaignIdstring
└productIdstring
└namestring
└statusenumcompleted 是算出来的:所有任务都已上线、已核实、失败或跳过。可选值:activecompletedarchived
└quotainteger建计划时选了多少个渠道。
└startsAtstring
└endsAt可为空string
└countsobject
└totalinteger
└submittedintegersubmitted + published + verified。
└liveintegerpublished + verified。
└blockedinteger
└doneinteger
└byStatusobject
└createdAtstring
└quotaDistributionQuota当前档位的分发上限与已用量。上限为 null 表示不限。
└planstring
└limitsobject
└channels可为空integer单个产品可投递的不同渠道数,按 channelsPeriod 的周期计。
└channelsPeriodenummonth(付费档):按自然月(UTC)计,每个月都可投一批新渠道。total(免费版):按该产品累计计。可选值:monthtotal
└tasksPerMonth可为空integer每个自然月(UTC)可新建的任务数,各产品合计。
└activeCampaigns可为空integer同时进行中的计划数。
└usageobject
└activeCampaignsinteger
└tasksThisMonthinteger
└channels可为空integer只在请求指定了产品时有值。
可能的错误
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/campaigns" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "campaigns": [
      {
        "campaignId": "string",
        "productId": "string",
        "name": "string",
        "status": "active",
        "quota": 0,
        "startsAt": "2026-09-01T00:00:00.000Z",
        "endsAt": "2026-09-01T00:00:00.000Z",
        "counts": {
          "total": 0,
          "submitted": 0,
          "live": 0,
          "blocked": 0,
          "done": 0,
          "byStatus": null
        },
        "createdAt": "2026-09-01T00:00:00.000Z"
      }
    ],
    "quota": {
      "plan": "string",
      "limits": {
        "channels": 0,
        "channelsPeriod": "month",
        "tasksPerMonth": 0,
        "activeCampaigns": 0
      },
      "usage": {
        "activeCampaigns": 0,
        "tasksThisMonth": 0,
        "channels": 0
      }
    }
  }
}
POST/v1/campaigns

按明确的渠道清单建计划

每个渠道 id 一条任务,投递素材当场按产品档案备好,零成本。请传实际选定的渠道 —— 计划是「决定投哪里」的记录,🚫 不是由服务端展开的筛选条件。

该产品已有进行中或已投递任务的渠道会被剔除,列在 skipped 里并给出理由(already_open、already_submitted、not_found、broken、inactive、other_product、locked)。一条都不剩时返回 HTTP 200,ok: false 且 failure: "no_valid_targets"。超出当前档位的分发配额是拒绝:**409 quota_exceeded**,响应体带 dimension、limit、used、requested —— 什么都不会建,🚫 不做「能建几条建几条」。

请求体

字段类型说明
productId必填string
name必填string
targetIds必填array<string>来自 GET /v1/channels 的渠道 id。只传实际选定的渠道。
endsAtstring可选期限,显示在工作台里。到期不会自动关闭任何东西。

响应200

字段类型说明
successenum可选值:true
dataCreateCampaignOutcome
└okboolean
└failureenumok 为 false 时出现。可选值:no_valid_targets
└campaignCampaign
└campaignIdstring
└productIdstring
└namestring
└statusenumcompleted 是算出来的:所有任务都已上线、已核实、失败或跳过。可选值:activecompletedarchived
└quotainteger建计划时选了多少个渠道。
└startsAtstring
└endsAt可为空string
└countsobject
└totalinteger
└submittedintegersubmitted + published + verified。
└liveintegerpublished + verified。
└blockedinteger
└doneinteger
└byStatusobject
└createdAtstring
└tasksarray<Task>
└taskIdstring
└campaignIdstring
└productIdstring
└statusenumpublished 是你回写的。verified 是 QueryWin 在上线页面上看到的(目录与 AI 工具榜看链接,其余看提及)。对外转述时请分开说。可选值:plannedpreparedin_progressblockedsubmittedpublishedverifiedfailedskipped
└blockedReason可为空enum可选值:logincaptchapaymentmissing_materialothernull
└missingarray<string>档案缺少的必填素材。在工作台里补齐档案后,任务会自行重新准备。
└listingUrl可为空string
└markedByenum最近一次状态变化是谁做的:人(或本接口)、浏览器扩展、或 QueryWin 自身。可选值:userdevicesystem
└hasGeneratedboolean已有为该渠道改写的版本。
└reviewDueAt可为空string提交后该回头查看的时间(submittedAt + 该渠道的审核天数)。
└submittedAt可为空string
└publishedAt可为空string
└verifiedAt可为空string
└nextarray<string>从当前状态出发,可通过 POST /v1/tasks/{id}/status 设置的状态。
└targetobject
└targetIdstring
└namestring
└urlstring
└submitUrlstring
└kindstring
└sourceenum可选值:seeduserrivals
└languagestring
└requiresBacklinkboolean
└check可为空objectQueryWin 在条目上线后做的回查。任务上线前为 null。
└kindenum查什么:指向产品的链接(目录、AI 工具榜)或品牌提及(其余类型)。可选值:link_livemention_seen
└state可为空enumconfirmed = 已看到。unconfirmed = 一轮回查都没找到(状态不变;请核对地址)。lost = 曾经有、现在没了(任务已置为失败)。可选值:confirmedunconfirmedlostnull
└checkedAt可为空string
└dueAt可为空string
└updatedAtstring
└skippedarray<object>
└targetIdstring
└reasonenumother_product = 属于别的产品的 AI 引用来源候选;inactive = 已停用或被忽略的渠道;locked = 免费版渠道库窗口之外(按匹配度前 window 条,条数见 GET /v1/channels 的返回;自己添加的、收藏的、AI 引用来源不受限)。可选值:not_foundbrokeninactiveother_productalready_openalready_submittedlocked
可能的错误
400product_id_required、name_required / name_too_long(80 字)、target_ids_required / too_many_targets(100 条)或 invalid_date
401鉴权失败
403missing_scope_publish —— 这把密钥没有 publish 权限
404product_not_found —— 该 productId 不属于这个账号
409quota_exceeded —— 响应体带 dimension(active_campaigns / tasks_per_month / channels)、limit、used、requested;channels 另带 period(month / total,与 DistributionQuota.limits.channelsPeriod 一致)

示例

bash
curl -X POST https://www.querywin.com/api/v1/campaigns \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "clx1prod000",
    "name": "Directories, September",
    "targetIds": [
      "clx1tgt001",
      "clx1tgt002"
    ]
  }'
json — 响应
{
  "success": true,
  "data": {
    "ok": true,
    "failure": "no_valid_targets",
    "campaign": {
      "campaignId": "string",
      "productId": "string",
      "name": "string",
      "status": "active",
      "quota": 0,
      "startsAt": "2026-09-01T00:00:00.000Z",
      "endsAt": "2026-09-01T00:00:00.000Z",
      "counts": {
        "total": 0,
        "submitted": 0,
        "live": 0,
        "blocked": 0,
        "done": 0,
        "byStatus": null
      },
      "createdAt": "2026-09-01T00:00:00.000Z"
    },
    "tasks": [
      {
        "taskId": "string",
        "campaignId": "string",
        "productId": "string",
        "status": "planned",
        "blockedReason": "login",
        "missing": [
          "string"
        ],
        "listingUrl": "string",
        "markedBy": "user",
        "hasGenerated": true,
        "reviewDueAt": "2026-09-01T00:00:00.000Z",
        "submittedAt": "2026-09-01T00:00:00.000Z",
        "publishedAt": "2026-09-01T00:00:00.000Z",
        "verifiedAt": "2026-09-01T00:00:00.000Z",
        "next": [
          "string"
        ],
        "target": {
          "targetId": "string",
          "name": "string",
          "url": "string",
          "submitUrl": "string",
          "kind": "string",
          "source": "seed",
          "language": "string",
          "requiresBacklink": true
        },
        "check": {
          "kind": "link_live",
          "state": "confirmed",
          "checkedAt": "2026-09-01T00:00:00.000Z",
          "dueAt": "2026-09-01T00:00:00.000Z"
        },
        "updatedAt": "2026-09-01T00:00:00.000Z"
      }
    ],
    "skipped": [
      {
        "targetId": "string",
        "reason": "not_found"
      }
    ]
  }
}
GET/v1/campaigns/{id}

一条计划及其任务

该计划与其中的每条任务。免费。

响应200

字段类型说明
successenum可选值:true
dataCampaignDetail
└campaignCampaign
└campaignIdstring
└productIdstring
└namestring
└statusenumcompleted 是算出来的:所有任务都已上线、已核实、失败或跳过。可选值:activecompletedarchived
└quotainteger建计划时选了多少个渠道。
└startsAtstring
└endsAt可为空string
└countsobject
└totalinteger
└submittedintegersubmitted + published + verified。
└liveintegerpublished + verified。
└blockedinteger
└doneinteger
└byStatusobject
└createdAtstring
└tasksarray<Task>
└taskIdstring
└campaignIdstring
└productIdstring
└statusenumpublished 是你回写的。verified 是 QueryWin 在上线页面上看到的(目录与 AI 工具榜看链接,其余看提及)。对外转述时请分开说。可选值:plannedpreparedin_progressblockedsubmittedpublishedverifiedfailedskipped
└blockedReason可为空enum可选值:logincaptchapaymentmissing_materialothernull
└missingarray<string>档案缺少的必填素材。在工作台里补齐档案后,任务会自行重新准备。
└listingUrl可为空string
└markedByenum最近一次状态变化是谁做的:人(或本接口)、浏览器扩展、或 QueryWin 自身。可选值:userdevicesystem
└hasGeneratedboolean已有为该渠道改写的版本。
└reviewDueAt可为空string提交后该回头查看的时间(submittedAt + 该渠道的审核天数)。
└submittedAt可为空string
└publishedAt可为空string
└verifiedAt可为空string
└nextarray<string>从当前状态出发,可通过 POST /v1/tasks/{id}/status 设置的状态。
└targetobject
└targetIdstring
└namestring
└urlstring
└submitUrlstring
└kindstring
└sourceenum可选值:seeduserrivals
└languagestring
└requiresBacklinkboolean
└check可为空objectQueryWin 在条目上线后做的回查。任务上线前为 null。
└kindenum查什么:指向产品的链接(目录、AI 工具榜)或品牌提及(其余类型)。可选值:link_livemention_seen
└state可为空enumconfirmed = 已看到。unconfirmed = 一轮回查都没找到(状态不变;请核对地址)。lost = 曾经有、现在没了(任务已置为失败)。可选值:confirmedunconfirmedlostnull
└checkedAt可为空string
└dueAt可为空string
└updatedAtstring
可能的错误
401鉴权失败
404campaign_not_found

示例

bash
curl "https://www.querywin.com/api/v1/campaigns/{id}" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "campaign": {
      "campaignId": "string",
      "productId": "string",
      "name": "string",
      "status": "active",
      "quota": 0,
      "startsAt": "2026-09-01T00:00:00.000Z",
      "endsAt": "2026-09-01T00:00:00.000Z",
      "counts": {
        "total": 0,
        "submitted": 0,
        "live": 0,
        "blocked": 0,
        "done": 0,
        "byStatus": null
      },
      "createdAt": "2026-09-01T00:00:00.000Z"
    },
    "tasks": [
      {
        "taskId": "string",
        "campaignId": "string",
        "productId": "string",
        "status": "planned",
        "blockedReason": "login",
        "missing": [
          "string"
        ],
        "listingUrl": "string",
        "markedBy": "user",
        "hasGenerated": true,
        "reviewDueAt": "2026-09-01T00:00:00.000Z",
        "submittedAt": "2026-09-01T00:00:00.000Z",
        "publishedAt": "2026-09-01T00:00:00.000Z",
        "verifiedAt": "2026-09-01T00:00:00.000Z",
        "next": [
          "string"
        ],
        "target": {
          "targetId": "string",
          "name": "string",
          "url": "string",
          "submitUrl": "string",
          "kind": "string",
          "source": "seed",
          "language": "string",
          "requiresBacklink": true
        },
        "check": {
          "kind": "link_live",
          "state": "confirmed",
          "checkedAt": "2026-09-01T00:00:00.000Z",
          "dueAt": "2026-09-01T00:00:00.000Z"
        },
        "updatedAt": "2026-09-01T00:00:00.000Z"
      }
    ]
  }
}
GET/v1/channels

可投递的入口,按匹配度排序

内置渠道(目录、启动平台、AI 工具榜、社区、内容平台)、你自行添加的条目,以及 —— 传了 productId 时 —— AI 答案在该产品的搜索词上引用过的站点(source: "rivals")。带 productId 时按相关性排序,每条渠道带 taskStatus(该产品在此已有任务时非空)。免费。

**citedByAi 表示 AI 答案在你的搜索词上引用过该站,🚫 不表示该站会收录你的产品** —— 去争取被提及,正是任务要做的事。

查询参数

字段类型说明
productIdstring按该产品的匹配度排序、附上 taskStatus,并包含它的 AI 引用来源候选。
kindstring渠道类型。可选值:directorylaunchai_directorycommunitycontentother
sourcestringseed = 内置渠道,user = 自行添加,rivals = 该产品的 AI 引用来源。可选值:seeduserrivals
pricingstring投递费用。可选值:freeconditionalpaidunknown
submitMethodstring投递方式:填写表单、在社区发帖,或写信投稿。可选值:formpostemail
qstring按名称、域名与主题搜索。
hideSubmittedboolean隐藏该产品已有进行中或已投递任务的渠道。需要 productId。
pageinteger缺省 1。
pageSizeinteger缺省 30。

响应200

字段类型说明
successenum可选值:true
dataChannelList
└productId可为空string
└itemsarray<Channel>
└targetIdstring作为 targetIds 传给 POST /v1/campaigns。
└namestring
└urlstring
└submitUrlstring提交表单或发帖页;对 AI 引用来源,是被 AI 答案引用最多的那一页。
└kindenum可选值:directorylaunchai_directorycommunitycontentother
└submitMethodenumform = 填写该站的提交表单,post = 自己在社区发帖,email = 写信向编辑投稿(收件地址在打开页面时读取,不入库)。可选值:formpostemail
└sourceenumseed = 内置渠道,user = 自行添加,rivals = AI 答案在该产品的搜索词上引用过的站点。可选值:seeduserrivals
└pricingTypeenum可选值:freeconditionalpaidunknown
└priceNote可为空string
└languagestringen、zh、multi,或 AI 引用来源按搜索词判出的语言代码。
└topicsarray<string>
└requiresAccountboolean
└requiresBacklinkboolean
└reviewDays可为空integer通常的审核天数。任务会在此之后提醒你回头查看。
└siteRank可为空integer在公开的 Tranco 榜单中的全球排名(数字越小访问量越大)。null = 不在前一百万。它不是 Domain Rating。
└hasFormSpecboolean该渠道的表单字段已登记,素材按它的字数上限裁。
└relevance可为空integer与请求所指产品的匹配分。只用于排序。
└taskStatus可为空string该产品在此渠道进行中或已完成的任务状态;null = 尚无。
└citedByAi可为空object只有 source: "rivals" 有。AI 答案在所列搜索词上引用过该站。这🚫 不是该站会收录你的产品的承诺 —— 去争取正是任务要做的事。
└queriesinteger在多少条不同的搜索词上被引用。
└samplesinteger多少次 AI 答案采样引用了它。
└searchesarray<string>
└pagesarray<string>被引用的页面,引用最多的在前。较早的采样只记录了域名,此时为空。
└totalinteger
└pageinteger
└pageSizeinteger
└limitedboolean免费版:只返回默认排序(按 productId 的匹配度)的前 window 条,筛选、搜索、排序参数会以 403 library_locked 拒绝。total 仍是渠道库的真实总数。
└window可为空integer免费版窗口条数:基础 20 条,每有一位好友通过你的邀请链接注册加 20 条(你本人通过邀请注册的,另加 20 条)。列表不受限时为 null。
可能的错误
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/channels" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "productId": "string",
    "items": [
      {
        "targetId": "string",
        "name": "string",
        "url": "string",
        "submitUrl": "string",
        "kind": "directory",
        "submitMethod": "form",
        "source": "seed",
        "pricingType": "free",
        "priceNote": "string",
        "language": "string",
        "topics": [
          "string"
        ],
        "requiresAccount": true,
        "requiresBacklink": true,
        "reviewDays": 0,
        "siteRank": 0,
        "hasFormSpec": true,
        "relevance": 0,
        "taskStatus": "string",
        "citedByAi": {
          "queries": 0,
          "samples": 0,
          "searches": [],
          "pages": []
        }
      }
    ],
    "total": 0,
    "page": 0,
    "pageSize": 0,
    "limited": true,
    "window": 0
  }
}
GET/v1/products

产品清单与各自的档案完整度

分发链从这里开始;其余分发接口都要带 productId。completeness 与 missing 来自已保存的产品档案:档案里空着的格,投递素材里就是空的;必填格缺失时任务会停在 blocked / missing_material,直到档案补齐。用 GET /v1/products/{id} 读取,用 PATCH /v1/products/{id} 填写。免费。

响应200

字段类型说明
successenum可选值:true
dataProductList
└productsarray<Product>
└productIdstring
└namestring
└urlstring
└domainstring
└primaryLanguageenum可选值:enzhjakodefresptitrunlpltrarthviid
└topicsarray<string>
└completenessinteger档案完整度 0–100。在工作台或通过 PATCH /v1/products/{id} 补齐。
└missingarray<string>档案里空着的格。每一格都是所有投递素材里的空缺。
└sitesarray<object>
└siteIdstring
└domainstring
└syncedThrough可为空string
可能的错误
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/products" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "products": [
      {
        "productId": "string",
        "name": "string",
        "url": "string",
        "domain": "string",
        "primaryLanguage": "en",
        "topics": [
          "string"
        ],
        "completeness": 0,
        "missing": [
          "string"
        ],
        "sites": [
          {
            "siteId": null,
            "domain": null,
            "syncedThrough": null
          }
        ]
      }
    ]
  }
}
POST/v1/products

创建产品

需要付费档位与 publish 权限。用公开主页地址和可选名称创建产品,占用产品名额,不扣积分。返回已保存的完整档案,再用 PATCH /v1/products/{id} 填写。不抓网页、不调用 AI。同域名重复创建返回 409 product_exists,并带已有 productId;响应丢失时可据此继续操作。产品默认值可以修改,不代表已核实的网站事实。

请求体

字段类型说明
url必填string
namestring

响应201

字段类型说明
successboolean
dataProductDetail
└namestring
└urlstring
└primaryLanguageenum可选值:enzhjakodefresptitrunlpltrarthviid
└businessTypeenum可选值:saastoolecommercecontentserviceother
└launchStatusenum可选值:livebeta
└pricingModelenum可选值:freefreemiumpaidtrial
└tagline可为空object
└shortDesc可为空object
└longDesc可为空object
└firstComment可为空object
└topicsarray<string>
└promoCode可为空string
└videoUrl可为空string
└demoUrl可为空string
└links可为空object
└webAppstring
└appStorestring
└playStorestring
└chromeExtensionstring
└macosstring
└windowsstring
└socials可为空object
└xstring
└linkedinstring
└githubstring
└instagramstring
└youtubestring
└facebookstring
└contactName可为空string
└contactEmail可为空string
└galleryarray<string>
└productIdstring
└domainstring
└thumbnailUrl可为空string
└completenessinteger (0–100)
└missingarray<string>
└createdAtstring
└updatedAtstring
└sitesarray<object>
└siteIdstring
└domainstring
└syncedThrough可为空string
可能的错误
400invalid_product_input、invalid_url 或 url_not_public
401鉴权失败
403plan_required,写操作还可能返回 missing_scope_publish
409product_exists(带已有 productId)或 product_limit_reached
429rate_limited —— 每把密钥每分钟最多 120 次请求

示例

bash
curl -X POST https://www.querywin.com/api/v1/products \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "name": "Example"
  }'
json — 响应
{
  "success": true,
  "data": {
    "name": "string",
    "url": "string",
    "primaryLanguage": "en",
    "businessType": "saas",
    "launchStatus": "live",
    "pricingModel": "free",
    "tagline": null,
    "shortDesc": null,
    "longDesc": null,
    "firstComment": null,
    "topics": [
      "string"
    ],
    "promoCode": "string",
    "videoUrl": "string",
    "demoUrl": "string",
    "links": {
      "webApp": "string",
      "appStore": "string",
      "playStore": "string",
      "chromeExtension": "string",
      "macos": "string",
      "windows": "string"
    },
    "socials": {
      "x": "string",
      "linkedin": "string",
      "github": "string",
      "instagram": "string",
      "youtube": "string",
      "facebook": "string"
    },
    "contactName": "string",
    "contactEmail": "string",
    "gallery": [
      "string"
    ],
    "productId": "string",
    "domain": "string",
    "thumbnailUrl": "string",
    "completeness": 0,
    "missing": [
      "string"
    ],
    "createdAt": "2026-09-01T00:00:00.000Z",
    "updatedAt": "2026-09-01T00:00:00.000Z",
    "sites": [
      {
        "siteId": "string",
        "domain": "string",
        "syncedThrough": "string"
      }
    ]
  }
}
PATCH/v1/products/{id}

填写或更新产品档案

需要 publish 权限。提交的字段立即保存,未提交的字段不变;对象(包括多语言文案)和数组整项替换。请先读取档案,以保留其他语言。不扣积分、不调用 AI。尚未投递的任务素材会异步刷新。只填写已知事实,不要编造缺失的产品资料。

请求体

字段类型说明
namestring
urlstring
primaryLanguageenum可选值:enzhjakodefresptitrunlpltrarthviid
businessTypeenum可选值:saastoolecommercecontentserviceother
launchStatusenum可选值:livebeta
pricingModelenum可选值:freefreemiumpaidtrial
taglineobject
shortDescobject
longDescobject
firstCommentobject
topicsarray<string>
promoCodestring
videoUrlstring
demoUrlstring
linksobject
└webAppstring
└appStorestring
└playStorestring
└chromeExtensionstring
└macosstring
└windowsstring
socialsobject
└xstring
└linkedinstring
└githubstring
└instagramstring
└youtubestring
└facebookstring
contactNamestring
contactEmailstring
galleryarray<string>

响应200

字段类型说明
successboolean
dataProductDetail
└namestring
└urlstring
└primaryLanguageenum可选值:enzhjakodefresptitrunlpltrarthviid
└businessTypeenum可选值:saastoolecommercecontentserviceother
└launchStatusenum可选值:livebeta
└pricingModelenum可选值:freefreemiumpaidtrial
└tagline可为空object
└shortDesc可为空object
└longDesc可为空object
└firstComment可为空object
└topicsarray<string>
└promoCode可为空string
└videoUrl可为空string
└demoUrl可为空string
└links可为空object
└webAppstring
└appStorestring
└playStorestring
└chromeExtensionstring
└macosstring
└windowsstring
└socials可为空object
└xstring
└linkedinstring
└githubstring
└instagramstring
└youtubestring
└facebookstring
└contactName可为空string
└contactEmail可为空string
└galleryarray<string>
└productIdstring
└domainstring
└thumbnailUrl可为空string
└completenessinteger (0–100)
└missingarray<string>
└createdAtstring
└updatedAtstring
└sitesarray<object>
└siteIdstring
└domainstring
└syncedThrough可为空string
可能的错误
400invalid_product_input、invalid_url、url_not_public、invalid_email 或 invalid_gallery
401鉴权失败
403plan_required,写操作还可能返回 missing_scope_publish
404product_not_found
409product_exists(带已有 productId)
429rate_limited —— 每把密钥每分钟最多 120 次请求

示例

bash
curl -X PATCH https://www.querywin.com/api/v1/products/{id} \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tagline": {
      "en": "Your product tagline",
      "zh": "你的产品标语"
    },
    "shortDesc": {
      "en": "A factual description of the product."
    },
    "topics": [
      "productivity",
      "developer-tools"
    ],
    "contactEmail": "hello@example.com"
  }'
json — 响应
{
  "success": true,
  "data": {
    "name": "string",
    "url": "string",
    "primaryLanguage": "en",
    "businessType": "saas",
    "launchStatus": "live",
    "pricingModel": "free",
    "tagline": null,
    "shortDesc": null,
    "longDesc": null,
    "firstComment": null,
    "topics": [
      "string"
    ],
    "promoCode": "string",
    "videoUrl": "string",
    "demoUrl": "string",
    "links": {
      "webApp": "string",
      "appStore": "string",
      "playStore": "string",
      "chromeExtension": "string",
      "macos": "string",
      "windows": "string"
    },
    "socials": {
      "x": "string",
      "linkedin": "string",
      "github": "string",
      "instagram": "string",
      "youtube": "string",
      "facebook": "string"
    },
    "contactName": "string",
    "contactEmail": "string",
    "gallery": [
      "string"
    ],
    "productId": "string",
    "domain": "string",
    "thumbnailUrl": "string",
    "completeness": 0,
    "missing": [
      "string"
    ],
    "createdAt": "2026-09-01T00:00:00.000Z",
    "updatedAt": "2026-09-01T00:00:00.000Z",
    "sites": [
      {
        "siteId": "string",
        "domain": "string",
        "syncedThrough": "string"
      }
    ]
  }
}
GET/v1/products/{id}

读取完整产品档案

返回已保存的多语言文案、链接、联系人、图片、完整度和缺失项。需要 read 权限,不扣积分。产品不属于当前工作区时也返回 product_not_found。

响应200

字段类型说明
successboolean
dataProductDetail
└namestring
└urlstring
└primaryLanguageenum可选值:enzhjakodefresptitrunlpltrarthviid
└businessTypeenum可选值:saastoolecommercecontentserviceother
└launchStatusenum可选值:livebeta
└pricingModelenum可选值:freefreemiumpaidtrial
└tagline可为空object
└shortDesc可为空object
└longDesc可为空object
└firstComment可为空object
└topicsarray<string>
└promoCode可为空string
└videoUrl可为空string
└demoUrl可为空string
└links可为空object
└webAppstring
└appStorestring
└playStorestring
└chromeExtensionstring
└macosstring
└windowsstring
└socials可为空object
└xstring
└linkedinstring
└githubstring
└instagramstring
└youtubestring
└facebookstring
└contactName可为空string
└contactEmail可为空string
└galleryarray<string>
└productIdstring
└domainstring
└thumbnailUrl可为空string
└completenessinteger (0–100)
└missingarray<string>
└createdAtstring
└updatedAtstring
└sitesarray<object>
└siteIdstring
└domainstring
└syncedThrough可为空string
可能的错误
401鉴权失败
403plan_required,写操作还可能返回 missing_scope_publish
404product_not_found
429rate_limited —— 每把密钥每分钟最多 120 次请求

示例

bash
curl "https://www.querywin.com/api/v1/products/{id}" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "name": "string",
    "url": "string",
    "primaryLanguage": "en",
    "businessType": "saas",
    "launchStatus": "live",
    "pricingModel": "free",
    "tagline": null,
    "shortDesc": null,
    "longDesc": null,
    "firstComment": null,
    "topics": [
      "string"
    ],
    "promoCode": "string",
    "videoUrl": "string",
    "demoUrl": "string",
    "links": {
      "webApp": "string",
      "appStore": "string",
      "playStore": "string",
      "chromeExtension": "string",
      "macos": "string",
      "windows": "string"
    },
    "socials": {
      "x": "string",
      "linkedin": "string",
      "github": "string",
      "instagram": "string",
      "youtube": "string",
      "facebook": "string"
    },
    "contactName": "string",
    "contactEmail": "string",
    "gallery": [
      "string"
    ],
    "productId": "string",
    "domain": "string",
    "thumbnailUrl": "string",
    "completeness": 0,
    "missing": [
      "string"
    ],
    "createdAt": "2026-09-01T00:00:00.000Z",
    "updatedAt": "2026-09-01T00:00:00.000Z",
    "sites": [
      {
        "siteId": "string",
        "domain": "string",
        "syncedThrough": "string"
      }
    ]
  }
}
POST/v1/products/{id}/images/from-url

从 URL 导入产品图片

需要 publish 权限。抓取公开 HTTP(S) 图片并保存副本:thumbnail 替换缩略图,gallery 追加画廊图(最多六张)。支持 JPEG、PNG、WebP 和 SVG,最大 4 MB;SVG 转为 PNG。复用现有抓取器拦截内网和不安全跳转。不扣积分。重复导入画廊可能增加重复图片;响应丢失后先读取档案再决定是否重试。

请求体

字段类型说明
url必填string
kindenum可选值:thumbnailgallery默认 gallery

响应200

字段类型说明
successboolean
dataProductDetail
└namestring
└urlstring
└primaryLanguageenum可选值:enzhjakodefresptitrunlpltrarthviid
└businessTypeenum可选值:saastoolecommercecontentserviceother
└launchStatusenum可选值:livebeta
└pricingModelenum可选值:freefreemiumpaidtrial
└tagline可为空object
└shortDesc可为空object
└longDesc可为空object
└firstComment可为空object
└topicsarray<string>
└promoCode可为空string
└videoUrl可为空string
└demoUrl可为空string
└links可为空object
└webAppstring
└appStorestring
└playStorestring
└chromeExtensionstring
└macosstring
└windowsstring
└socials可为空object
└xstring
└linkedinstring
└githubstring
└instagramstring
└youtubestring
└facebookstring
└contactName可为空string
└contactEmail可为空string
└galleryarray<string>
└productIdstring
└domainstring
└thumbnailUrl可为空string
└completenessinteger (0–100)
└missingarray<string>
└createdAtstring
└updatedAtstring
└sitesarray<object>
└siteIdstring
└domainstring
└syncedThrough可为空string
可能的错误
400invalid_product_input 或 invalid_url
401鉴权失败
403plan_required,写操作还可能返回 missing_scope_publish
404product_not_found
409gallery_full
413image_too_large
415image_type
429rate_limited —— 每把密钥每分钟最多 120 次请求
502image_unreachable
503storage_unavailable

示例

bash
curl -X POST https://www.querywin.com/api/v1/products/{id}/images/from-url \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/logo.png",
    "kind": "thumbnail"
  }'
json — 响应
{
  "success": true,
  "data": {
    "name": "string",
    "url": "string",
    "primaryLanguage": "en",
    "businessType": "saas",
    "launchStatus": "live",
    "pricingModel": "free",
    "tagline": null,
    "shortDesc": null,
    "longDesc": null,
    "firstComment": null,
    "topics": [
      "string"
    ],
    "promoCode": "string",
    "videoUrl": "string",
    "demoUrl": "string",
    "links": {
      "webApp": "string",
      "appStore": "string",
      "playStore": "string",
      "chromeExtension": "string",
      "macos": "string",
      "windows": "string"
    },
    "socials": {
      "x": "string",
      "linkedin": "string",
      "github": "string",
      "instagram": "string",
      "youtube": "string",
      "facebook": "string"
    },
    "contactName": "string",
    "contactEmail": "string",
    "gallery": [
      "string"
    ],
    "productId": "string",
    "domain": "string",
    "thumbnailUrl": "string",
    "completeness": 0,
    "missing": [
      "string"
    ],
    "createdAt": "2026-09-01T00:00:00.000Z",
    "updatedAt": "2026-09-01T00:00:00.000Z",
    "sites": [
      {
        "siteId": "string",
        "domain": "string",
        "syncedThrough": "string"
      }
    ]
  }
}
GET/v1/tasks

跨计划的任务流水

投递记录,按最近更新排。可按产品、计划或逗号分隔的状态列表筛选。byStatus 统计的是状态筛选之前范围内的全部任务。免费。

查询参数

字段类型说明
productIdstring只看该产品的任务。
campaignIdstring
statusstring逗号分隔,如 prepared,in_progress。
pageinteger缺省 1。
pageSizeinteger缺省 30。

响应200

字段类型说明
successenum可选值:true
dataTaskList
└itemsarray<Task>
└taskIdstring
└campaignIdstring
└productIdstring
└statusenumpublished 是你回写的。verified 是 QueryWin 在上线页面上看到的(目录与 AI 工具榜看链接,其余看提及)。对外转述时请分开说。可选值:plannedpreparedin_progressblockedsubmittedpublishedverifiedfailedskipped
└blockedReason可为空enum可选值:logincaptchapaymentmissing_materialothernull
└missingarray<string>档案缺少的必填素材。在工作台里补齐档案后,任务会自行重新准备。
└listingUrl可为空string
└markedByenum最近一次状态变化是谁做的:人(或本接口)、浏览器扩展、或 QueryWin 自身。可选值:userdevicesystem
└hasGeneratedboolean已有为该渠道改写的版本。
└reviewDueAt可为空string提交后该回头查看的时间(submittedAt + 该渠道的审核天数)。
└submittedAt可为空string
└publishedAt可为空string
└verifiedAt可为空string
└nextarray<string>从当前状态出发,可通过 POST /v1/tasks/{id}/status 设置的状态。
└targetobject
└targetIdstring
└namestring
└urlstring
└submitUrlstring
└kindstring
└sourceenum可选值:seeduserrivals
└languagestring
└requiresBacklinkboolean
└check可为空objectQueryWin 在条目上线后做的回查。任务上线前为 null。
└kindenum查什么:指向产品的链接(目录、AI 工具榜)或品牌提及(其余类型)。可选值:link_livemention_seen
└state可为空enumconfirmed = 已看到。unconfirmed = 一轮回查都没找到(状态不变;请核对地址)。lost = 曾经有、现在没了(任务已置为失败)。可选值:confirmedunconfirmedlostnull
└checkedAt可为空string
└dueAt可为空string
└updatedAtstring
└totalinteger
└pageinteger
└pageSizeinteger
└byStatusobject
可能的错误
401鉴权失败

示例

bash
curl "https://www.querywin.com/api/v1/tasks" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "items": [
      {
        "taskId": "string",
        "campaignId": "string",
        "productId": "string",
        "status": "planned",
        "blockedReason": "login",
        "missing": [
          "string"
        ],
        "listingUrl": "string",
        "markedBy": "user",
        "hasGenerated": true,
        "reviewDueAt": "2026-09-01T00:00:00.000Z",
        "submittedAt": "2026-09-01T00:00:00.000Z",
        "publishedAt": "2026-09-01T00:00:00.000Z",
        "verifiedAt": "2026-09-01T00:00:00.000Z",
        "next": [
          "string"
        ],
        "target": {
          "targetId": "string",
          "name": "string",
          "url": "string",
          "submitUrl": "string",
          "kind": "string",
          "source": "seed",
          "language": "string",
          "requiresBacklink": true
        },
        "check": {
          "kind": "link_live",
          "state": "confirmed",
          "checkedAt": "2026-09-01T00:00:00.000Z",
          "dueAt": "2026-09-01T00:00:00.000Z"
        },
        "updatedAt": "2026-09-01T00:00:00.000Z"
      }
    ],
    "total": 0,
    "page": 0,
    "pageSize": 0,
    "byStatus": null
  }
}
GET/v1/tasks/{id}

一条任务及其投递素材

该渠道表单要求的每一格,按渠道的字数上限从产品档案裁出(source: "profile"),加上已有的渠道改写版本(source: "ai")与在工作台里定稿的修改(source: "override")。source: "none" 表示档案里没有这一格 —— 🚫 不要自行编造。🚫 不会触发改写,不消耗任何积分。

响应200

字段类型说明
successenum可选值:true
dataTaskDetailResult
└taskTaskDetail
可能的错误
401鉴权失败
404task_not_found

示例

bash
curl "https://www.querywin.com/api/v1/tasks/{id}" \
  -H "Authorization: Bearer $QUERYWIN_API_KEY"
json — 响应
{
  "success": true,
  "data": {
    "task": null
  }
}
POST/v1/tasks/{id}/materials

为该渠道改写素材(扣积分)

一次 AI 改写,把档案改成适合这个渠道的说法:更紧凑的目录描述、创始人首评、社区帖、给编辑的投稿信,或 —— 对 AI 引用来源 —— 投稿信加一段可供对方页面直接采用的补充段落。同步返回,几秒钟。只依据档案中的事实;任何一段出现档案之外的链接就整段舍弃、不收费。

输入不变时返回上一版且不重复收费(cached: true);force: true 强制重写,照价收费。GET /v1/tasks/{id} 里从档案裁出的素材通常已够投目录;渠道需要另一种语气(社区、投稿信)时再改写。

产物一段都没通过校验时返回 HTTP 200,ok: false 且 failure: "engine_failed"。积分不足才是真正的 402。

请求体

字段类型说明
confirmSpend必填integer授权上限(积分),语义与大纲 / 正文相同。单价从 GET /v1/usage 的 materials.pricePerTask 读。免费额度还在时同样必填。 (min 0)
forceboolean即使上一版之后没有任何变化也重写。照价收费。

响应200

字段类型说明
successenum可选值:true
dataWriteMaterialsOutcome
└okboolean
└failureenumok 为 false 时出现。不收费。可选值:engine_failedengine_unavailable
└cachedboolean输入未变;返回的是上一版,未收费。
└freeUsedboolean
└creditsSpentinteger
└taskTaskDetail
可能的错误
400confirm_spend_required 或 confirm_spend_too_low(响应体里带当前 price)
401鉴权失败
402insufficient_credits —— 响应体带 requiredCredits、currentBalance、shortfall
403missing_scope_spend —— 这把密钥没有 spend 权限
404task_not_found
429rate_limited 或 daily_limit_reached(响应体带 resetAt)

示例

bash
curl -X POST https://www.querywin.com/api/v1/tasks/{id}/materials \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "confirmSpend": 10
  }'
json — 响应
{
  "success": true,
  "data": {
    "ok": true,
    "failure": "engine_failed",
    "cached": true,
    "freeUsed": true,
    "creditsSpent": 0,
    "task": null
  }
}
POST/v1/tasks/{id}/status

回写投递结果

记录你用自己的账号投递之后发生的事。QueryWin 从不代你向任何站点投递。表单提交后置为 submitted;条目上线后置为 published 并带上线地址(条目或帖子本身,🚫 不是站点首页);QueryWin 会在约 72 小时后回查该页面是否出现指向产品的链接(目录、AI 工具榜)或品牌提及(其余类型),并自行置为 verified —— 你不能设置它。

blocked 表示「需要人处理」:请带 reason(login、captcha、payment、missing_material、other)。failed / skipped 关闭任务;prepared 放回待投。状态机不允许的转换返回 **409 transition_not_allowed**;任务的 next 字段列出当前状态能推到哪些状态。

请求体

字段类型说明
status必填enumverified 不能设置;QueryWin 回查条目后自行设置。可选值:preparedin_progressblockedsubmittedpublishedfailedskipped
listingUrlstringpublished 必填:上线的条目或帖子本身,🚫 不是站点首页。仅支持 http/https。已知地址时也可随 submitted 一并传。
notestring
reasonenumblocked 必填。可选值:logincaptchapaymentmissing_materialother

响应200

字段类型说明
successenum可选值:true
dataTaskDetailResult
└taskTaskDetail
可能的错误
400invalid_status、listing_url_required(published 必须带 listingUrl)、invalid_listing_url 或 reason_required(blocked 必须带 reason)
401鉴权失败
403missing_scope_publish —— 这把密钥没有 publish 权限
404task_not_found
409transition_not_allowed —— 先读任务,next 列出允许的状态

示例

bash
curl -X POST https://www.querywin.com/api/v1/tasks/{id}/status \
  -H "Authorization: Bearer $QUERYWIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "published",
    "listingUrl": "https://example-directory.com/tools/your-product"
  }'
json — 响应
{
  "success": true,
  "data": {
    "task": null
  }
}
QueryWin 开放 API —— 给脚本与 AI 助手用的内容链与分发链接口