ComfyOne API文档
OnethingAI
发布于:2025-06-12
获取开发者密钥
此密钥为平台API操作唯一标识,务必保证不要泄露
❗️登录OneThingAI平台,进入账户中心,选择开发者密钥自助创建密钥
ComfyOne简介
ComfyOne可以将多个ComfyUI应用合并统一调度使用,支持多工作流可以并发执行功能 ,可自行管理应用实例,上下线实例能力
域名: https://pandora-server-cf.onethingai.com
必须请求头信息
头名称 | 内容 |
---|---|
Authorization | Bearer {TOKEN} |
ComfyOne 整体使用流程
也可以使用以下的sdk来操作ComfyOne API
python sdk (需要使用更复杂的任务调度的,可以使用sdk提供的节点scheduler 模块来实现scheduler 例子)
typescript sdk (例子参考 examples/main.ts)
版本更新说明
### v1.1.5版本 + 优化程序 + 限制每个用户最大连接 ws 数
v1.1.4 版本
支持自定义工作流任务
v1.1.3 版本
修复查询任务状态接口偶尔出现 404 问题
支持查询历史任务列表接口
v1.1.2 版本
修复调度工作流节点 ID为非数字问题
修复部分任务失败未通知问题
任务状态接口返回任务耗时
v1.1.1 版本
支持系统环境变量输入
修复任务执行后不更新状态问题
修复部分失败任务消息通知丢失问题
任务超时无法被调度,自动失败能力
v1.1.0 版本
支持 WebSocket 任务状态通知
支持运行中任务也可以取消
任务执行错误返回执行错误节点
注意:只保留 3 天内的任务和结果数据,如有需要麻烦自行在有效期内保存好
系统变量
系统变量,在执行前系统会自动更新为对应的数据
{COMFYONE:TASK_ID} 任务ID
{COMFYONE:WORKFLOW_ID} 工作流ID
示例
提交任务信息
// 提交任务的参数为
{
"workflow_id": "test123",
"inputs":[
{"id": "8", "task_id": "{COMFYONE:TASK_ID}", "workflow_id":"{COMFYONE:WORKFLOW_ID}"}
],
...
}
// {"code":0,"msg":"success","data":{"task_id":"task456"}}
真实提交到后端为
{
"inputs":[
{"id": "8", "task_id": "task456", "workflow_id":"test123"}
],
...
}
开放接口
GET 实例列表
GET /v1/backends
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": [
{
"name": "string",
"tasks": 0,
"is_live": true,
"is_down": true
}
]
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | [object] | true | none |
| none |
»» name | string | true | none |
| 实例ID |
»» tasks | integer | true | none |
| 当前运行任务数 |
»» is_live | boolean | true | none |
| 是否存活 |
»» is_down | boolean | true | none |
| 是否手动下线 |
POST 添加实例
POST /v1/backends
Body 请求参数
{"instance_id": "string" }
如何获取实例 ID
点击我的应用
找到创建好的 ComfyUI 应用
在应用 ID 处,点击复制按钮
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
body | body | object | 否 | none |
» instance_id | body | string | 是 | 实例 ID |
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": {
"name": "string",
"tasks": 0,
"is_live": true,
"is_down": true
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» name | string | true | none |
| 实例 ID |
»» tasks | integer | true | none |
| 当前任务数 |
»» is_live | boolean | true | none |
| 是否存活 |
»» is_down | boolean | true | none |
| 是否手动下线 |
PATCH 上下线实例
PATCH /v1/backends/{name}
Body 请求参数
{
"state": "up"
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
name | path | string | 是 | 实例ID |
body | body | object | 否 | none |
» state | body | string | 是 | 实例状态 |
枚举值
属性 | 值 |
» state | up |
» state | down |
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": {
"name": "string",
"tasks": 0,
"is_live": true,
"is_down": true
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» name | string | true | none |
| 实例ID |
»» tasks | integer | true | none |
| 当前任务数 |
»» is_live | boolean | true | none |
| 是否存活 |
»» is_down | boolean | true | none |
| 是否手动下线 |
DELETE 删除实例
DELETE /v1/backends/{name}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
name | path | string | 是 | none |
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": {
"name": "string",
"tasks": 0,
"is_ive": true,
"is_down": true
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» name | string | true | none |
| 实例 ID |
»» tasks | integer | true | none |
| 当前任务数 |
»» is_ive | boolean | true | none |
| 是否存活 |
»» is_down | boolean | true | none |
| 是否手动下线 |
POST 创建工作流
POST /v1/workflows
Body 请求参数
示例请求数据
{
"name": "test",
"inputs": [
{
"id": "5",
"name": "width",
"type": "number"
},
{
"id": "5",
"name": "height",
"type": "number"
}
],
"outputs": [
"9"
],
"workflow": {
"3": {
"inputs": {
"seed": 156680208700286,
"steps": 20,
"cfg": 8,
"sampler_name": "euler",
"scheduler": "normal",
"denoise": 1,
"model": [
"4",
0
],
"positive": [
"6",
0
],
"negative": [
"7",
0
],
"latent_image": [
"5",
0
]
},
"class_type": "KSampler"
},
"4": {
"inputs": {
"ckpt_name": "AWPainting_1.4.safetensors"
},
"class_type": "CheckpointLoaderSimple"
},
"5": {
"inputs": {
"width": 512,
"height": 512,
"batch_size": 1
},
"class_type": "EmptyLatentImage"
},
"6": {
"inputs": {
"text": "beautiful scenery nature glass bottle landscape, , purple galaxy bottle,",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode"
},
"7": {
"inputs": {
"text": "text, watermark",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode"
},
"8": {
"inputs": {
"samples": [
"3",
0
],
"vae": [
"4",
2
]
},
"class_type": "VAEDecode"
},
"9": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"8",
0
]
},
"class_type": "SaveImage"
}
}
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
body | body | object | 是 | 提交内容 |
» name | body | string | 是 | 工作流名称 |
» inputs | body | [object] | 是 | 工作流输入定义 |
»» id | body | integer|string | 是 | 节点 ID |
»» name | body | string | 是 | 输入名称 |
»» type | body | string | 是 | 输出参数类型 |
» outputs | body | [string] | 是 | 工作流需要获取输出的节点 |
» workflow | body | object | 是 | 工作流信息 |
»» ^[0-9]+(\:\d+)?$ | body | 否 | 节点定义 | |
»»» class_type | body | string | 是 | 节点类名称 |
»»» inputs | body | object | 否 | 节点的输入定义 |
枚举值
属性 | 值 | 说明 |
»» type | image | 图片类型 |
»» type | string | 字符串 |
»» type | number | 数字,可以是整数、小数 |
请求示例
const fetch = require('node-fetch');
const workflowName = 'test';
const inputs = [{id: 10, type: 'image', name: 'image'}...];
const outputs = ['13'];
const workflowData = {"10": {inputs: {image: "", upload: "image"},"class_type": "LoadImage"},...};
const run = async function createWorkflow(name, inputs, outputs, workflow){
const url = 'https://pandora-server-cf.onethingai.com/v1/workflows'
const resp = await fetch(url, {
headers: {
"accept": 'application/json',
"content-type": 'application/json',
"Authorization": `Bearer ${process.env.ONETHINGAI_TOKEN}`
},
body: JSON.stringify({ name, inputs, outpus, workflow }),
method: "POST"
});
return await resp.json()
}
console.log(run(workflowName, inputs, outputs, workflowData))
返回示例
200 Response
{
"code": 0,
"msg": "Success",
"data": {
"id": "667d3a99c8e1118ea12be2b9"
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| 结果数据 |
»» id | string | true | none |
| 工作流ID |
如何获取工作流信息
打开 ComfyUI 界面,点击如图1所示的设置
在设置界面找到开启开发模式,勾选,如图2所示
配置好的工作流后,点击保存API格式,如图3所示
打开下载的文件,拷贝里面的所有内容,这就是工作流的真实信息
图1
图2
图3
PATCH 修改工作流
PATCH /v1/workflows/{id}
Body 请求参数
{
"inputs": [
{
"id": "5",
"name": "width",
"type": "number"
}
]
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
id | path | string | 是 | 工作流ID |
body | body | object | 否 | 提交内容 |
» name | body | string | 否 | 工作流名称 |
» inputs | body | [object] | 否 | 工作流输入定义 |
»» id | body | integer|string | 是 | 节点 ID |
»» params | body | object | 是 | 输入定义 |
» outputs | body | [string] | 否 | 工作流需要获取输出的节点 |
» workflow | body | 否 | 工作流信息 | |
»» class_type | body | string | 是 | 节点类名称 |
»» inputs | body | object | 是 | 节点输入定义 |
请求示例
const fetch = require('node-fetch');
const workflowId = '667d3a99c8e1118ea12be2b9';
const inputs = [{id: 10, type: 'image', name: 'image'}...];
const outputs = ['13'];
const workflowData = {"10": {inputs: {image: "", upload: "image"},"class_type": "LoadImage"},...};
const run = async function createWorkflow(workflowId, inputs, outputs, workflow){
const url = `https://pandora-server-cf.onethingai.com/v1/workflows/${workflowId}`
const resp = await fetch(url, {
headers: {
"accept": 'application/json',
"content-type": 'application/json',
"Authorization": `Bearer ${process.env.ONETHINGAI_TOKEN}`
},
body: JSON.stringify({ inputs, outpus, workflow }),
method: "PATCH"
});
return await resp.json()
}
console.log(run(workflowId, inputs, outputs, workflowData))
返回示例
200 Response
{
"code": 0,
"msg": "Success",
"data": {
"id": "667d3a99c8e1118ea12be2b9"
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» id | string | true | none |
| 工作流ID |
DELETE 删除工作流
DELETE /v1/workflows/{id}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
id | path | string | 是 | none |
请求示例
const fetch = require('node-fetch');
const workflowId = '667d3a99c8e1118ea12be2b9';
const run = async function createWorkflow(workflowId){
const url = `https://pandora-server-cf.onethingai.com/v1/workflows/${workflowId}`
const resp = await fetch(url, {
headers: {
"accept": 'application/json',
"content-type": 'application/json',
"Authorization": `Bearer ${process.env.ONETHINGAI_TOKEN}`
},
method: "DELETE"
});
return await resp.json()
}
console.log(run(workflowId))
返回示例
200 Response
{
"code": 0,
"msg": "Success",
}
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
GET 工作流列表
GET /v1/workflows
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
page | query | integer | 否 | 页码 |
page_size | query | integer | 否 | 10 |
Host | header | string | 否 | none |
请求示例
const fetch = require('node-fetch');
const run = async function listWorkflows(page, pageSize){
const url = `https://pandora-server-cf.onethingai.com/v1/workflows?page=${page}&page_size=${pageSize}`
const resp = await fetch(url, {
headers: {
"accept": 'application/json',
"content-type": 'application/json',
"Authorization": `Bearer ${process.env.ONETHINGAI_TOKEN}`
},
method: "GET"
});
return await resp.json()
}
console.log(run(1, 10))
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": {
"list": [
{
"id": "string",
"name": "string",
"inputs": [
{
"id": null,
"name": null,
"type": null
}
],
"outputs": [
"string"
],
"total_nodes": 0,
"updated_at": "string",
"created_at": "string"
}
],
"pagination": {
"page": 1,
"page_size": 10,
"total": 1
}
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» list | [object] | true | none |
| none |
»»» id | string | true | none |
| 工作流ID |
»»» name | string | true | none |
| 工作流名称 |
»»» inputs | [object] | false | none |
| 工作流输入定义 |
»»»» id | integer | true | none |
| 节点 ID |
»»»» name | string | true | none |
| 节点参数名称 |
»»»» type | string | true | none |
| 节点参数类型 |
»»» outputs | [string] | false | none |
| 工作流需要获取输出的节点 |
»»» total_nodes | integer | true | none |
| 总节点数 |
»»» updated_at | string | true | none |
| 更新时间 |
»»» created_at | string | true | none |
| 创建时间 |
»» pagination | object | false | none |
| none |
»»» page | integer | true | none |
| 当前页面 |
»»» page_size | integer | true | none |
| 每页限制条数 |
»»» total | integer | true | none |
| 总记录数 |
GET 单个工作流
GET /v1/workflows/{id}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
id | path | string | 是 | none |
请求示例
const fetch = require('node-fetch');
const workflowId = '667d3a99c8e1118ea12be2b9';
const run = async function createWorkflow(workflowId){
const url = `https://pandora-server-cf.onethingai.com/v1/workflows/${workflowId}`
const resp = await fetch(url, {
headers: {
"accept": 'application/json',
"content-type": 'application/json',
"Authorization": `Bearer ${process.env.ONETHINGAI_TOKEN}`
},
method: "GET"
});
return await resp.json()
}
console.log(run(workflowId))
返回示例
200 Response
{
"code": 0,
"msg": "Success",
"data": {
"id": "667d3a99c8e1118ea12be2b9",
"name": "test",
"inputs": [
{
"id": 10,
"name": "image",
"type": "image"
}
],
"outputs": [
"13"
],
"total_nodes": 5,
"workflow": "{\"10\":{\"inputs\":{\"image\":\"9b6811d2da10e59ac2b830bf57c5eaf9ca96374e0be00aeafbbbf4cad14e1a8c.jpg\",\"upload\":\"image\"},\"class_type\":\"LoadImage\"},...\"13\":{\"inputs\":{\"images\":[\"12\",0]},\"class_type\":\"PreviewImage\"}}",
"updated_at": "2024-07-08T02:15:02.231Z",
"created_at": "2024-07-08T02:15:02.231Z"
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» id | string | true | none |
| 工作流ID |
»» name | string | true | none |
| 工作流名称 |
»» inputs | [object] | true | none |
| 工作流输入参数定义 |
»»» id | integer | true | none |
| 节点ID |
»»» name | string | true | none |
| 节点参数名称 |
»»» type | string | true | none |
| 节点参数类型 |
»» outputs | [string] | true | none |
| 工作流定义监听输出节点ID |
»» total_nodes | integer | true | none |
| 总节点数 |
»» workflow | string | true | none |
| 工作流定义 |
»» updated_at | string | true | none |
| 更新时间 |
»» created_at | string | true | none |
| 创建时间 |
POST 生成任务
POST /v1/prompts
Body 请求参数
以下是使用创建工作流示例,并将潜空间设置为 1024x1024 的任务
{
"workflow_id": "667d3a99c8e1118ea12be2b9",
"inputs": [
{
"id": "5",
"params": {
"width": 1024,
"height": 1024
}
}
],
"free_cache": false
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
body | body | object | 否 | 请求数据 |
» workflow_id | body | string | 是 | 工作流 ID |
» free_cache | body | boolean | 否 | 清理缓存节点 |
» free_gpu | body | boolean | 否 | 释放显存 |
» backend | body | string | 否 | 指定实例ID |
» inputs | body | [object] | 是 | 工作流参数 |
»» id | body | integer|string | 是 | 节点ID |
»» params | body | object | 是 | 节点需要修改的参数 |
请求示例
const fetch = require('node-fetch');
const params = {
workflow_id: '667d3a99c8e1118ea12be2b9',
inputs: [
{
id: "10",
params: {
image: 'https://pandora-server-cf.onethingai.com/v1/files/inputs/9b/68/9b6811d2da10e59ac2b830bf57c5eaf9ca96374e0be00aeafbbbf4cad14e1a8c.jpg'
}
}
]
}
const run = async function prompts(params){
const url = 'https://pandora-server-cf.onethingai.com/v1/prompts'
const resp = await fetch(url, {
headers: {
"accept": 'application/json',
"content-type": 'application/json',
"Authorization": `Bearer ${process.env.ONETHINGAI_TOKEN}`
},
body: JSON.stringify({ ...params }),
method: "POST"
});
return await resp.json()
}
console.log(run(params))
返回示例
200 Response
{
"code": 0,
"msg": "Success",
"data": {
"taskId": "667d3a99c8e1118ef12be2b9"
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| 接口返回数据 |
»» taskId | String | true | none |
| 任务ID,用于后续查询任务结果 |
POST 创建工作流任务
POST /v1/prompts_workflow
Body 请求参数
说明: 该接口是创建工作流+生成任务的合并接口,在不需要复用工作流的情况下可使用该接口
示例请求数据
{
"name": "test",
"inputs": [
{
"id": "5",
"params": {
"width": 1024,
"height": 1024
}
}
],
"outputs": [
"9"
],
"workflow": {
"3": {
"inputs": {
"seed": 156680208700286,
"steps": 20,
"cfg": 8,
"sampler_name": "euler",
"scheduler": "normal",
"denoise": 1,
"model": [
"4",
0
],
"positive": [
"6",
0
],
"negative": [
"7",
0
],
"latent_image": [
"5",
0
]
},
"class_type": "KSampler"
},
"4": {
"inputs": {
"ckpt_name": "AWPainting_1.4.safetensors"
},
"class_type": "CheckpointLoaderSimple"
},
"5": {
"inputs": {
"width": 512,
"height": 512,
"batch_size": 1
},
"class_type": "EmptyLatentImage"
},
"6": {
"inputs": {
"text": "beautiful scenery nature glass bottle landscape, , purple galaxy bottle,",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode"
},
"7": {
"inputs": {
"text": "text, watermark",
"clip": [
"4",
1
]
},
"class_type": "CLIPTextEncode"
},
"8": {
"inputs": {
"samples": [
"3",
0
],
"vae": [
"4",
2
]
},
"class_type": "VAEDecode"
},
"9": {
"inputs": {
"filename_prefix": "ComfyUI",
"images": [
"8",
0
]
},
"class_type": "SaveImage"
}
}
}
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
body | body | object | 是 | 提交内容 |
» name | body | string | 是 | 工作流名称 |
» inputs | body | [object] | 是 | 工作流输入定义 |
»» id | body | integer|string | 是 | 节点 ID |
»» params | body | object | 是 | 节点需要修改的参数 |
» outputs | body | [string] | 是 | 工作流需要获取输出的节点 |
» backend | body | string | 否 | 指定实例ID |
» free_cache | body | boolean | 否 | 清理缓存节点 |
» free_gpu | body | boolean | 否 | 释放显存 |
» workflow | body | object | 是 | 工作流信息 |
»» ^[0-9]+(\:\d+)?$ | body | 否 | 节点定义 | |
»»» class_type | body | string | 是 | 节点类名称 |
»»» inputs | body | object | 否 | 节点的输入定义 |
枚举值
属性 | 值 | 说明 |
»» type | image | 图片类型 |
»» type | string | 字符串 |
»» type | number | 数字,可以是整数、小数 |
返回示例
200 Response
{
"code": 0,
"msg": "Success",
"data": {
"taskId": "667d3a99c8e1118ef12be2b9"
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| 接口返回数据 |
»» taskId | String | true | none |
| 任务ID,用于后续查询任务结果 |
GET 查看任务的状态
GET /v1/prompts/{id}/status
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
id | path | string | 是 | none |
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": {
"status": "pendding",
"message": "string",
"position": 0,
"images": [
"string"
],
"text": [
"string"
],
"tags": [
"string"
]
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | true | none |
| 接口数据 | |
»» status | string | true | none |
| 状态 |
»» message | string | true | none |
| 信息 |
»» position | integer | false | none |
| 当前位置 |
»» images | [string] | false | none |
| 生成图片地址 |
»» text | [string] | false | none |
| 文本信息 |
»» tags | [string] | false | none |
| 标签信息 |
»» videos | [string] | false | none |
| 生成视频地址 |
»» gifs | [string] | false | none |
| 生成动图地址 |
»» cost_time | integer | false | none |
| 任务执行耗时,单位毫秒 |
枚举值
属性 | 值 |
status | pendding |
status | running |
status | finished |
status | failed |
status | cancel |
错误信息
添加节点错误信息:Node xxx#123 节点执行错误信息
GET 查看历史任务列表
GET /v1/prompts
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
page | query | integer | 否 | 分页页码 |
page_size | query | integer | 否 | 分页大小 |
workflowId | query | string | 否 | 查询某个工作流的 ID |
status | query | string | 否 | 过滤某个状态 |
返回示例
200 Response
{
"code": 0,
"msg": "success",
"data": {
"list": [
{
"task_id": "676526a12a9f535e8d324b26",
"state": "finished",
"backend": "test",
"workflow_id": "676404f6ad6f29dad4eb5aa6",
"prompt_id": "b8f1a085-1db1-4551-91de-8b5cab516587",
"dispatched_at": "2024-12-20 08:12:37",
"created_at": "2024-12-20 08:11:13"
}
...
],
"pagination": {
"total": 20,
"page": 1,
"page_size": 10
}
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | ListData | true | none |
| 接口数据 |
»» list | [Object] | true | none |
| 任务列表信息 |
»»» task_id | string | true | none |
| 任务 ID |
»»» state | string | true | none |
| 任务状态 |
»»» backend | string | true | none |
| 执行后端 |
»»» workflow_id | string | true | none |
| 工作流 ID |
»»» prompt_id | string | true | none |
| ComfyUI的执行 ID |
»»» dispatched_at | string | true | none |
| 分配时间 |
»»» created_at | string | true | none |
| 创建时间 |
»» pagination | Pagination | true | none |
| 分页信息 |
»»» page | integer | true | none |
| 当前分页页码 |
»»» page_size | integer | true | none |
| 分页大小 |
»»» total | integer | true | none |
| 总数 |
枚举值
属性 | 值 |
status | pendding |
status | running |
status | finished |
status | failed |
status | cancel |
POST 取消生成
POST /v1/prompts/{id}/cancel
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
id | path | string | 是 | 任务 ID |
返回示例
200 Response
{
"code": 0,
"msg": "string"
}
返回结果
POST 上传图片
POST /v1/files
Body 请求参数
file: string
请求参数
名称 | 位置 | 类型 | 必选 | 说明 |
body | body | object | 否 | none |
» file | body | string(binary) | 否 | none |
返回示例
200 Response
{
"code": 0,
"msg": "string",
"data": {
"path": "string"
}
}
返回结果
状态码 | 状态码含义 | 说明 | 数据模型 |
200 | 成功 | Inline |
返回数据结构
状态码 200
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
---|---|---|---|---|---|
» code | integer | true | none |
| 状态码 |
» msg | string | true | none |
| 错误信息 |
» data | object | true | none |
| none |
»» path | string | true | none |
| 图片下载地址 |
任务通知接口
GET /v1/ws
该接口为 websocket 协议,支持长链接通知,每个用户最多只有 15 个连接
注:由于接口是在有任务信息时才会发送消息,空闲情况下会无信息发送,这样会导致部分 websocket 的库认为读消息超时了,这里建议使用websocket 的原生 ping pong 来保活,可以避免被库给关闭了
ping pong的示例代码
ctx, cancel := context.WithCancel(context.Background())
maxLastPongMessage := int32(0)
ws.SetPongHandler(func(_ string) {
atomic.AddInt32(&maxLastPongMessage, -1)
})
// 定时发 ping 消息
go func() {
defaultInterval := 5 * time.Second
ticker := time.NewTimer(defaultInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
err := ws.WriteControl(websocket.PingMessage, nil, time.Now().Add(time.Second))
if err != nil {
klog.V(3).InfoS("websocket send ping message has failure", "error", err, "clientIp", clientAddr, "uid", uid)
cancel()
return
}
// 超过 3 次没有响应 pong 消息了
if atomic.AddInt32(&maxLastPongMessage, 1) > 3 {
cancel()
return
}
ticker.Reset(defaultInterval)
case <-ctx.Done():
return
}
}
}()
调用示例
const ws = new WebSocket('wss://pandora-server-cf.onethingai.com/v1/ws', {
headers: {
'Authorization': `Bearer ${process.env.ONETHINGAI_TOKEN}`
}
});
// 接收消息的回调
ws.onmessage = (event) => {
console.log(data);
const data = JSON.parse(event.data);
if (data.type == 'pendding') {
// TODO: 需要处理任务等待执行
console.log(`任务 ${data.task_id} 等待执行, 当前位置: ${data.data.current}`);
}
if (data.type == 'progress') {
// TODO: 需要处理任务正在执行
console.log(`任务 ${data.task_id} 正在执行, 进度: ${data.data.process}%`);
}
if (data.type == 'finished') {
// TODO: 需要处理任务已完成
if (data.data.success) {
// TODO: 任务处理全部完成,可以通过认为状态接口获取输出内容
}
}
if (data.type == 'error') {
// TODO: 需要处理任务执行出错
console.error('任务执行出错:', data.data.message);
}
}
// 连接建立时的回调
ws.onopen = () => {
console.log('WebSocket 连接已建立');
}
// 连接关闭时的回调
ws.onclose = () => {
console.log('连接已关闭');
}
// 发生错误时的回调
ws.onerror = (error) => {
console.error('WebSocket 错误:', error);
}
消息通知数据结构
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
» type | string | true | none | 任务状态 pendding:等待执行 progress:执行中 finished:执行完成 error: 执行失败 | |
» taskId | string | true | none | 任务 ID | |
» data | object | true | none | 内容 | |
»» message | string | true | none | 消息 | |
»» current | integer | true | none | 任务当前所在队列位置 | |
»» success | boolean | true | none | 执行是否成功 | |
»» process | integer | true | none | 工作流执行进度,取值为:0-100 |
返回消息示例
{ "type": "pendding","taskId": "667d3a99c8e1118ef12be2b9", "data": {"message": "等待中...", "current": 1}}
{ "type": "progress","taskId": "667d3a99c8e1118ef12be2b9", "data": {"message": "执行中...", "process": 0}}
....
{ "type": "progress","taskId": "667d3a99c8e1118ef12be2b9", "data": {"message": "执行中...", "process": 30}}
....
{ "type": "finished","taskId": "667d3a99c8e1118ef12be2b9", "data": {"message": "完成", "success": true}}
数据模型
Workflow
{
"class_type": "string",
"inputs": {}
}
属性
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
class_type | string | true | none | none | |
inputs | object | true | none | none |
TaskStatus
{
"status": "pendding",
"message": "string",
"position": 0,
"images": [
"string"
],
"text": [
"string"
],
"tags": [
"string"
]
}
属性
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
status | string | true | none | 状态 | |
message | string | true | none | 信息 | |
position | integer | false | none | 当前位置 | |
images | [string] | false | none | 生成图片地址 | |
text | [string] | false | none | 文本信息 | |
tags | [string] | false | none | 标签信息 |
枚举值
属性 | 值 |
status | pendding |
status | running |
status | finished |
status | failed |
status | cancel |
Response
{
"code": 0,
"msg": "string"
}
属性
名称 | 类型 | 必选 | 约束 | 中文名 | 说明 |
code | integer | true | none | 状态码 | |
msg | string | true | none | 错误信息 |