提交接口
完整的「上传 → 冻结报价 → 幂等提交 → 读取报告」流程。所有接口均需 Authorization: Bearer <api_key>,并且 Key 必须是属于客户账户的 Managed API Key。
1. 上传文档
POST /v1/uploads
Content-Type: multipart/form-data
| 字段 | 类型 | 必须 | 说明 |
|---|---|---|---|
| file | File | ✓ | PDF / DOCX / TXT,最大 50 MB |
{
"upload_id": "upl_xxxxxxxx",
"filename": "paper.pdf",
"size": 214528,
"word_count": 2847,
"mime_type": "application/pdf",
"status": "pending"
}
2. 创建冻结报价
POST /v1/submissions/quote
Content-Type: application/json
{
"upload_id": "upl_xxxxxxxx",
"report_types": ["similarity", "ai"]
}
返回的 quote.quote_id 是提交所需的冻结报价标识。它绑定上传、报告类型、路由计划和额度成本;不要把一份报价用于其他上传或报告组合。
3. 创建提交
POST /v1/submissions
Content-Type: application/json
Idempotency-Key: <8-128 character key>
{
"upload_id": "upl_xxxxxxxx",
"report_types": ["similarity", "ai"],
"quote_id": "qte_xxxxxxxx"
}
| 字段 | 类型 | 说明 |
|---|---|---|
| upload_id | string | 上传接口返回的 upload id |
| report_types | string[] | similarity / ai 任选一个或两个,不能重复 |
| quote_id | string | 上一步报价返回的冻结报价 id |
Idempotency-Key 是必填 HTTP 头。网络重试时使用相同的 Key 和完全相同的请求体;相同 Key 配合不同请求会得到 idempotency_key_conflict,而不是第二次上游提交。
{
"submission": {
"id": "sub_xxxxxxxx",
"status": "queued",
"report_types": ["similarity", "ai"],
"credits_cost": 2,
"credits_refunded": 0,
"report_exists": { "similarity": false, "ai": false }
},
"links": {
"submission_url": "/v1/submissions/sub_xxxxxxxx",
"events_url": "/v1/submissions/sub_xxxxxxxx/events",
"job_url": null
}
}
| 状态 | 错误码 | 说明 |
|---|---|---|
| 402 | insufficient_credits | 额度不足 |
| 400 | invalid_input | 参数校验失败 |
| 404 | upload_not_found | upload_id 不存在或不属于当前用户 |
| 409 | idempotency_key_conflict | 相同幂等键搭配了不同请求 |
| 409 | upload_not_pending | 上传已不再可用于新提交 |
4. 查询状态
GET /v1/submissions/:id
queued:排队中running:正在执行或获取报告partial_completed:已有部分请求报告可用completed:所有请求报告都可用failed:失败;failure_code解释原因,平台侧终态失败按原额度分配退款
查询响应中的 report_exists 和可选 scores 适合列表或轮询展示;完整结构化内容在单独的报告元数据接口中返回。
5. 报告元数据和文件下载
GET /v1/submissions/:id/report?type=similarity
GET /v1/submissions/:id/report?type=ai
这些接口返回 JSON 元数据,包括 structured_payload、provider_leg 和 generated_at。二进制报告文件由另一个端点提供:
GET /v1/submissions/:id/report/file?type=similarity
GET /v1/submissions/:id/report/file?type=ai
下载端点以 Content-Type 和 Content-Disposition 指明文件类型与文件名。报告还未准备好时,两个端点均返回 report_not_ready。
6. 查询分派 Job
GET /v1/submissions/:id/job
创建响应中的 job_url 在尚未分派时为 null。获取该链接会返回安全的 job id、状态和可选失败信息;请勿用旧 /v1/jobs 入口创建 Managed API Key 提交。当前 Managed API Key 表面没有 submissions 列表端点,因此不要假设 offset 或 cursor 列表契约。
实时事件(SSE)
curl -N https://turnitinai.vip/v1/submissions/sub_xxxxxxxx/events \
-H "Authorization: Bearer $TURNITIN_API_KEY"
submission_status:{ "status": "queued|running|partial_completed|completed|failed", "failure_code": null }job_event:{ "event": "job.*", "occurred_at": "...", "data": { ... } }
SSE 是进度提示;客户端重连后应再次读取 GET /v1/submissions/:id,以该状态和 report_exists 作为最终事实。