{
  "openapi": "3.1.0",
  "info": {
    "title": "文识云 — AIGC 检测 API",
    "version": "1.0.0",
    "summary": "AI 文本检测与 AI 图片检测的异步任务接口",
    "description": "文识云是一个 AIGC 检测 API 服务：底层接入腾讯朱雀检测模型，对外提供 AI 文本检测与 AI 图片检测两类接口。\n本站是独立的第三方接口服务，不是上游官方产品，也不代表官方。\n\n调用模型是异步任务：提交接口立即返回 task_id，之后轮询 GET /v1/tasks/{task_id} 取结果。\n提交即扣费，因此提交类接口强制要求 Idempotency-Key。",
    "contact": {
      "name": "技术支持",
      "url": "https://sbnew.top/contact"
    },
    "license": {
      "name": "见用户协议",
      "url": "https://sbnew.top/terms"
    }
  },
  "servers": [
    {
      "url": "https://sbnew.top",
      "description": "生产环境"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "检测",
      "description": "提交文本或图片检测任务"
    },
    {
      "name": "任务",
      "description": "查询任务状态与结果"
    },
    {
      "name": "账户",
      "description": "调用记录与计价规则"
    }
  ],
  "paths": {
    "/v1/text/classify": {
      "post": {
        "tags": [
          "检测"
        ],
        "summary": "提交文本检测任务，立即返回 task_id（异步，不返回结果）",
        "description": "- text 必填，上限 20000 个字符（按 Unicode 字符计，不是字节）。超限直接返回 400，不会进入检测流程。\n- is_merge 控制分段粒度：false 时每个段落独立出置信度，结果在 result.segment_labels；省略或 true 时合并为整体判定，返回体积更小。需要逐段定位 AI 生成片段时用 false，只要整体结论时用 true。\n- 改这个参数等于换了一次提交，重试时应换用新的 Idempotency-Key：幂等是按「账号 + 键」去重的，不校验请求内容，复用旧键会直接返回上一次的任务。",
        "operationId": "classifyText",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TextClassifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "任务已受理，返回 task_id。此时还没有检测结果。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Task"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "参数不合法、请求体不是 JSON，或提交类接口缺少 Idempotency-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "API Key 缺失、格式错误或已禁用",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "余额不足",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "账号已停用，或该检测类型未开放",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "请求体超过上限（默认 16MB）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "超出每秒请求上限或每日提交配额；Retry-After 给出建议等待秒数",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务内部错误",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "处理超时",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/image/classify": {
      "post": {
        "tags": [
          "检测"
        ],
        "summary": "提交图片检测任务，立即返回 task_id（异步，不返回结果）",
        "description": "- image_url 与 image_base64 二选一：前者是公网可访问的 http/https 地址，后者是图片内容的 Base64 编码。\n- 两个字段都同时接受 camelCase 写法（imageUrl / imageBase64），从上游文档直接迁移过来的代码不必改写字段名。\n- 支持 jpg / png / webp；图片需大于 300×300 像素，单张解码后不超过 10MB，请求体整体不超过 16MB。",
        "operationId": "classifyImage",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImageClassifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "任务已受理，返回 task_id。此时还没有检测结果。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Task"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "参数不合法、请求体不是 JSON，或提交类接口缺少 Idempotency-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "API Key 缺失、格式错误或已禁用",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "余额不足",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "账号已停用，或该检测类型未开放",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "请求体超过上限（默认 16MB）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "超出每秒请求上限或每日提交配额；Retry-After 给出建议等待秒数",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务内部错误",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "处理超时",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tasks/{task_id}": {
      "get": {
        "tags": [
          "任务"
        ],
        "summary": "查询任务状态与结果，取结果的唯一方式",
        "description": "- status 取值为 pending / running / succeeded / failed；前两者是中间态，需要继续轮询，后两者是终态。\n- 只能查询本账号提交的任务，别人的 task_id 一律 404。\n- 轮询间隔建议不小于 1 秒：查询接口有独立的每秒上限，但密集轮询换不来更快的结果——推理耗时由上游决定。",
        "operationId": "getTask",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "提交接口返回的任务 ID。只能查询本账号的任务，别人的一律 404。"
          }
        ],
        "responses": {
          "200": {
            "description": "任务状态。status 为 succeeded 时 result 有内容；failed 时看 error_code。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/Task"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "参数不合法、请求体不是 JSON，或提交类接口缺少 Idempotency-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "API Key 缺失、格式错误或已禁用",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "余额不足",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "账号已停用，或该检测类型未开放",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "任务不存在，或不属于当前账号",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "请求体超过上限（默认 16MB）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "超出每秒请求上限或每日提交配额；Retry-After 给出建议等待秒数",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务内部错误",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "处理超时",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "tags": [
          "账户"
        ],
        "summary": "分页查询本账号的调用记录（与 /v1/tasks/{id} 返回同一形状）",
        "description": "- 查询参数：limit 默认 20、最大 100；offset 最大 100000。\n- 响应为 { list, total, limit, offset }：list 无记录时是 []，total 用于判断是否还有下一页。\n- 列表项与单条查询的字段完全一致，前端可以复用同一套渲染。",
        "operationId": "listUsage",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            },
            "description": "每页条数，默认 20，最大 100。"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0,
              "maximum": 100000
            },
            "description": "偏移量。配合 total 判断是否还有下一页。"
          }
        ],
        "responses": {
          "200": {
            "description": "分页结果。list 无记录时是 []，不是 null。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/UsagePage"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "参数不合法、请求体不是 JSON，或提交类接口缺少 Idempotency-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "API Key 缺失、格式错误或已禁用",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "余额不足",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "账号已停用，或该检测类型未开放",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "请求体超过上限（默认 16MB）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "超出每秒请求上限或每日提交配额；Retry-After 给出建议等待秒数",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务内部错误",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "处理超时",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pricing": {
      "get": {
        "tags": [
          "账户"
        ],
        "summary": "查询当前生效的计价规则",
        "description": "- 该接口同样在 /v1 分组内，需要携带 API Key（本站没有匿名可读的对外接口）。\n- 返回的是实时规则：运营在管理后台改价后，这里立即反映，不必等发版。",
        "operationId": "listPricing",
        "responses": {
          "200": {
            "description": "当前生效的计价规则。运营改价后立即反映，不必等发版。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "rules"
                      ],
                      "properties": {
                        "rules": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PricingRule"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "参数不合法、请求体不是 JSON，或提交类接口缺少 Idempotency-Key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "API Key 缺失、格式错误或已禁用",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "余额不足",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "账号已停用，或该检测类型未开放",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "请求体超过上限（默认 16MB）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "超出每秒请求上限或每日提交配额；Retry-After 给出建议等待秒数",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务内部错误",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "处理超时",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "用户中心创建的 API Key，形如 sk-zq-…。每个请求都要带 Authorization: Bearer <API_KEY>。"
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "maxLength": 64
        },
        "description": "提交类接口必填。同一个键重复提交只执行一次、只扣一次费；网络超时后的重试必须复用原键，换了参数要换新键。"
      }
    },
    "responses": {
      "Error": {
        "description": "统一错误响应",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "错误码。取值见 /docs 的错误码表；不建议在代码里穷举匹配，认不出的码按失败处理即可。",
            "examples": [
              "invalid_param",
              "invalid_api_key",
              "insufficient_balance",
              "rate_limited",
              "quota_exceeded"
            ]
          },
          "message": {
            "type": "string",
            "description": "可直接展示给开发者的说明。"
          }
        }
      },
      "TextClassifyRequest": {
        "type": "object",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 20000,
            "description": "待检测文本，上限 20000 个 Unicode 字符（不是字节）。超限直接返回 400，不会进入检测流程。"
          },
          "is_merge": {
            "type": "boolean",
            "description": "分段粒度。false 时每个段落独立出置信度，结果在 result.segment_labels；省略或 true 时合并为整体判定。语义容易搞反：false 才是分段。"
          }
        }
      },
      "ImageClassifyRequest": {
        "type": "object",
        "description": "image_url 与 image_base64 二选一；同时接受 camelCase 写法（imageUrl / imageBase64）。",
        "properties": {
          "image_url": {
            "type": "string",
            "format": "uri",
            "description": "公网可访问的 http/https 图片地址。"
          },
          "image_base64": {
            "type": "string",
            "description": "图片内容的 Base64 编码。"
          },
          "imageUrl": {
            "type": "string",
            "format": "uri",
            "description": "image_url 的 camelCase 别名。"
          },
          "imageBase64": {
            "type": "string",
            "description": "image_base64 的 camelCase 别名。"
          }
        }
      },
      "Task": {
        "type": "object",
        "required": [
          "task_id",
          "status",
          "created_at"
        ],
        "properties": {
          "task_id": {
            "type": "string",
            "description": "任务 ID，用于轮询。"
          },
          "provider": {
            "type": "string",
            "description": "检测类型标识（文本或图片）。"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "succeeded",
              "failed"
            ],
            "description": "pending / running 是中间态，继续轮询；succeeded / failed 是终态。"
          },
          "cost": {
            "description": "本次调用的扣费金额（元）。",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ]
          },
          "result": {
            "description": "检测结果。succeeded 时是文本结果或图片结果之一（互斥）；其余状态为 null。",
            "oneOf": [
              {
                "$ref": "#/components/schemas/TextResult"
              },
              {
                "$ref": "#/components/schemas/ImageResult"
              },
              {
                "type": "null"
              }
            ]
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "任务终态为 failed 时的错误码，属于执行阶段失败，与 HTTP 错误码是两回事。"
          },
          "error_msg": {
            "type": [
              "string",
              "null"
            ],
            "description": "失败说明。"
          },
          "latency_ms": {
            "type": [
              "integer",
              "null"
            ],
            "description": "任务耗时（毫秒）。"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "提交时间。"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "终态时间。"
          }
        }
      },
      "TextResult": {
        "type": "object",
        "description": "文本检测结果。只有文本任务会返回。",
        "properties": {
          "status": {
            "type": "string",
            "description": "上游返回的状态字段，原样透传。"
          },
          "softmax_confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "模型对整篇文本的分类置信度。判断整体倾向看这个值。"
          },
          "ratio_confidence": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "与分段标签占比相关的另一个置信度口径。与 softmax_confidence 明显不一致时，通常说明文本里人工与 AI 内容混杂。"
          },
          "labels_ratio": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "各标签占比，全部相加为 1。键是字符串：0=人工、1=AI、2=疑似 AI；实际出现哪几个键取决于这次检测，不要假设固定。"
          },
          "segment_labels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SegmentLabel"
            },
            "description": "逐段结果，仅在 is_merge=false 时有意义。"
          }
        }
      },
      "SegmentLabel": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "该段原文。"
          },
          "label": {
            "type": "integer",
            "enum": [
              0,
              1,
              2
            ],
            "description": "0=人工，1=AI，2=疑似 AI。"
          },
          "conf": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "该段置信度。"
          },
          "order": {
            "type": "integer",
            "description": "段落在全文中的顺序。"
          },
          "position": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "minItems": 2,
            "maxItems": 2,
            "description": "[起始位置, 段长]，按 Unicode 字符计。第二项是长度，不是结束下标：段落覆盖 [position[0], position[0]+position[1])。"
          }
        }
      },
      "ImageResult": {
        "type": "object",
        "description": "图片检测结果。只有图片任务会返回。",
        "properties": {
          "status": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "required": [
              "confidence"
            ],
            "properties": {
              "confidence": {
                "type": "number",
                "minimum": 0,
                "maximum": 1,
                "description": "AI 生成置信度，越接近 1 越倾向于判定为 AI 生成。"
              }
            }
          }
        }
      },
      "UsagePage": {
        "type": "object",
        "required": [
          "list",
          "total",
          "limit",
          "offset"
        ],
        "properties": {
          "list": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            },
            "description": "调用记录，无记录时是 []。"
          },
          "total": {
            "type": "integer",
            "description": "总条数，用于判断是否还有下一页。"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        }
      },
      "PricingRule": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "description": "检测类型标识。"
          },
          "charge_mode": {
            "type": "string",
            "description": "计费方式：按量或按次。"
          },
          "unit_size": {
            "type": "integer",
            "description": "计价单位大小（按量计费时是字数）。"
          },
          "unit_price": {
            "description": "单价（元）。",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ]
          },
          "min_charge": {
            "description": "每次调用的最低收费（元）。",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ]
          },
          "enabled": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "description": "1 表示该规则当前生效。"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}