Image2PPTAPI

Image2PPT 开发者 API

把图片和 PDF 批量转换成可编辑的 PPTX。上传一批文件,我们在后台用 AI 拆解版面、还原成可编辑的文字与形状,合成一个 PPTX 给你下载。

本文面向对接方的开发同学,读完就能接入。


一分钟了解怎么用

  1. 登录后进入「开发者 / API」页面创建一个 API 密钥。
  2. POST /api/v1/jobs 上传文件,拿到一个任务号
  3. 每隔几秒调 GET /api/v1/jobs/{任务号} 查进度,直到状态变成 completed
  4. GET /api/v1/jobs/{任务号}/download 下载成品 PPTX。

转换是异步的:提交后立刻返回任务号,真正的转换在后台跑。别在提交那一步干等结果。


认证

拿到密钥

登录 Image2PPT 后,从账号菜单进入「开发者 / API」页面,在「API Keys」处自助创建,得到一串形如下面的密钥:

i2p_live_xxxxxxxxxxxxxxxxxxxxxxxx

密钥只在创建时完整显示一次,请当场保存好。 之后页面只会显示前几位用于辨认。密钥泄露或需要轮换时,在同一页面吊销旧的、重建新的。

怎么带

每个请求都在 HTTP 头里带上密钥:

Authorization: Bearer i2p_live_xxxxxxxxxxxxxxxxxxxxxxxx

没带或带错,会返回 401(错误码 INVALID_API_KEY)。

基础地址

https://image2ppt.com

下文所有路径都拼在这个地址后面。


统一约定


端点

1. 提交任务 POST /api/v1/jobs

上传一批文件,创建一个转换任务。请求体是 multipart/form-data

字段

字段 必填 说明
files 一个或多个文件。支持 png / jpeg / webp / gif / pdf单文件不超过 35MB,同一请求的文件内容合计不超过 45MB。同一个字段名 files 重复出现来传多个文件。
locale 成品语言环境,zh-CN(默认)或 en
aspectRatio 幻灯片比例,auto(默认,随原图)/ 16:9 / 4:3

一次提交有两条上限,都要满足

上限 数值 说明
总页数 ≤ 50 页 一张图片算 1 页,一个 PDF 按它的实际页数算。
总体积 ≤ 45MB 这一次请求里所有文件内容加起来。单个文件另有 35MB 的上限。

两条是独立的:23 张高清图片只有 23 页,却很容易超过 45MB。页数没满不代表能提交。

超过总体积会返回 413 PAYLOAD_TOO_LARGE遇到它请减少单次提交的文件数量分批提交,重试同样的内容不会成功。

官方 SDK 分两种用法,行为不同:submit() / convert()(TypeScript 同名)只提交你给的这一批,会在上传前先本地核对体积和页数,超了直接报错,不会白传一遍,但不会替你拆批;要自动拆批请用 submit_all() / convert_all()(TypeScript 为 submitAll() / convertAll()),它们按体积和页数把文件切成若干次提交,每次一个任务。

成功响应 201 Created

{
  "jobId": "job_abc123",
  "status": "pending",
  "slideCount": 12,
  "creditsReserved": 12
}

curl 示例

curl -X POST https://image2ppt.com/api/v1/jobs \
  -H "Authorization: Bearer i2p_live_xxxx" \
  -F "files=@slide1.png" \
  -F "files=@slide2.png" \
  -F "files=@report.pdf" \
  -F "locale=zh-CN" \
  -F "aspectRatio=16:9"

可能的错误

HTTP code 含义
401 INVALID_API_KEY 密钥无效或缺失。
400 INVALID_FILE 文件格式不支持,或单文件超过 35MB。
400 TOO_MANY_SLIDES 总页数超过 50。
400 UPLOAD_ABORTED 上传中途断开,请求体没收完。重试即可;反复出现多半是这次提交太大,先按上面的体积上限分批。
400 MALFORMED_UPLOAD 请求体不是合法的 multipart/form-data。这是客户端拼装问题,重试不会好——检查边界串和各分段的头。
402 INSUFFICIENT_CREDITS 可用积分不够覆盖这次提交。
413 PAYLOAD_TOO_LARGE 同一请求的文件内容合计超过 45MB。
429 RATE_LIMITED 触发限流,见下方「限流」。

2. 查询任务状态 GET /api/v1/jobs/{jobId}

轮询这个端点看进度。

成功响应 200 OK

{
  "jobId": "job_abc123",
  "status": "processing",
  "progress": 45,
  "slideCount": 12,
  "creditsUsed": 0,
  "creditsRefunded": 0,
  "createdAt": "2026-07-07 08:00:00",
  "completedAt": null
}

字段

字段 说明
status pending(排队中)/ processing(转换中)/ completed(已完成)/ failed(已失败)。
progress 进度百分比,0–100。
slideCount 总页数。
creditsUsed 结算后实际扣除的积分。
creditsRefunded 部分成功时退回的失败页积分,见「计费与退款」。
createdAt / completedAt UTC 创建时间 / 完成时间,格式为 YYYY-MM-DD HH:MM:SS(未完成时 completedAtnull)。
downloadUrl 仅当 completed 且成品仍在保留期内时给出,是下载端点的相对路径;其余状态不返回这个字段。
error 仅当 failed 时给出,形如 {"code": "...", "message": "..."}

失败时的样子

{
  "jobId": "job_abc123",
  "status": "failed",
  "progress": 0,
  "slideCount": 12,
  "creditsUsed": 0,
  "creditsRefunded": 12,
  "createdAt": "2026-07-07 08:00:00",
  "completedAt": "2026-07-07 08:01:00",
  "error": { "code": "CONVERSION_FAILED", "message": "转换失败,请稍后重试" }
}

可能的错误

HTTP code 含义
404 JOB_NOT_FOUND 任务号不存在,或不属于当前密钥所在账户。

提示:任务号只在你自己的账户内可见,别人拿不到、也查不到你的任务。


3. 下载成品 GET /api/v1/jobs/{jobId}/download

任务完成后,从这里下载 PPTX。

成功响应 200 OK,响应体就是 PPTX 二进制流(Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation)。

可能的错误

HTTP code 含义
409 NOT_READY 任务还没完成,成品暂不可下载。等状态变成 completed 再来。
410 OUTPUT_EXPIRED 成品已过保留期被清理,无法下载(见下方「保留期」)。
416 RANGE_NOT_SATISFIABLE Range 请求的起点超出文件大小,请丢弃旧的续传位置后重新下载。
404 JOB_NOT_FOUND 任务号不存在或不属于本账户。

保留期:成品 PPTX 在完成后保留 7 天,过期自动清理,之后下载会返回 410 OUTPUT_EXPIRED。请在保留期内取走。(历史记录仍在,只是成品文件不再保存。)


4. 查询账户 GET /api/v1/account

成功响应 200 OK

{
  "email": "you@example.com",
  "credits": 328
}

credits 是当前可用积分(不含已被进行中任务锁定的部分)。API 转换与网页端共用同一份积分。


限流

账户限流(同一账户下所有密钥共享额度):

超出时返回 429RATE_LIMITED),并在 Retry-After 响应头给出建议等待的秒数

正确的应对:读 Retry-After,等这么多秒再重试,别无脑立刻重试。官方 Python 客户端的 wait() 已经内建了这个退避;若你自己直接提交,参考下面的伪代码:

import time, requests

while True:
    resp = requests.post(url, headers=headers, files=files)
    if resp.status_code != 429:
        break
    time.sleep(int(resp.headers.get("Retry-After", "5")))

版本与升级提示

官方 SDK(0.2.0 起)每个请求都会自报家门:

User-Agent: image2ppt-python/0.2.0
User-Agent: image2ppt-node/0.2.0

这个头只用于统计和联系你,不参与鉴权、不参与限流、不影响任何请求的结果

自己写客户端的话,不用管这个头——带不带都一样,我们把所有非官方 SDK 的调用统一记成「自建客户端」,不区分语言、不记版本,也不保存你报的那串字符(所以带一个自定义的名字并不会让你的程序在我们这边更容易被认出来,这一点我们不做假承诺)。

只有一个请求:不要冒用 image2ppt-python/...image2ppt-node/...。这两个字符串是官方 SDK 的身份,冒用会让「官方 SDK 占比」这个数失真,而且我们会照着它给你发升级提示——提示里指的版本你根本没在用。

如果你用的官方 SDK 版本已经低于我们仍在维护的最低版本,响应里会多带三个标准头(RFC 8594 / RFC 9745),成功的响应上也带

Deprecation: @1793491200
Sunset: Sun, 01 Nov 2026 00:00:00 GMT
Link: <https://github.com/shrektan/image2ppt-sdk/blob/main/CHANGELOG.md>; rel="deprecation"

**这些头只是提醒。**状态码不变,请求照常处理,不会因此被拒绝。官方 SDK 收到后会在你的日志里打一条警告(可以关掉)。真要停用某个版本,我们会提前很久单独公告,不会只靠这个头。


业务语义

异步与时延预期

提交后任务在后台跑。单页典型耗时约 2 分钟,九成任务在 3 分钟内完成。页数多的任务更久。建议轮询间隔从 5 秒起、逐步退避到 15 秒左右,不要每秒猛查。

一个任务 = 一个 PPTX

一次提交的所有文件(多张图 / 多页 PDF)会合成同一个 deck,按上传顺序排页。想要多个独立 PPTX,就分成多次提交。

计费与退款

一句话:你只为成功产出的页付费。


官方 SDK

我们提供 Python 和 Node.js/TypeScript 两个官方客户端,都封装了提交、轮询、下载、429 退避和错误映射。源码、示例和完整说明在 GitHub:https://github.com/shrektan/image2ppt-sdk

SDK 只在服务端使用。别把 API 密钥放进浏览器或任何用户能看到的地方——谁都能读出来。

Python

pip install image2ppt
from image2ppt import Image2PPTClient, Image2PPTError, JobFailedError

client = Image2PPTClient(api_key="i2p_live_你的密钥")

try:
    # 一步到位:提交 → 轮询等待 → 下载
    job = client.convert(
        ["slide1.png", "slide2.png", "report.pdf"],
        dest_path="out.pptx",
        locale="zh-CN",
        aspect_ratio="16:9",
    )
    print("完成,用掉积分:", job.credits_used, "退回:", job.credits_refunded)
except JobFailedError as e:
    print("转换失败:", e.code, e.message)
except Image2PPTError as e:
    print("请求出错:", e.status_code, e.code, e.message)

Node.js / TypeScript

零依赖,需要 Node 18+(用内置 fetch)。

npm install image2ppt
import { Image2PPTClient, Image2PPTError, JobFailedError } from "image2ppt";

const client = new Image2PPTClient({ apiKey: "i2p_live_你的密钥" });

try {
  const job = await client.convert(
    ["slide1.png", "slide2.png", "report.pdf"],
    "out.pptx",
    { locale: "zh-CN", aspectRatio: "16:9" },
  );
  console.log("完成,用掉积分:", job.creditsUsed, "退回:", job.creditsRefunded);
} catch (e) {
  if (e instanceof JobFailedError) console.error("转换失败:", e.code, e.message);
  else if (e instanceof Image2PPTError) console.error("请求出错:", e.statusCode, e.code, e.message);
  else throw e;
}

分步控制(submit / wait / download)、账户查询(account)和各异常的完整说明见 GitHub 仓库的 README 与示例。


错误码总表

message 是给人读的,语言跟着请求的 Accept-Language 走:说中文就给中文,不带这个头或者说别的语言一律给英文。浏览器 cookie、界面语言头这些都不影响它——从浏览器里调这个接口也一样,你声明什么就是什么。要在代码里分支请用 code,它不随语言变。

HTTP code 出现场景
401 INVALID_API_KEY 密钥无效或缺失(所有端点)。
400 NO_FILES 没有带任何文件(提交)。
400 INVALID_FILE 文件格式不支持或单文件超 35MB(提交)。
400 INVALID_PDF PDF 无法读取或解析(提交)。
400 INVALID_ASPECT_RATIO 画幅比例不认识,用 auto16:94:3(提交)。
400 TOO_MANY_SLIDES 总页数超过 50(提交)。
400 PAGE_RATE_EXCEEDED 单次提交页数就超过每分钟提交上限,永远排不进窗口(提交)。
400 UPLOAD_ABORTED 上传中途断开,请求体没收完(提交)。重试即可;反复出现多半是这次提交太大,见 PAYLOAD_TOO_LARGE
400 MALFORMED_UPLOAD 请求体不是合法的 multipart/form-data(提交)。客户端拼装问题,重试不会好。
402 INSUFFICIENT_CREDITS 可用积分不足,或余额为 0(提交)。
403 API_KEY_REQUIRED 缺少有效的 API key(提交)。
403 ACCOUNT_DELETED 账号已删除(提交)。
413 PAYLOAD_TOO_LARGE 同一请求的文件内容合计超过 45MB(提交)。
429 RATE_LIMITED 触发限流,带 Retry-After 头(提交)。轮询状态不限流。
404 JOB_NOT_FOUND 任务号不存在或不属于本账户(查询、下载)。
409 NOT_READY 任务未完成就来下载(下载)。
410 OUTPUT_EXPIRED 成品已过保留期被清理(下载)。
416 RANGE_NOT_SATISFIABLE 下载续传范围超出成品文件大小(下载)。
5xx STORAGE_FAILED 服务端处理出错,稍后重试;反复出现请联系我们。