Skip to content

Doc2X API v2 PDF 接口文档

基础信息

Base URL:https://v2.doc2x.noedgeai.com。本页介绍开放平台 PDF 解析:创建预上传任务、上传原文件、等待解析、请求导出、下载并保存结果。网页工作台、CLI 和 API 的账户与格式范围不同。

旧 POST /api/v2/parse/pdf 不建议新系统接入;请使用下方预上传流程。v3-2026 是解析模型选择,不是把 URL 改成 /api/v3。

PDF API:预上传、上传、解析状态、导出状态与本地保存

放大查看流程图

输入与额度

  • 预上传接口公开文件口径为不超过 1 GiB(1,073,741,824 bytes) 的 PDF;旧直接上传入口的 300 MiB 限制不可套用于这个入口。账号、部署配置或文件条件仍可能进一步限制接收。
  • 单任务页数、同时处理任务数、处理中的页数和剩余额度分别判断,以开放平台账户条件及状态响应为准;不要把历史文档的 2000 页写成所有账户保证。图片 API 与 CLI 有各自上限。
  • 提供可打开、未损坏的 PDF。文件后缀改成 .pdf 不会把别的格式转换成 PDF。遇到密码或兼容问题,先本地检查,必要时拆分或另存副本。
  • API 结果与关联图片临时保留约 24 小时,应尽快下载。保存 result.json 或 Markdown 文字本身,不等于已保存其引用的图片。

Authorization 鉴权

在开放平台登录并创建/管理 API Key,确认当前解析额度。它不是桌面客户端或 Zotero 的登录 Token。以下 YOUR_DOC2X_API_KEY、TASK_UID、UPLOAD_URL、DOWNLOAD_URL 都是占位符;只在自己的运行环境替换,不提交到版本库。

text
Authorization: Bearer YOUR_DOC2X_API_KEY

请求开放平台接口时发送 Bearer 头;PUT 预签名上传 URL 和 GET 下载 URL 时不要附加该 API Key。签名 URL 自身有时效与访问能力,不放入公开日志。

POST /api/v2/parse/preupload 文件预上传

可选 model 为 v2 或 v3-2026;公开接口约定省略时使用默认模型。本教程显式传入 v3-2026,避免依赖默认值。其他值不要自行编造。

bash
curl --fail-with-body --request POST 'https://v2.doc2x.noedgeai.com/api/v2/parse/preupload' \
  --header "Authorization: Bearer $DOC2X_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"model":"v3-2026"}'

简化响应示意(ID 和地址为占位,不可直接调用):

json
{"code":"success","data":{"uid":"TASK_UID","url":"https://upload.example.invalid/signed.pdf"}}

先保存 uid,再向返回的 data.url PUT 原始文件二进制,不使用 multipart/form-data。取得链接后立即上传,以签名 URL 实际有效期为准;过期不能靠修改 URL 参数续期。

bash
curl --fail-with-body --request PUT "$UPLOAD_URL" --data-binary '@paper.pdf'

PUT 成功后进入状态查询,不要重复上传同一签名链接。上传传输失败时保留 uid 并先判断状态;网络中断不证明服务端未接收,盲目新建任务可能重复消耗额度。

GET /api/v2/parse/status 查看异步状态

bash
curl --fail-with-body --get 'https://v2.doc2x.noedgeai.com/api/v2/parse/status' \
  --header "Authorization: Bearer $DOC2X_API_KEY" \
  --data-urlencode "uid=$TASK_UID"

每隔 1–3 秒查询一次并设置总等待期限。刚上传后可能有短暂队列/状态传播延迟。HTTP 成功不代表任务成功,还需检查 JSON 的 code 和 data.status。

字段/状态怎么处理
code != "success"接口错误;记录错误码和任务 ID,按下方排查。
data.status = "processing"等待后继续 GET,不重发创建请求。
data.status = "failed"停止等待,检查 data.detail。
data.status = "success"读取 data.result.pages,保存结果并进入导出。
超时或未识别的状态保留 uid,稍后查原任务;不要把本地超时解释为远端取消。

简化完成响应:

json
{"code":"success","data":{"status":"success","progress":100,"result":{"pages":[{"page_idx":0,"page_width":1000,"page_height":1400,"md":"# Example\nText","url":"","score":89}]}}}

任务失败可发生在成功的 HTTP/业务外层内:

json
{"code":"success","data":{"status":"failed","detail":"Example failure detail"}}

page_idx 从 0 开始;page_width/page_height 是结果页面坐标尺寸;md 为本页 Markdown,url 可能为空,score 是质量分而非逐字准确率。v3-2026 的结构化字段见 v3 JSON。

POST /api/v2/convert/parse 请求导出文件

解析成功后创建一次导出任务,再轮询导出结果接口。不要把创建接口当成轮询接口。

参数类型说明
uidstring已成功解析的任务 ID。
tostringmd、tex 或 docx;网页中的其他选项不自动等于公开 API 参数。
formula_modestring必填,通常为 normal;Markdown 使用美元公式定界时选 dollar。
filenamestring,可选MD/TEX 文件基本名,不带扩展名,例如 paper。
merge_cross_page_formsboolean,可选尝试合并跨页表格;应核对合并结果。
formula_levelinteger,可选0 保留公式;1 将行内公式降为文本;2 将所有公式降为文本。只对源解析模型 v3-2026 生效。
json
{"uid":"TASK_UID","to":"md","formula_mode":"normal","filename":"paper","merge_cross_page_forms":false,"formula_level":0}

将上面的任务 ID 换成实际值并保存为 export-request.json:

bash
curl --fail-with-body --request POST 'https://v2.doc2x.noedgeai.com/api/v2/convert/parse' \
  --header "Authorization: Bearer $DOC2X_API_KEY" \
  --header 'Content-Type: application/json' \
  --data-binary '@export-request.json'

响应可为 {"code":"success","data":{"status":"processing","url":""}}。同一 uid 连续比较不同格式或公式等级时,等当前导出完成并下载后再请求下一份;不要并行覆盖结果。

GET /api/v2/convert/parse/result 导出获取结果

bash
curl --fail-with-body --get 'https://v2.doc2x.noedgeai.com/api/v2/convert/parse/result' \
  --header "Authorization: Bearer $DOC2X_API_KEY" \
  --data-urlencode "uid=$TASK_UID"

沿用有界轮询规则。只有 data.status="success" 且 data.url 非空才下载;失败检查 detail。解析成功与导出成功是两个阶段。

json
{"code":"success","data":{"status":"success","url":"https://download.example.invalid/export.zip"}}

下载与本地保存

bash
curl --fail --location --output export.zip "$DOWNLOAD_URL"
unzip -l export.zip

MD/TEX 导出可能是包含文本与图片资源的 ZIP;先检查实际文件格式,再解压到新目录。DOCX 是办公文档,即使内部也使用 ZIP 容器,也应保留 .docx 扩展名用办公软件打开。不要只改后缀推断格式。保留 Markdown/TeX 与图片的相对路径,在目标编辑器检查公式、图片、表格和页序。

标准 JSON 解析会将 \u0026 还原为 &;只有解析后的字符串仍含字面量 \u0026 时才替换一次,不要随意改写签名 URL 的其他字符。

完整 Python 示例

需要 Python 3.10+ 和 requests(python -m pip install requests)。在本机设置 DOC2X_API_KEY,准备 paper.pdf,保存为 parse_pdf.py 后运行 python parse_pdf.py。示例会真实提交解析/导出任务并消耗对应额度;本教程代码仅作离线校验,没有代替你运行服务。

python
import json
import os
import time
from pathlib import Path

import requests

BASE = "https://v2.doc2x.noedgeai.com"


def api(method, path, *, key, **kwargs):
    response = requests.request(method, BASE + path,
        headers={"Authorization": "Bearer " + key}, timeout=(10, 90), **kwargs)
    response.raise_for_status()
    body = response.json()
    if body.get("code") != "success":
        raise RuntimeError(f"API error: {body.get('code')}: {body.get('msg', '')}")
    return body["data"]


def wait_for(path, uid, *, key, max_wait=1200):
    deadline = time.monotonic() + max_wait
    while time.monotonic() < deadline:
        data = api("GET", path, key=key, params={"uid": uid})
        state = data.get("status")
        if state == "success":
            return data
        if state == "failed":
            raise RuntimeError(f"Task failed: {data.get('detail', '')}")
        # Upload/queue propagation can briefly precede processing.
        time.sleep(3)
    raise TimeoutError(f"Wait expired; retain uid={uid} and query status, do not resubmit")


def main():
    key = os.environ["DOC2X_API_KEY"]
    source = Path("paper.pdf")
    if not source.is_file() or source.stat().st_size == 0:
        raise ValueError("Provide a nonempty paper.pdf")
    out = Path("api-output")
    out.mkdir(exist_ok=False)  # Choose a new directory for each intentional task.
    task = api("POST", "/api/v2/parse/preupload", key=key,
               json={"model": "v3-2026"})
    uid = task["uid"]
    (out / "task.json").write_text(json.dumps({"uid": uid}), encoding="utf-8")
    # Signed object-storage URLs do not need your Doc2X Authorization header.
    with source.open("rb") as stream:
        response = requests.put(task["url"], data=stream, timeout=(10, 180))
        response.raise_for_status()
    parsed = wait_for("/api/v2/parse/status", uid, key=key)
    result = parsed["result"]
    (out / "result.json").write_text(
        json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
    pages = sorted(result.get("pages", []), key=lambda p: p.get("page_idx", 0))
    (out / "preview.md").write_text(
        "\n\n".join(p.get("md", "") for p in pages), encoding="utf-8")
    api("POST", "/api/v2/convert/parse", key=key, json={
        "uid": uid, "to": "md", "formula_mode": "normal",
        "filename": "paper", "merge_cross_page_forms": False, "formula_level": 0})
    exported = wait_for("/api/v2/convert/parse/result", uid, key=key)
    download_url = exported["url"].replace("\\u0026", "&")
    with requests.get(download_url, stream=True, timeout=(10, 180)) as response:
        response.raise_for_status()
        with (out / "export.zip").open("wb") as target:
            for chunk in response.iter_content(1024 * 1024):
                target.write(chunk)
    print(f"Saved result.json, preview.md and export.zip in {out}; uid={uid}")


if __name__ == "__main__":
    main()

api-output/task.json 在上传前保存 uid。result.json 是 data.result,可继续用于结构化处理;preview.md 是逐页正文合并,不保证图片已本地化;完整 MD 导出包为 export.zip。再次运行请选择新输出目录,避免覆盖已有结果。

错误排查

错误或现象处理
HTTP 401/403检查 API Key、账户与权限;不要使用网页登录 Token 替代。
HTTP 429 / parse_task_limit_exceeded / parse_concurrency_limit减少并行任务,等已有任务完成,按账户任务数/处理页数限额调整。
parse_quota_limit核对开放平台剩余解析额度,勿连续重试。
parse_file_too_large / parse_page_limit_exceeded按正在使用的入口与实际返回限额拆分;不能用网页/CLI限制代替API合同。
parse_status_not_found检查保存的 uid、账号及结果是否过期;过期后先找本地备份。
parse_file_not_pdf / parse_file_invalid本地打开验证 PDF、加密与文件内容;改后缀无效。
parse_timeout / parse_error / parse_create_task_error保留任务 ID、错误码和脱敏 request_id;检查文件后再决定是否拆分或联系支持,不无限重建。
parse_file_lock文件可能因重复失败被临时锁定;检查兼容性并联系支持,不通过改名反复提交。
下载返回错误或文件损坏先检查HTTP状态与导出状态;不要把错误JSON当ZIP保存。链接过期时查询原任务能否取回,勿先重跑OCR。

服务端既可能用 HTTP 错误,也可能在 HTTP 200 中返回业务错误。并发、页数与配额错误也可能在上传后查询状态时才出现。

实用集成

  • pdfdeal 官方文档:先按其当前版本安装与配置;不要假设任意旧版本都有 v3 裁切辅助函数。
  • MCP 工具:开放平台 API Key,适合 MCP 客户端提交、查询和保存结果。
  • CLI:个人账户登录流程,与开放平台 API 不同。
  • 扣子插件:可用性和参数以插件当前说明为准。

其他参考