使用 HTTP 接入应用
通过 HTTP 完成 RuntimeSession、模型媒体、应用间授权和开发者版本接入。
HTTP 合同是所有语言 SDK 的共同底座。本页区分三种完全不同的凭据,先选对运行场景再复制示例:
需要逐接口核对参数、返回、错误和幂等语义时,阅读“应用中心 HTTP API 参考”,或下载 OpenAPI YAML 导入支持 OpenAPI 3.1 的工具。
| 场景 | 凭据 | 地址 | 谁可以拿到 |
|---|---|---|---|
| 本地模拟 | CLI 注入的固定本地测试令牌 | 127.0.0.1 随机端口 | jusp app dev --local 子进程 |
| 本地联网调试 | jusp app dev --online 签发的短期调试令牌 | https://app-api.jusuanhub.com:10443/v1 | 当前开发者的本地进程 |
| 正式应用运行 | 平台托管应用身份 + 当前用户 RuntimeSession | 平台自动注入 | 已部署应用服务端 |
| 版本管理 | 短期 CLI 会话或已登录开发者会话 | /api/v1/appstore/developer | 当前应用所有者 |
不要把 SDK 下载凭据、调试令牌、平台托管应用凭据和 RuntimeSession 混用。它们权限、有效期和泄漏风险不同。
1. 本地固定模拟
对于 Go、Java、Node.js 或 shell,同样用 CLI 启动本地 HTTP 模拟:
jusp app dev --local --app-key my-app -- ./run-local.shrun-local.sh 不需要知道随机端口和固定测试令牌:
#!/usr/bin/env bash
curl --fail-with-body \
-X POST "$JUSP_APP_RUNTIME_BASE_URL/chat/completions" \
-H "Authorization: Bearer $JUSP_APP_RUNTIME_TOKEN" \
-H 'Content-Type: application/json' \
--data-binary '{"model":"local-chat","messages":[{"role":"user","content":"你好"}]}'本地模拟的 HTTP 路径、请求和返回结构与联网调试一致,另外覆盖 RuntimeSession 和应用间授权。所有结果都是稳定假数据;模拟器不连平台、不扣积分、不触及真实用户或应用数据。通过 --scenario 可切换 400/402/409/429/503/504 和异步失败。
2. 本地联网调试
先在已有项目目录执行:
jusp app dev --online \
--app-id <应用ID> \
--version-id <当前候选版本ID> \
-- ./run-debug.sh浏览器选择本人或已获准测试账号并确认后,子进程得到 JUSP_APP_RUNTIME_BASE_URL 和 JUSP_APP_RUNTIME_TOKEN。下面的脚本会真实调用平台并按所选账号扣积分:
#!/usr/bin/env bash
curl --fail-with-body \
-X POST "$JUSP_APP_RUNTIME_BASE_URL/chat/completions" \
-H "Authorization: Bearer $JUSP_APP_RUNTIME_TOKEN" \
-H 'Content-Type: application/json' \
--data-binary '{"model":"<从 services 返回的模型>","messages":[{"role":"user","content":"用一句话介绍成都"}]}'令牌只存在于子进程环境,到期后重新配对。不要写入 .env、shell history、日志、版本包或镜像层。
公网调试接口字典
Base URL:https://app-api.jusuanhub.com:10443/v1
| 方法 | 路径 | 用途 | 备注 |
|---|---|---|---|
| GET | /openapi.json | 读取当前公网合同 | 只用于开发工具和类型生成 |
| GET | /services | 查询当前可调用服务和动态媒体规格 | 调用前优先查询 |
| GET | /models | 查询兼容模型别名 | 只使用返回值,不猜模型名 |
| GET | /audio/voices | 查询可用音色 | 返回公开音色 ID |
| GET | /audio/voices/{voiceId} | 查询音色详情 | ID 必须来自音色列表 |
| POST | /chat/completions | 文本或多模态对话 | OpenAI 风格 messages |
| POST | /embeddings | 向量化 | 服务必须支持 embedding |
| POST | /rerank | 文档重排 | 传 query 和 documents |
| POST | /ocr | OCR | 以服务合同为准 |
| POST | /documents/parse | 文档结构化解析 | 可返回结构化产物 |
| POST | /audio/transcriptions | 语音转写 | 文件/引用格式以服务合同为准 |
| POST | /audio/generations | 语音生成 | 真实扣费 |
| POST | /images/generations | 图片生成 | 真实扣费 |
| POST | /media/generations | 视频等异步媒体生成 | 返回任务标识 |
| POST | /media/prompt-optimizations | 提示词优化 | clientRequestId 和公开 model 别名必填 |
| POST | /assets/input?model=... | 上传短期调试输入素材 | multipart 字段名为 file |
| GET | /jobs/{jobId} | 查询异步任务 | 使用原任务标识 |
| GET/HEAD | /assets/{assetId}/content | 读取结果或元数据 | URL 和过期时间以响应为准 |
| POST | /admission/preview | 预估媒体准入 | 不代表最终一定执行 |
具体请求字段不是静态猜测出来的。先调用 /services 并用 serviceKind 过滤,选择 available: true 的服务,再按其 mediaSpecContract 和能力约束组织请求。Python SDK 会把原始 modelAlias/available 统一为 model/status。
3. 用户打开应用与 RuntimeSession
用户点击应用后,平台从当前登录身份生成一次性打开信息,并把下面的 runtime 对象交给目标应用:
{
"runtime": {
"launchCode": "一次性短码",
"appKey": "your-app",
"appVersionId": "appver_...",
"expiresAt": "2026-08-31T12:00:00Z"
}
}浏览器把 launchCode 交给目标应用自己的 /api/runtime/exchange。Python SDK 会自动使用平台托管的应用身份完成交换;其他语言按下面的 HTTP 合同实现:
POST {JUSP_APP_SESSION_BASE_URL}/apps/{appKey}/runtime-sessions:exchange
Authorization: Bearer <平台注入的应用凭据>
Content-Type: application/json
{"launchCode":"..."}响应:
{
"sessionId": "session_...",
"appKey": "your-app",
"appVersionId": "appver_...",
"subject": {
"tenantId": "...",
"accountId": "...",
"workspaceId": "...",
"userId": "...",
"organizationId": "...",
"membershipId": "..."
},
"appRoles": ["your-app.editor"],
"expiresAt": "2026-08-31T12:30:00Z"
}约束:
- 启动码只能成功交换一次;错误应用不能消费别人的启动码。
- 应用凭据必须与
appKey匹配。 - 浏览器不持有应用凭据,也不直接调用平台运行接口。
- RuntimeSession 是当前用户、当前应用、当前版本的不可变快照,不是永久登录态。
- 不接受浏览器额外提交的用户、租户或角色字段。
需要重新确认会话时,服务端调用:
GET {JUSP_APP_SESSION_BASE_URL}/apps/{appKey}/runtime-sessions/{sessionId}:resolve
Authorization: Bearer <平台注入的应用凭据>成功解析最多做 1 秒的有界正向缓存,并且不能越过 expiresAt;401/403/404 不缓存。
4. 组织结构与成员目录
组织管理员在应用内选择部门、班级或成员时,应用使用当前 RuntimeSession,不能让前端提交组织 ID。正式应用后端使用平台托管应用凭据调用:
POST {JUSP_APP_SESSION_BASE_URL}/apps/{appKey}/runtime-sessions/{sessionId}/organization-directory/groups:list
Authorization: Bearer <平台托管应用凭据>
Content-Type: application/json
{}POST {JUSP_APP_SESSION_BASE_URL}/apps/{appKey}/runtime-sessions/{sessionId}/organization-directory/members:list
Authorization: Bearer <平台托管应用凭据>
Content-Type: application/json
{"groupId":"group_...","includeDescendants":true,"search":"张","page":1,"pageSize":50}平台从会话推导组织并重新读取当前成员和应用角色事实。只有组织管理员上下文可访问;响应只包含组结构、展示名、成员关系、组织角色和当前应用角色,不包含联系方式、密码、余额、平台内部角色或其他应用角色。
本地联网调试使用 CLI 短期令牌,不能使用正式应用凭据。CLI 注入的 JUSP_APPSTORE_DEVELOPER_BASE_URL 是以下接口的前缀;应用、版本及会话 ID 均由本次配对产生:
curl --fail-with-body -X POST \
"$JUSP_APPSTORE_DEVELOPER_BASE_URL/apps/$JUSP_APP_ID/versions/$JUSP_APP_VERSION_ID/runtime-sessions/$JUSP_APP_RUNTIME_SESSION_ID/organization-directory/groups:list" \
-H "Authorization: Bearer $JUSP_APP_DEBUG_TOKEN" \
-H 'Content-Type: application/json' --data '{}'成员接口把末尾换成 members:list,分页字段同正式接口。默认使用本人;如果本人不是组织管理员,请超管为此应用授权专用测试组织的管理员账号,再在浏览器确认页选择该账号。平台新签发 1 小时调试会话,不提供下载他人登录 session 的接口。移除授权后旧调试会话的后续请求失效。
5. 正式应用调用模型和媒体
平台给应用自动注入 Base URL 与应用凭据。Python SDK 会生成下列请求;其他语言实现必须同时携带平台注入的应用凭据和当前 RuntimeSession:
POST {JUSP_APP_RUNTIME_BASE_URL}/chat/completions
Authorization: Bearer <平台注入的应用凭据>
X-Jusp-Runtime-Session-Id: session_...
Content-Type: application/json
{"model":"<从 available-services 返回的模型>","messages":[{"role":"user","content":"你好"}]}正式 Runtime 接口:
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /available-services | 当前用户、应用和版本可调用的服务 |
| POST | /chat/completions | 文本/多模态对话 |
| POST | /embeddings | 向量化 |
| POST | /rerank | 重排 |
| POST | /ocr | OCR |
| POST | /audio/transcriptions | 语音转写 |
| POST | /media/prompt-optimizations | 提示词优化,必须有 clientRequestId、公开 model 别名和媒体上下文 |
| POST | /media/jobs:dry-run | 媒体任务准入预检 |
| POST | /media/jobs | 创建异步媒体任务 |
| POST | /media/jobs:batch-get | 用 platformJobIds 批量读取最多 100 个任务 |
| GET | /media/events | 通过 SSE 按游标持续恢复任务事件 |
| GET | /media/jobs/{jobId} | 查询任务 |
| GET | /media/jobs/{jobId}/results/{assetId}/download | 下载任务结果 |
| POST | /media/exports | 创建结果导出 |
| GET | /media/exports/{exportId} | 查询导出 |
| GET | /media/exports/{exportId}/download | 下载导出 |
| POST | /resource-usage:aggregate | 按本应用的受限业务资源 ID 聚合用量 |
创建异步任务应发送稳定的 Idempotency-Key。平台返回的 jobRecoveryRef 只属于该任务的受控恢复,不是用户身份替代品;恢复查询时按 SDK 指示发送,不能拿来发起新任务。SDK对创建、查询、下载、事件consume_events和批量batch_get_jobs提供命名方法;导出创建/查询及资源用量使用request,二进制导出下载按正式Runtime参考使用HTTP客户端。完整正文与恢复例子见媒体全链路,本表仅是指南索引,不替代逐接口字段。
可觅常规模型调用属于哪条链
可觅的文本扩写、内容分析和提示词优化直接走本节 Runtime API:
可觅业务请求 → RuntimeSession → 应用 Runtime → 已上架模型服务普通模型调用不需要经过 Agent Runtime。
6. 应用间调用
例如 VideoForge 要调用可觅:调用方不能把自己的应用凭据或 RuntimeSession 直接交给可觅。正确链路是短期、单用途授权:
VideoForge 当前 RuntimeSession
→ AppStore 签发 grant(绑定 callee、scope、请求摘要、幂等键)
→ VideoForge 把 grant 和业务请求发给可觅
→ 可觅用自己的平台托管身份核验 grant
→ 可觅得到同一用户的受控主体快照调用方签发:
POST {JUSP_APP_SESSION_BASE_URL}/apps/{callerAppKey}/app-grants
Authorization: Bearer <调用方的平台托管应用凭据>
Content-Type: application/json
{
"runtimeSessionId": "session_...",
"calleeAppKey": "coommc",
"scope": "integration.probe",
"idempotencyKey": "probe-1",
"requestDigest": "sha256:<规范化业务请求摘要>"
}被调用方解析:
POST {JUSP_APP_SESSION_BASE_URL}/apps/{calleeAppKey}/app-grants:resolve
Authorization: Bearer <被调用方的平台托管应用凭据>
Content-Type: application/json
{"grant":"...","scope":"integration.probe","requestDigest":"sha256:..."}Grant 与被调用应用、scope、请求摘要、当前用户和有效期绑定。请求正文变化后必须重新签发,不能复用旧摘要。
本地联调
调用方项目先在 .jusp/app.yaml 声明 dependencies[].appKey/apiVersion/capabilities,再把提供方绑定到本机回环地址:
jusp app dev --local --app-key videoforge \
--dependency coommc=http://127.0.0.1:9080 \
-- ./run-debug.shCLI 只接受已声明依赖和本机地址。提供方应维护自己的 OpenAPI、语言 SDK 和本地假服务;平台不替应用猜业务协议。
联网调试
联网调试命令必须携带候选版本 ID。CLI 注入 JUSP_APP_DEBUG_TOKEN、JUSP_APP_ID、JUSP_APP_VERSION_ID 和 JUSP_APP_INTERAPP_BASE_URL。调用方先签发调试 grant:
以下 integration.probe 是无业务回显样例,只用于证明授权和路由闭环,不读取或修改聚算可觅项目。真实业务路径和 DTO 必须以被调应用自己的 OpenAPI/SDK 为准。
POST https://app-api.jusuanhub.com:10443/api/v1/appstore/developer/apps/{appId}/versions/{versionId}/app-grants
Authorization: Bearer <CLI短期调试令牌>
Content-Type: application/json
{
"calleeAppKey": "coommc",
"apiVersion": "v1",
"scope": "integration.probe",
"idempotencyKey": "probe-1",
"requestDigest": "sha256:<规范化业务请求摘要>"
}然后调用公开中转入口:
POST https://app-api.jusuanhub.com:10443/v1/inter-app/coommc/v1/probe:echo
Authorization: Bearer <CLI短期调试令牌>
X-Jusp-App-Grant: <上一步返回的grant>
Content-Type: application/json
{"echo":"hello"}平台只允许候选版本已声明的依赖;目标应用必须在激活的生产版本中声明同一 API 版本、scope 与 onlineDebug: true。中转入口不暴露目标应用集群地址,不接受开发者自行指定上游,不自动重试业务请求。
7. 开发者版本 HTTP 接口
前缀:/api/v1/appstore/developer。所有单应用接口先校验所有权,越权和不存在统一返回 404。
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /publishers | 读取当前个人开发者的隐藏建档记录;通常由页面自动使用 |
| GET/POST | /apps | 列出或创建自己的应用 |
| GET | /apps/{appId} | 应用详情 |
| GET | /apps/{appId}/versions | 版本列表 |
| POST | /apps/{appId}/submissions:validate | 只校验版本提交包 |
| POST | /apps/{appId}/versions | 创建版本,可 multipart 附源文件 |
| GET/DELETE | /apps/{appId}/versions/{versionId} | 查看版本,或按当前状态发起删除申请 |
| PUT | /apps/{appId}/versions/{versionId}/source | 更新结构化源事实 |
| POST | /apps/{appId}/versions/{versionId}/source/upload | 上传源文件 |
| GET | /apps/{appId}/versions/{versionId}/source/content | 在认证会话中查看原始 JSON |
| GET | /apps/{appId}/versions/{versionId}/source/download | 下载原始源文件 |
| POST/GET | /apps/{appId}/versions/{versionId}/requests | 创建/查看删除、上架或下架申请 |
| POST | /apps/{appId}/versions/{versionId}/changes | 创建或恢复同版本修改稿 |
| POST | /apps/{appId}/versions/{versionId}/changes/{requestId}/source/upload | 替换修改稿源文件并重新解析 |
| POST | /apps/{appId}/versions/{versionId}/changes/{requestId}/submit | 提交确有差异的修改稿;理由可空 |
| GET | /apps/{appId}/versions/{versionId}/audit | 版本审计 |
| POST | /apps/{appId}/image-imports | 版本创建前上传镜像 |
| POST | /apps/{appId}/versions/{versionId}/image-imports | 给草稿版本上传镜像 |
| POST | /apps/{appId}/versions/{versionId}/validate | 执行平台检查 |
| POST | /apps/{appId}/versions/{versionId}/submit | 提交上架审核 |
| GET/PUT | /apps/{appId}/roles | 查看/维护应用角色定义 |
| POST | /apps/{appId}/cli-authorizations | 签发一次性 CLI 配对码 |
| POST | /cli-sessions:exchange | 用一次性配对码和 PKCE verifier 换取短期 CLI token |
| POST | /apps/{appId}/launch | 给自有版本签发短期预览启动码 |
| POST | /sdk/python/credentials | 签发 SDK 下载凭据 |
镜像字节不直接发给平台制品仓库。创建 image import 后,平台返回短期分片 URL;客户端上传所有分片,再调用 complete,平台加载、存放并返回不可变摘要。
镜像导入的完整顺序是:
POST /apps/{appId}/image-imports,传文件名、字节数、归档 SHA-256、组件名、展示版本和幂等键。- 按返回的
uploadParts[].url上传 tar 分片,记录每个ETag;这些 URL 只是当前上传会话的短期地址。 POST /apps/{appId}/image-imports/{imageImportId}/complete,传分片编号、ETag和字节数。- 平台检查归档、导入并返回
imageAssetId和不可变摘要;版本包只引用imageAssetId。
如果版本已存在,把上述路径改为 /apps/{appId}/versions/{versionId}/image-imports...,就会绑定该草稿版本。生产项目建议使用 Python SDK 或 jusp app image upload,它们已处理分片和幂等重试。
8. 错误、重试和请求追踪
错误响应至少提供 code、message 和请求 ID。保存请求 ID,排查时不要保存令牌或完整业务正文。
| HTTP | 含义 | 客户端动作 |
|---|---|---|
| 400 | 请求字段或状态不合法 | 修正请求,不重试 |
| 401 | 凭据或 RuntimeSession 失效 | 重新授权/重新打开应用 |
| 402 | 余额不足 | 提示用户充值,不重试 |
| 403 | 当前主体无权限 | 停止,不换用户绕过 |
| 404 | 资源不存在或所有权不匹配 | 刷新列表,不探测 ID |
| 409 | 幂等冲突或状态已变化 | 读取最新状态后决定 |
| 429 | 限流 | 仅按 Retry-After 退避 |
| 5xx | 平台暂不可用 | 仅幂等请求指数退避 |
同步生成请求没有幂等键时不自动重试。异步任务、版本创建和应用间授权使用稳定幂等键,避免重复任务、重复审核或重复扣费。