Explore 应用市场 API
Explore 探索广场(应用市场)接口。包含两类端点:
- 公开广场(无需登录):浏览分类、公开应用列表与详情。
- 用户端申请上架(需登录):项目作者申请把已发布的应用上架到 Explore、查询申请状态、撤回申请。
可见性遵循「双门」语义:一个应用要在广场公开,既需要运营审核通过(status='approved'),又需要作者把对应 deployment 设为公开(visibility='public' 且未删除)。两道门相互独立,审批不会改写 deployment 的可见性。
源码:apps/backend/src/routes/explore.ts
认证
| 类别 | 路由前缀 | 认证 |
|---|---|---|
| 公开广场 | /api/explore | 无需登录 |
| 申请上架 | /projects | JWT Bearer Token,且需对目标项目有 write(读列表为 read)权限 |
Authorization: Bearer <JWT>申请状态机
申请(submission)在以下状态间流转:
| 状态 | 含义 |
|---|---|
pending | 已提交,待审核 |
approved | 审核通过(满足双门后即在广场展示) |
rejected | 审核驳回 |
withdrawn | 作者主动撤回 |
delisted | 已上架后被运营下架 |
pending → approved / rejected / withdrawnapproved → delistedrejected / withdrawn / delisted之后可对同一文档重新发起新申请。- 同一文档同一时刻只允许存在一个活跃申请(
pending或approved);重复申请返回409。
公开广场端点(无需登录)
GET /api/explore/categories
获取分类 key 列表。展示名由前端按 key 做国际化映射。
请求参数
无。
响应格式
{
"categories": ["agents", "marketing", "research", "finance", "lifestyle", "hr", "tools"]
}错误码
| 状态码 | 说明 |
|---|---|
500 | 获取分类失败 |
GET /api/explore/apps
获取公开应用列表。仅返回审核通过且 deployment 满足公开条件的应用(fail-closed)。
Query 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
category | string | 否 | 按分类 key 筛选,必须是合法分类 |
featured | string | 否 | 传 true 时仅返回精选应用 |
page | int | 否 | 页码,从 1 开始,默认 1,上限 1000 |
limit / pageSize | int | 否 | 每页条数,默认 20,上限 50(limit 优先于 pageSize) |
排序固定为:精选优先(
featured降序)→ 权重降序(sort_weight)→ 审核通过时间降序(approved_at)。
响应格式
{
"items": [
{
"submission": {
"id": "uuid",
"deployment_id": "uuid",
"document_id": "uuid",
"work_type": "flow",
"category": "agents",
"title": "示例应用",
"description": "应用简介",
"featured": false,
"sort_weight": 0,
"approved_at": "2026-06-22T00:00:00.000Z"
},
"deployment": {
"id": "uuid",
"title": "示例应用",
"description": "展示用描述",
"banner_image": "https://...",
"version_major": 1,
"version_minor": 0,
"doc_type": "flow",
"team_name": "示例团队"
}
}
],
"total": 1,
"page": 1,
"pageSize": 20
}
work_type取值为flow或ui。deployment.title/description在 deployment 自身缺省时会回落到对应文档的标题/描述。
错误码
| 状态码 | code | 说明 |
|---|---|---|
400 | invalid_pagination | page / limit 不是正整数 |
400 | page_too_large | page 超过 1000 |
400 | invalid_category | category 不在合法分类列表中 |
500 | - | 获取列表失败 |
GET /api/explore/apps/:deployment_id
获取单个公开应用详情,一次性返回详情页所需字段。
路径参数
| 参数 | 说明 |
|---|---|
deployment_id | deployment ID |
响应格式
返回 { submission, deployment },结构同列表中的单个条目(见上)。
未审核通过、deployment 已转为私有或已删除的应用一律返回
404,不暴露其存在性。
错误码
| 状态码 | 说明 |
|---|---|
404 | 应用不存在或不满足公开条件 |
500 | 获取详情失败 |
用户端申请上架端点(需登录)
POST /projects/:projectId/explore-submissions
为项目下的某个 deployment 申请上架 Explore。需对项目有 write 权限。
路径参数
| 参数 | 说明 |
|---|---|
projectId | 项目 ID |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
deployment_id | string | 是 | 待上架的 deployment ID,必须属于该项目且未删除 |
category | string | 是 | 分类 key,必须是合法分类 |
title | string | 是 | 申请标题,最长 200 字符 |
description | string | null | 否 | 申请描述,最长 5000 字符 |
{
"deployment_id": "uuid",
"category": "agents",
"title": "我的应用",
"description": "应用简介"
}响应格式(201)
{
"success": true,
"submission": {
"id": "uuid",
"deployment_id": "uuid",
"document_id": "uuid",
"project_id": "uuid",
"team_id": "uuid",
"submitted_by_user_id": "uuid",
"work_type": "flow",
"category": "agents",
"title": "我的应用",
"description": "应用简介",
"status": "pending",
"status_reason": null,
"reviewed_by_user_id": null,
"reviewed_at": null,
"featured": false,
"sort_weight": 0,
"approved_at": null,
"created_at": "2026-06-22T00:00:00.000Z",
"updated_at": "2026-06-22T00:00:00.000Z"
}
}冲突响应(409)
当该文档已有进行中(pending / approved)的申请时返回,附带现有申请,供前端渲染按钮状态:
{
"error": "该文档已有进行中的申请",
"code": "active_submission_exists",
"submission": { "id": "uuid", "status": "pending", "...": "..." }
}错误码
| 状态码 | code | 说明 |
|---|---|---|
400 | - | 请求体无效,或 deployment_id / category / title 缺失,或字段超长 |
400 | invalid_category | category 不在合法分类列表中 |
401 | - | 未登录 |
403 | - | 对该项目无 write 权限 |
404 | - | Deployment 不存在或不属于该项目 |
409 | active_submission_exists | 该文档已有进行中的申请 |
500 | - | 创建申请失败 |
GET /projects/:projectId/explore-submissions
获取本项目下的所有申请(含各状态),用于查看审核进度。需对项目有 read 权限。
路径参数
| 参数 | 说明 |
|---|---|
projectId | 项目 ID |
响应格式
{
"success": true,
"items": [
{
"id": "uuid",
"deployment_id": "uuid",
"document_id": "uuid",
"project_id": "uuid",
"team_id": "uuid",
"submitted_by_user_id": "uuid",
"work_type": "flow",
"category": "agents",
"title": "我的应用",
"description": "应用简介",
"status": "pending",
"status_reason": null,
"reviewed_by_user_id": null,
"reviewed_at": null,
"featured": false,
"sort_weight": 0,
"approved_at": null,
"created_at": "2026-06-22T00:00:00.000Z",
"updated_at": "2026-06-22T00:00:00.000Z",
"deployments": {
"id": "uuid",
"visibility": "public",
"deleted_at": null,
"version_major": 1,
"version_minor": 0
}
}
]
}每条申请附带对应 deployment 的当前可见性快照,便于前端判断「审核已过但 deployment 仍私有」等情形。
错误码
| 状态码 | 说明 |
|---|---|
401 | 未登录 |
403 | 对该项目无 read 权限 |
500 | 查询申请列表失败 |
POST /projects/:projectId/explore-submissions/:id/withdraw
撤回一个待审核申请(pending → withdrawn)。撤回不硬删,仅改状态留审计痕迹。需对项目有 write 权限。
路径参数
| 参数 | 说明 |
|---|---|
projectId | 项目 ID |
id | 申请 ID(必须属于该项目) |
请求体
无。
响应格式
{
"success": true,
"submission": { "id": "uuid", "status": "withdrawn", "...": "..." },
"idempotent": false
}对已撤回的申请重复撤回是幂等操作:返回当前状态且
idempotent: true,不报错。
错误码
| 状态码 | code | 说明 |
|---|---|---|
401 | - | 未登录 |
403 | - | 对该项目无 write 权限 |
404 | - | 申请不存在或不属于该项目 |
409 | invalid_transition | 当前状态不可撤回(如已 approved / rejected),附带当前申请 |
500 | - | 撤回申请失败 |