# 读取研究收集历史

标准 URL： https://sosoapi.ai/zh-hans/docs/api/research-api-collection-history-query

契约：sha256:ab393e91e9b7f18a

读取有界限的 UTC 群组观察；未知不等于零。部分 HN 样本不适合用来判断动能或预测。需要 agent:research。

POST /research-api/collection-history/query

## 验证与权限

- **接受的凭证类别：** user_session、delegated_oauth、personal_access_token

- **委派能力:** agent:research

- **最低工作区角色：** viewer

- **访问范围：** 此用户获准访问的资源

- **需要所有工作区同意：** 否

- **变更状态：** 否

- **操作完成时:** 当前获授权的单一确切来源群组汇总收集历史；收集计数不代表发布量、市场成长、动能或预测

令牌只能使用其所有者持有的权利。每次请求会检查工作区成员资格、资源拥有权、所选工作区及已授予能力。core 与 full 配置只变更显示的工具，不会授予访问权限。

## 请求字段

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "workspace_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "project_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "project_revision": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "corpus_snapshot_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "bucket": {
      "default": "day",
      "type": "string",
      "enum": [
        "hour",
        "day"
      ]
    },
    "since": {
      "type": "string",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "format": "date-time"
    },
    "until": {
      "type": "string",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "format": "date-time"
    }
  },
  "required": [
    "workspace_id",
    "project_id",
    "project_revision",
    "corpus_snapshot_id",
    "since",
    "until"
  ],
  "additionalProperties": false
}
```

## 响应与完成

成功 HTTP 状态：200

成功 HTTP 响应可能表示请求已接受，并非已完成。背景工作请存储返回 ID，持续检查同一操作直到完成。已排程或已接受的帖子，只有平台确认后才算已发布；客户端逾时无法证明结果。

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "workspace_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "project_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "project_revision": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "corpus_snapshot_id": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
    },
    "bucket": {
      "type": "string",
      "enum": [
        "hour",
        "day"
      ]
    },
    "since": {
      "type": "string",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "format": "date-time"
    },
    "until": {
      "type": "string",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "format": "date-time"
    },
    "generated_at": {
      "type": "string",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "format": "date-time"
    },
    "status": {
      "type": "string",
      "enum": [
        "available",
        "insufficient_history",
        "not_applicable",
        "incomparable"
      ]
    },
    "reason": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "no_listening_sources",
            "mixed_sources",
            "mixed_cohorts",
            "mixed_methods",
            "method_unavailable",
            "unsupported_method",
            "no_completed_observations",
            "history_limit"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "cohort": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "source": {
              "type": "string",
              "const": "hacker_news"
            },
            "query_revision": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            },
            "generation": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            },
            "method_version": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "selected_listening_refs": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            },
            "excluded_selected_items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 499
            },
            "scope": {
              "type": "string",
              "const": "selected_listening_stream_cohort"
            }
          },
          "required": [
            "source",
            "query_revision",
            "generation",
            "method_version",
            "selected_listening_refs",
            "excluded_selected_items",
            "scope"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "method_version": {
      "type": "string",
      "const": "listening-collection-history/v1"
    },
    "time_basis": {
      "type": "string",
      "const": "collection_completed_at_or_requested_at"
    },
    "deduplication": {
      "type": "string",
      "const": "latest_observation_per_source_per_bin"
    },
    "count_meaning": {
      "type": "string",
      "const": "bounded_collection_observations"
    },
    "momentum_eligible": {
      "type": "boolean",
      "const": false
    },
    "forecast_eligible": {
      "type": "boolean",
      "const": false
    },
    "qualification_reason": {
      "type": "string",
      "enum": [
        "hn_partial_overlapping_sample_unqualified",
        "no_qualified_cohort"
      ]
    },
    "observed_bins": {
      "type": "integer",
      "minimum": 0,
      "maximum": 24
    },
    "unknown_bins": {
      "type": "integer",
      "minimum": 0,
      "maximum": 24
    },
    "bins": {
      "maxItems": 24,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "format": "date-time"
          },
          "end": {
            "type": "string",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
            "format": "date-time"
          },
          "period_partial": {
            "type": "boolean"
          },
          "state": {
            "type": "string",
            "enum": [
              "observed",
              "unknown"
            ]
          },
          "counts": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "source_items": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10240
                  },
                  "matched_items": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10240
                  },
                  "removed_items": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10240
                  },
                  "unavailable_items": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10240
                  }
                },
                "required": [
                  "source_items",
                  "matched_items",
                  "removed_items",
                  "unavailable_items"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "runs": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "completed": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "successful": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "succeeded": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "partial": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "failed": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "cancelled": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              },
              "pending": {
                "type": "integer",
                "minimum": 0,
                "maximum": 512
              }
            },
            "required": [
              "total",
              "completed",
              "successful",
              "succeeded",
              "partial",
              "failed",
              "cancelled",
              "pending"
            ]
          },
          "source_windows": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "since": {
                    "type": "string",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "format": "date-time"
                  },
                  "until": {
                    "type": "string",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "format": "date-time"
                  },
                  "distinct_windows": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 512
                  }
                },
                "required": [
                  "since",
                  "until",
                  "distinct_windows"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "gaps": {
            "maxItems": 5,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "unobserved",
                "incomplete_collection",
                "failed_collection",
                "cancelled_collection",
                "partial_period"
              ]
            }
          },
          "coverage": {
            "type": "string",
            "const": "partial_indexed_sample"
          }
        },
        "required": [
          "start",
          "end",
          "period_partial",
          "state",
          "counts",
          "runs",
          "source_windows",
          "gaps",
          "coverage"
        ]
      }
    }
  },
  "required": [
    "workspace_id",
    "project_id",
    "project_revision",
    "corpus_snapshot_id",
    "bucket",
    "since",
    "until",
    "generated_at",
    "status",
    "reason",
    "cohort",
    "method_version",
    "time_basis",
    "deduplication",
    "count_meaning",
    "momentum_eligible",
    "forecast_eligible",
    "qualification_reason",
    "observed_bins",
    "unknown_bins",
    "bins"
  ]
}
```

## 错误与安全重试

检查 HTTP 状态和响应正文。400 验证错误可能包含 ZodError；处理程序错误使用 error、message 和 code 字段。保留 request_id 或 x-request-id 以便诊断，但不要保留凭证。先解决 401/403 访问错误再重试，并在收到 429 时遵循 Retry-After。如写入结果不确定或返回 5xx，先读取现有结果。仅在支持时复用幂等键；重试行为因操作而异，并不保证恰好交付一次。

## 示例

这些示例使用已依schema检查的虚构值。请将 ID 替换为你有权使用的 ID、将媒体替换为已就绪素材，并将日期替换为已确认的发布时间。提交写入前，请检查账号资格。本页不会发送 API 请求。

在服务器上将 SOSOAPI_ACCESS_TOKEN 设为此操作接受的凭证，且不要放入浏览器代码。AI 智能代理 请使用 sosoapi auth login 通过浏览器登录，并由 CLI 更新凭证。

request.json

```json
{
  "workspace_id": "11111111-1111-4111-8111-111111111111",
  "project_id": "30000000-0000-4000-8000-000000000001",
  "project_revision": 1,
  "corpus_snapshot_id": "30000000-0000-4000-8000-000000000002",
  "bucket": "day",
  "since": "2026-11-01T00:00:00Z",
  "until": "2026-11-02T00:00:00Z"
}
```

cURL

```bash
curl --request POST \
  "https://gqeshlawtcexsapabaui.supabase.co/functions/v1/research-api/collection-history/query" \
  -H "Authorization: Bearer $SOSOAPI_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @request.json
```

JavaScript

```js
// Server-side JavaScript. Do not print tokens or credential-bearing responses.
const token = process.env.SOSOAPI_ACCESS_TOKEN;
if (!token) throw new Error("Set an accepted credential for this operation");
const response = await fetch("https://gqeshlawtcexsapabaui.supabase.co/functions/v1/research-api/collection-history/query", {
  method: "POST",
  headers: { "Content-Type": "application/json", Authorization: "Bearer " + token },
  body: JSON.stringify({
  "workspace_id": "11111111-1111-4111-8111-111111111111",
  "project_id": "30000000-0000-4000-8000-000000000001",
  "project_revision": 1,
  "corpus_snapshot_id": "30000000-0000-4000-8000-000000000002",
  "bucket": "day",
  "since": "2026-11-01T00:00:00Z",
  "until": "2026-11-02T00:00:00Z"
})
});
const result = await response.json();
// Check response.ok, the operation-specific body and completion state before continuing.
```

CLI

```bash
npx sosoapi api post /research-api/collection-history/query < request.json
```

合成响应示例

```json
{
  "workspace_id": "11111111-1111-4111-8111-111111111111",
  "project_id": "30000000-0000-4000-8000-000000000001",
  "project_revision": 1,
  "corpus_snapshot_id": "30000000-0000-4000-8000-000000000002",
  "bucket": "day",
  "since": "2026-11-01T00:00:00Z",
  "until": "2026-11-02T00:00:00Z",
  "generated_at": "2026-11-03T00:00:00Z",
  "status": "insufficient_history",
  "reason": "no_completed_observations",
  "cohort": {
    "source": "hacker_news",
    "query_revision": 1,
    "generation": 1,
    "method_version": "hn-indexed-literal-sample/v1",
    "selected_listening_refs": 1,
    "excluded_selected_items": 0,
    "scope": "selected_listening_stream_cohort"
  },
  "method_version": "listening-collection-history/v1",
  "time_basis": "collection_completed_at_or_requested_at",
  "deduplication": "latest_observation_per_source_per_bin",
  "count_meaning": "bounded_collection_observations",
  "momentum_eligible": false,
  "forecast_eligible": false,
  "qualification_reason": "hn_partial_overlapping_sample_unqualified",
  "observed_bins": 0,
  "unknown_bins": 1,
  "bins": [
    {
      "start": "2026-11-01T00:00:00Z",
      "end": "2026-11-02T00:00:00Z",
      "period_partial": false,
      "state": "unknown",
      "counts": null,
      "runs": {
        "total": 0,
        "completed": 0,
        "successful": 0,
        "succeeded": 0,
        "partial": 0,
        "failed": 0,
        "cancelled": 0,
        "pending": 0
      },
      "source_windows": null,
      "gaps": [
        "unobserved"
      ],
      "coverage": "partial_indexed_sample"
    }
  ]
}
```

## 相关工具与指南

MCP： sosoapi_research_collection_history_query

[API 参考](https://sosoapi.ai/zh-hans/docs/api)
