API接口文档

6. API 接口

API 地址:https://api.iloveofd.cn

API 接口总览

接口 方法 说明
/api/login POST 登录并获取 Token
/api/auth GET 获取 BOS 临时授权
BOS Endpoint PUT 上传文件
/api/create POST 创建转换任务
/api/status/{requestId} GET 查询任务状态
/api/detail/{requestId} GET 获取转换结果
/api/balance GET 查询账户余额
/api/billing/{year}/{month} GET 查询月度账单
/api/billing/{year}/{month}/{day} GET 查询每日账单
/api/order/list GET 查询充值记录

6.1 登录并获取 Token

请求

POST /api/login

Content-Type

application/json

认证

无需 Token。

请求参数

参数 类型 必填 说明
username String 是 API 用户名
password String 是 API 密码

cURL

curl -X POST 'https://api.iloveofd.cn/api/login' \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "your_username",
    "password": "your_password"
  }'

Java

import okhttp3.*;

public class LoginExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        String json = """
                {
                  "username": "your_username",
                  "password": "your_password"
                }
                """;

        RequestBody body = RequestBody.create(
                json,
                MediaType.parse("application/json")
        );

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/login")
                .post(body)
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

Python

import requests

response = requests.post(
    "https://api.iloveofd.cn/api/login",
    json={
        "username": "your_username",
        "password": "your_password"
    }
)

print(response.json())

成功响应

{
  "code": 200,
  "token": "your_token"
}

响应参数

参数 类型 说明
code Number 状态码
token String 身份认证 Token
msg String 错误信息

6.2 获取 BOS 临时授权

请求

GET /api/auth

需要 Token。

cURL

curl 'https://api.iloveofd.cn/api/auth' \
  -H 'token: your_token'

Java

import okhttp3.*;

public class AuthExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/auth")
                .addHeader("token", "your_token")
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

Python

import requests

response = requests.get(
    "https://api.iloveofd.cn/api/auth",
    headers={
        "token": "your_token"
    }
)

print(response.json())

响应参数

参数 类型 说明
accessKeyId String BOS 临时访问 Key
secretAccessKey String BOS 临时 Secret
securityToken String 临时安全 Token
bucket String BOS Bucket
endpoint String BOS 上传地址
durationSeconds Number 授权有效时间,秒 ,默认1200s
expiration String 授权过期时间

临时授权仅用于文件上传,不应作为长期凭证保存。


可以接着写成 6.3 上传文件至 BOS,并且和你前面的 6.2 保持一致的接口文档风格。这里建议重点把 auth 返回值 → 生成 fileKey → 拼接 BOS URL → PUT 上传 → 判断成功 → 调用 create 讲清楚。

6.3 上传文件至 BOS

获取 BOS 临时授权后,将待转换文件直接上传至百度云 BOS。百度云官方教程。

上传流程

上一步骤获取BOS 临时授权
        ↓
生成唯一 fileKey
        ↓
构造 BOS 上传地址
        ↓
PUT 上传文件
        ↓
判断上传结果
        ↓
上传成功
      

注意: 必须确认文件已经成功上传至 BOS 后,再调用 /api/create。

6.3.1 生成 fileKey

使用 UUID 作为文件 Key,并保留原文件扩展名。

例如:

原文件:
test.caj

fileKey:2642efca-cd38-46ec-bf3c-d1a2af8dea84.caj

Java:

String fileKey = UUID.randomUUID() + ".caj";

Python:

import uuid

file_key = f"{uuid.uuid4()}.caj"

不同文件类型应使用对应的文件扩展名。

6.3.2 构造 BOS 上传地址

使用 /api/auth 返回的参数endpoint和生成的filekey,造 BOS Object 上传地址:

https://{endpoint}/{fileKey}

例如:

https://iloveofd.bj.bcebos.com/2642efca-cd38-46ec-bf3c-d1a2af8dea84.caj

实际 endpoint 以 /api/auth 接口返回结果为准,不建议在程序中写死。

6.3.3 PUT 上传文件

上传文件时使用 HTTP PUT 请求。

请求:

PUT https://{endpoint}/{fileKey}

请求 Header:

参数 说明
Authorization BOS 请求授权信息
Content-Type 文件 MIME 类型
x-bce-security-token /api/auth 返回的临时安全 Token

BOS 请求需要按照百度云 BOS 的签名规则生成 Authorization。如果使用百度云 BOS SDK,可由 SDK 自动完成请求签名。

Java

使用百度云 BOS SDK 上传时,推荐直接使用 SDK,避免自行实现 BOS 请求签名。

import com.baidubce.auth.DefaultBceSessionCredentials;
import com.baidubce.services.bos.BosClient;
import com.baidubce.services.bos.BosClientConfiguration;


import java.io.File;
import java.util.UUID;

public class BosUploadExample {

    public static void main(String[] args) {

        String accessKeyId = "your_access_key_id";
        String secretAccessKey = "your_secret_access_key";
        String securityToken = "your_security_token";

        String bucket = "iloveofd";
        String endpoint = "https://iloveofd.gz.bcebos.com";

        File file = new File("./test.caj");
        String fileKey =UUID.randomUUID() + ".caj";

        DefaultBceSessionCredentials credentials = new DefaultBceSessionCredentials(accessKeyId , secretAccessKey , securityToken );

        // 3. 配置 BosClient,并设置上述凭证
        BosClientConfiguration configuration = new BosClientConfiguration();
        configuration.setCredentials(credentials);
        configuration.setEndpoint(endpoint);
        BosClient client = new BosClient(configuration);

        try {
            client.putObject(bucket, fileKey, file);
            System.out.println("上传成功,fileKey: " + fileKey);
        } finally {
            client.shutdown();
        }
    }
}

如果使用临时安全 Token,请根据所使用的 BOS Java SDK 版本配置 securityToken。具体配置方式以百度云 BOS SDK 当前版本为准。

Python

推荐使用百度云 BOS Python SDK 上传文件。

安装 SDK:

pip install baidubce

上传示例:

import os
import uuid

from baidubce.auth.bce_credentials import BceCredentials
from baidubce.bce_client_configuration import BceClientConfiguration
from baidubce.services.bos.bos_client import BosClient

file_path = "./test.caj"

filename = os.path.basename(file_path)

# 获取文件扩展名
suffix = os.path.splitext(file_path)[1]

# 生成唯一 fileKey
file_key = f"{uuid.uuid4()}{suffix}"

# /api/auth 返回的临时授权信息
access_key_id = "your_access_key_id"
secret_access_key = "your_secret_access_key"
security_token = "your_security_token"
bucket = "iloveofd"
endpoint = "https://iloveofd.gz.bcebos.com"
credentials = BceCredentials(access_key_id, secret_access_key)
config = BceClientConfiguration(credentials=credentials,endpoint=endpoint,security_token=security_token      )
client = BosClient(config)
client.put_object_from_file(bucket, file_key, filename)

6.3.4 上传成功判断

如果使用 HTTP PUT 方式上传,BOS 返回 HTTP 200 表示文件上传成功。

例如:

HTTP/1.1 200 OK

客户端确认上传成功后,再调用:

POST /api/create

如果上传失败,则不要调用 /api/create。


6.4 创建转换任务

请求

POST /api/create

需要 Token。

请求参数

参数 类型 必填 说明
taskType String 是 任务类型
strPairs Object 否 需要根据任务类型,输入不同任务类型参数
ossPendingFiles Array 是 待处理文件

ossPendingFiles

参数 类型 必填 说明
fileKey String 是 BOS 文件 Key
fileName String 是 文件名称
fileSize Number 否 文件大小,Byte

cURL

curl -X POST 'https://api.iloveofd.cn/api/create' \
  -H 'Content-Type: application/json' \
  -H 'token: your_token' \
  -d '{
    "taskType": "OFD2PDF",
    "strPairs": {},
    "ossPendingFiles": [
      {
        "fileKey": "xxx.ofd",
        "fileName": "example.ofd"
      }
    ]
  }'

Java

import okhttp3.*;

public class CreateTaskExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        String json = """
                {
                  "taskType": "OFD2PDF",
                  "strPairs": {},
                  "ossPendingFiles": [
                    {
                      "fileKey": "xxx.ofd",
                      "fileName": "example.ofd"
                    }
                  ]
                }
                """;

        RequestBody body = RequestBody.create(
                json,
                MediaType.parse("application/json")
        );

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/create")
                .addHeader("token", "your_token")
                .post(body)
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

Python

import requests

response = requests.post(
    "https://api.iloveofd.cn/api/create",
    headers={
        "token": "your_token"
    },
    json={
        "taskType": "OFD2PDF",
        "strPairs": {},
        "ossPendingFiles": [
            {
                "fileKey": "xxx.ofd",
                "fileName": "example.ofd"
            }
        ]
    }
)

print(response.json())

成功响应

{
  "code": 200,
  "requestId": "c8d157af99e64296bd8e027060691e83",
  "uuid": "5bc3aa30e04c47819a41241acdc10a42"
}

6.5查询任务状态

请求

GET /api/status/{requestId}

Path 参数

参数 类型 必填 说明
requestId String 是 创建任务返回的请求 ID

cURL

curl 'https://api.iloveofd.cn/api/status/c8d157af99e64296bd8e027060691e83' \
  -H 'token: your_token'

Java

import okhttp3.*;

public class StatusExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        String requestId =
                "c8d157af99e64296bd8e027060691e83";

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/status/" + requestId)
                .addHeader("token", "your_token")
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

Python

import requests

request_id = "c8d157af99e64296bd8e027060691e83"

response = requests.get(
    f"https://api.iloveofd.cn/api/status/{request_id}",
    headers={
        "token": "your_token"
    }
)

print(response.json())

响应

{
  "code": 200,
  "taskStatus": {
    "status": "PROCESSING",
    "uuid": "5bc3aa30e04c47819a41241acdc10a42",
    "progress": 50,
    "order": null
  }
}

状态

状态 说明
NOT_STARTED 等待处理
PROCESSING 转换中
COMPLETED 转换完成
FAILED 转换失败

6.6 获取转换结果

请求

GET /api/detail/{requestId}

cURL

curl 'https://api.iloveofd.cn/api/detail/c8d157af99e64296bd8e027060691e83' \
  -H 'token: your_token'

Java

import okhttp3.*;

public class DetailExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        String requestId =
                "c8d157af99e64296bd8e027060691e83";

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/detail/" + requestId)
                .addHeader("token", "your_token")
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

Python

import requests

request_id = "c8d157af99e64296bd8e027060691e83"

response = requests.get(
    f"https://api.iloveofd.cn/api/detail/{request_id}",
    headers={
        "token": "your_token"
    }
)

print(response.json())

成功响应

{
  "code": 200,
  "task": {
    "uuid": "26ef1de38d864a2ab3f5627e963740ac",
    "createTime": "1787497334590",
    "finishTime": "1787497358615",
    "taskType": "OFD2PDF",
    "taskStatus": "COMPLETED",
    "ossProcessedFiles": [
      {
        "sort": 0,
        "fileSize": 6828704,
        "fileName": "result.pdf",
        "fileUrl": "https://download.iloveofd.cn/...",
        "fileKey": "/2026/08/23/result.pdf"
      }
    ]
  }
}

6.7 查询账户余额

请求

GET /api/balance

cURL

curl 'https://api.iloveofd.cn/api/balance' \
  -H 'token: your_token'

Java

import okhttp3.*;

public class BalanceExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/balance")
                .addHeader("token", "your_token")
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

Python

import requests

response = requests.get(
    "https://api.iloveofd.cn/api/balance",
    headers={
        "token": "your_token"
    }
)

print(response.json())

响应

{
  "code": 200,
  "msg": "查询成功",
  "data": {
    "companyName": "your_company",
    "balance": 90.74,
    "balanceUpdateTime": "2026-08-23 15:37:30"
  }
}

6.8 查询账单

按月查询

GET /api/billing/{year}/{month}

例如:

GET /api/billing/2026/8

按日查询

GET /api/billing/{year}/{month}/{day}

例如:

GET /api/billing/2026/8/23

cURL

curl 'https://api.iloveofd.cn/api/billing/2026/8' \
  -H 'token: your_token'

Python

import requests

response = requests.get(
    "https://api.iloveofd.cn/api/billing/2026/8",
    headers={
        "token": "your_token"
    }
)

print(response.json())

Java

import okhttp3.*;

public class BillingExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/billing/2026/8")
                .addHeader("token", "your_token")
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

6.9 查询充值记录

请求

GET /api/order/list

cURL

curl 'https://api.iloveofd.cn/api/order/list' \
  -H 'token: your_token'

Python

import requests

response = requests.get(
    "https://api.iloveofd.cn/api/order/list",
    headers={
        "token": "your_token"
    }
)

print(response.json())

Java

import okhttp3.*;

public class OrderListExample {

    public static void main(String[] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url("https://api.iloveofd.cn/api/order/list")
                .addHeader("token", "your_token")
                .get()
                .build();

        try (Response response = client.newCall(request).execute()) {
            System.out.println(response.body().string());
        }
    }
}

7. 错误码

7.1 通用错误码

所有接口均通过 code 表示请求结果。

Code 说明
200 请求成功
400 请求参数错误
401 无权访问
402 Token 已失效或未登录
403 账户余额不足
404 资源或账户信息不存在

7.2 创建任务错误码

Code 说明
405 未发现需要处理的文件
406 单个任务超过文件数量限制
407 文件名称格式错误
408 当前账户未开通该功能
409 文件不存在
410 参数错误

8. 开发建议

Token

建议由服务端统一管理,不要暴露给前端。

文件上传

必须先上传文件,再调用 /api/create。

任务轮询

建议使用合理的轮询间隔,不要高频请求任务状态接口。

下载结果

fileUrl 为临时下载地址,任务完成后请及时下载。

余额

API 为计费服务,请确保账户余额充足。


9. 常见问题

Token 有效期多久?

默认有效期为 360 天。

文件可以直接提交给 /api/create 吗?

不可以。需要先通过 BOS 完成文件上传。

requestId 有什么作用?

用于查询任务状态和获取任务详情。

fileUrl 可以永久保存吗?

不建议。fileUrl 是临时下载地址,应在有效期内下载文件。

余额不足怎么办?

充值后重新创建任务。

如何查询费用?

使用 /api/billing/{year}/{month} 查询月度账单,或使用日期接口查询指定日期账单。