开放接口文档

面向桌面客户端、VR 实训程序和平台启动的 Web 实验。

V2 · 平台账号登录
BASE URLhttps://edu.hiholo.com/open/api/v2
01

快速接入

先完成登录和令牌交换,再回传实验结果。学习时长与试卷接口按实验需要接入。

当前登录方式:平台账号密码。客户端与网站使用同一套平台账号。
  1. 01客户端登录账号密码 → project
  2. 02获取令牌project + 项目签名 → access_token
  3. 03回传实验结果成绩、步骤、用时 → 结果记录
  4. 04上传报告附件使用同一 originId,按需调用

接入前准备

名称作用来源
username / password平台用户的登录账号和密码与网站登录账号一致;用户账号必须可正常使用。
appid标识一个实验项目由管理员在实验项目中配置,接入方从项目管理页获取。
secret计算项目签名与 appid 配套。请保存在接入方的受控配置中。
project用户登录凭证客户端登录接口返回;平台启动 Web 实验时也会在启动地址中携带。
access_token后续接口调用凭证使用 project 和项目签名换取。

appid / secret 配置完成后再联调。本文中的 APP_ID、APP_SECRET、PROJECT、ACCESS_TOKEN 等均为占位符。

从网站开始实验:启动地址已经携带 project 时,直接进入“获取令牌”步骤,随后执行相同的数据回传流程。

接口一览

用途方法路径
客户端登录POST/client/login
获取令牌POST/token
实验结果回传POST/data_upload
报告附件上传POST/attachment_upload
学习时长回传POST/duration_upload
获取试卷GET/paper/list

上表路径均以 https://edu.hiholo.com/open/api/v2 为前缀。客户端接入按本文展示的方法调用。

02

客户端登录

在客户端输入平台账号密码,登录成功后取得 project。账号密码通过 HTTPS 的 POST 表单提交。

POST/client/login

请求格式:application/x-www-form-urlencoded

字段位置 / 类型要求说明
usernameBody / String必填平台用户名、邮箱或已绑定手机号。
passwordBody / String必填对应账号的登录密码。
appidBody / String必填本次接入的实验项目编号。
cURL 示例
cURL
curl --request POST "https://edu.hiholo.com/open/api/v2/client/login"   --data-urlencode "username=YOUR_USERNAME"   --data-urlencode "password=YOUR_PASSWORD"   --data-urlencode "appid=APP_ID"
成功响应 JSON 示例
成功响应 JSON
{
  "code": 0,
  "msg": "",
  "project": "PROJECT_FROM_LOGIN",
  "un": "example_user",
  "dis": "示例用户"
}

保留返回的 project,下一步换取 access_token。un 是回传结果时使用的平台用户名;即使用邮箱或手机号登录,也应使用返回的 un 填写成绩中的 username。

查看本接口错误码
code含义
1缺少 username、password 或 appid。
2appid 无效,或项目尚未配置 secret。
8找不到该平台用户。
16用户已锁定。
17账号或密码错误。
03

获取调用令牌

project 用于换取 access_token。后续回传、上传和试卷接口使用 access_token。

POST/token

请求格式:application/x-www-form-urlencoded

字段位置 / 类型要求说明
projectBody / String必填登录返回或平台启动地址携带的原始 project。
appidBody / String必填实验项目编号。
signatureBody / String必填按下方规则计算的 32 位小写 MD5 字符串。

签名规则

signature = MD5(project + appid + secret)

将三个原始字符串直接拼接,按 UTF-8 编码计算 MD5,输出小写十六进制。计算签名时使用 URL 编码前的 project。

Python 签名 示例
Python 签名
signature = hashlib.md5((project + appid + secret).encode("utf-8")).hexdigest()
cURL 示例
cURL
curl --request POST "https://edu.hiholo.com/open/api/v2/token"   --data-urlencode "project=PROJECT_FROM_LOGIN"   --data-urlencode "appid=APP_ID"   --data-urlencode "signature=CALCULATED_SIGNATURE"
成功响应 JSON 示例
成功响应 JSON
{
  "code": 0,
  "msg": "",
  "access_token": "ACCESS_TOKEN_FROM_RESPONSE",
  "created_time": 1700000000,
  "expired_time": 1700086400,
  "created_at": "2023-11-15 06:13:20",
  "expired_at": "2023-11-16 06:13:20",
  "un": "example_user",
  "dis": "示例用户"
}

有效期与重新登录

project 和 access_token 当前有效期均为 24 小时。以响应中的 expired_time 判断令牌到期时间;到期后重新执行“客户端登录 → 获取令牌”。重新取得的令牌用于后续请求。

created_time / expired_time 是秒级 Unix 时间戳,created_at / expired_at 是可读时间字符串。服务端返回字段名使用 created / expired。

查看本接口错误码
code含义
1缺少 project、appid 或 signature。
2appid 无效,或项目未配置 secret。
3signature 验证失败,请核对 appid、secret、拼接顺序与原始 project。
4project 签名错误。
5project 已过期,请重新登录。
6其他令牌解析错误,查看 msg。
04

回传实验结果

实验结束后提交成绩、总用时和步骤记录。返回 code=0 后,本次实验结果才算回传成功。

POST/data_upload?access_token=ACCESS_TOKEN

请求格式:application/json

调用顺序:先让实验结果回传成功,再上传报告附件。access_token 放在 URL 查询参数中,结果数据放在 JSON Body。
字段位置 / 类型要求说明
access_tokenQuery / String必填获取令牌接口返回的 access_token。
usernameJSON / String必填使用登录响应中的 un,须与令牌用户一致。
titleJSON / String必填实验名称。
statusJSON / Integer必填1:完成;2:未完成。
scoreJSON / Number必填百分制,范围 0–100。
startTime / endTimeJSON / Integer必填13 位毫秒 Unix 时间戳。
timeUsedJSON / Integer必填本次实验总用时,单位:秒。
appidJSON / String必填须与 access_token 所属项目一致。
originIdJSON / String必填客户端为本次实验生成的唯一记录标识;在同一 appid 下不可重复。
stepsJSON / Array必填步骤数组,最多 200 项;没有步骤时传空数组 []。
请求 JSON · 保存为 result.json 示例
请求 JSON · 保存为 result.json
{
  "username": "example_user",
  "title": "示例实验",
  "status": 1,
  "score": 95,
  "startTime": 1700000000000,
  "endTime": 1700000600000,
  "timeUsed": 600,
  "appid": "APP_ID",
  "originId": "CLIENT_RECORD_UNIQUE_ID",
  "steps": [
    {
      "seq": 1,
      "title": "完成实验操作",
      "startTime": 1700000000000,
      "endTime": 1700000600000,
      "timeUsed": 600,
      "expectTime": 600,
      "maxScore": 100,
      "score": 95,
      "repeatCount": 1,
      "evaluation": "操作完成",
      "scoringModel": "按实验规则评分",
      "remarks": ""
    }
  ]
}
cURL 示例
cURL
curl --request POST "https://edu.hiholo.com/open/api/v2/data_upload?access_token=ACCESS_TOKEN"   --header "Content-Type: application/json"   --data-binary @result.json
成功响应 JSON 示例
成功响应 JSON
{
  "code": 0,
  "id": 123
}

steps 中的字段

每个步骤按下表提供完整字段。当前接口校验要求包含 remarks 键,没有备注时传空字符串。

字段类型说明
seqInteger步骤序号。
titleString步骤名称。
startTime / endTimeInteger13 位毫秒时间戳。
timeUsed / expectTimeInteger实际用时 / 参考用时,单位均为秒。
maxScore / scoreNumber步骤满分 / 实际得分。
repeatCountInteger操作次数。
evaluationString步骤评价。
scoringModelString赋分规则说明。
remarksString备注,允许空字符串。

originId 由客户端生成;响应中的 id 是服务端记录编号。后续上传报告仍使用原来的 originId。

查看本接口错误码
code含义
1缺少 access_token。
2令牌签名错误。
3令牌已过期。
4其他令牌解析错误。
5JSON 格式、主字段或步骤字段不完整。
6无效的 appid。
7同一 appid 下 originId 已存在。
8未知的平台用户。
9status 只能是 1 或 2。
10score 超出 0–100。
11startTime 不是 13 位时间戳。
12endTime 不是 13 位时间戳。
13步骤超过 200 项。
14用户与令牌不一致,或结果保存失败;结合 msg 判断。
15appid 与令牌所属项目不一致。
05

上传报告附件

为已经保存的实验结果附上报告。由表单上传文件,和 JSON 成绩请求分开调用。

POST/attachment_upload

请求格式:multipart/form-data

前置条件:对应的 appid + originId 已通过“回传实验结果”保存成功。上传报告时沿用这两个值。
字段位置 / 类型要求说明
access_tokenForm / String必填当前用户、当前项目的有效令牌。
appidForm / String必填与令牌和结果记录一致。
originIdForm / String必填已保存的实验结果标识。
filenameForm / String必填带扩展名的文件名,例如 report.pdf。
titleForm / String必填报告标题;同一项目和 originId 下不能重复上传同名报告。
remarksForm / String必填当前接口要求非空;没有备注可填“无”。
attachmentForm / File必填文件字段名固定为 attachment。

支持 doc / docx / xls / xlsx / pdf,文件大小不超过 5 MiB;上传时提供与文件类型对应的 MIME 类型。

cURL 示例
cURL
curl --request POST "https://edu.hiholo.com/open/api/v2/attachment_upload"   --form "access_token=ACCESS_TOKEN"   --form "appid=APP_ID"   --form "originId=CLIENT_RECORD_UNIQUE_ID"   --form "filename=report.pdf"   --form "title=实验报告"   --form "remarks=无"   --form "attachment=@report.pdf;type=application/pdf"
成功响应 JSON 示例
成功响应 JSON
{
  "code": 0,
  "id": 456
}
查看本接口错误码
code含义
1缺少 access_token。
2令牌签名错误。
3令牌过期。
4令牌解析错误。
5缺少必填表单参数。
6无效的 appid。
7appid 与令牌不一致。
8对应结果记录不存在,或缺少 attachment 文件;查看 msg / data。
9重复上传同名实验报告。
10目标文件已经存在。
11文件类型或大小不符合要求。
06

回传学习时长

用于累计练习、操作等学习时长,可在实验过程中按需调用。

POST/duration_upload

请求格式:application/x-www-form-urlencoded

字段位置 / 类型要求说明
access_tokenBody / String必填服务端从令牌识别用户和 appid。
exp_timeBody / Integer必填本次新增的正整数时长,单位:秒。
cURL 示例
cURL
curl --request POST "https://edu.hiholo.com/open/api/v2/duration_upload"   --data-urlencode "access_token=ACCESS_TOKEN"   --data-urlencode "exp_time=60"
成功响应 JSON 示例
成功响应 JSON
{
  "code": 0
}

平台按用户和项目累加 exp_time。每次发送本次新增量,例如刚完成的 60 秒。重复提交同一时间段会再次累加,客户端应记录已确认上报的区间。

查看本接口错误码
code含义
1缺少 exp_time 或 access_token。
2令牌签名错误。
3令牌过期。
4令牌解析错误。
6无效的 appid。
8未知的平台用户。
14保存时长失败,查看 msg。
07

获取项目试卷

获取当前项目配置的课程试卷及题目,用于实验中的测验环节。

GET/paper/list?access_token=ACCESS_TOKEN

请求格式:Query 参数

字段位置 / 类型要求说明
access_tokenQuery / String必填用于识别实验项目。
appidQuery / String可选传入时必须与令牌中的 appid 一致。
cURL 示例
cURL
curl "https://edu.hiholo.com/open/api/v2/paper/list?access_token=ACCESS_TOKEN"
成功响应 JSON 示例
成功响应 JSON
{
  "code": 0,
  "msg": "success",
  "data": [
    {
      "title": "示例试卷",
      "questions": [
        {
          "ID": "123",
          "TypeName": "单选题",
          "Subject": "示例题干",
          "Options": [
            "选项 A",
            "选项 B"
          ],
          "Answers": [
            0
          ],
          "UserAnswers": [],
          "Score": 5
        }
      ]
    }
  ]
}

data 为试卷数组;没有试卷时返回空数组。Answers 使用 Options 中从 0 开始的下标。字段名区分大小写。

查看本接口错误码
code含义
1缺少或无效的 access_token。
2令牌签名错误。
3令牌过期。
4令牌解析错误。
5请求 appid 与令牌不匹配。
6对应的实验项目不存在。
08

错误排查与约定

先确认请求地址、数据格式和 code,再按接口对应的错误说明处理。

先判断业务结果

HTTP 200 表示请求已到达接口;业务是否成功以 code 为准。0 为成功,其他值按该接口的错误码处理。兼容数字或数字字符串形式的 code;错误说明可能位于 msg 或 data。

各接口的错误码独立定义。例如 code=8 在登录接口表示未知用户,在附件接口可能表示尚无结果记录或未附文件。请结合接口路径与返回说明排查。

时间与字段约定

内容统一约定
startTime / endTime13 位毫秒 Unix 时间戳,包含结果和步骤字段。
timeUsed / expectTime / exp_time单位均为秒。
created_time / expired_time10 位秒级 Unix 时间戳,用于令牌创建和到期时间。
username使用登录或令牌响应中的 un。
originId客户端生成;在同一 appid 下唯一,成绩与附件始终复用同一个值。

常见问题

客户端登录成功后,为什么还不能回传?

登录返回的是 project。先调用获取令牌接口,得到 access_token 后再回传。

signature 验证失败,先检查什么?

确认 appid 与 secret 属于同一实验项目;按 project、appid、secret 的顺序直接拼接,使用原始字符串计算小写 MD5。

报告上传返回“originId 数据不存在”怎么办?

先确认结果回传返回 code=0,再用同一 appid 和 originId 上传附件。服务端返回的结果 id 不用于替代 originId。

网络超时后怎样处理重复结果?

保留本次实验的 originId。重复回传会返回 code=7,表示该项目下已存在相同标识;先确认已有记录,避免将同一实验作为新记录重复上报。

令牌到期后怎么办?

重新执行客户端登录与令牌交换,使用新的 access_token 发送后续请求。

客户端账号能直接用于网站登录吗?

两者使用同一套平台账号。项目 appid / secret 用于实验接入,用户 username / password 用于用户登录。

更新于 2026-11-05 · 示例均使用占位值,请替换为当前项目和用户的数据。