OneSky External API v1
Programmatically upload XLIFF / XLSX / DOCX / PPTX files for machine translation, poll job progress, and download the translated results.
通过 API 上传 XLIFF / XLSX / DOCX / PPTX 文件进行机器翻译,轮询任务进度,并下载翻译结果。
Overview概述
The API exposes four endpoints under the base path /v1. A
typical integration uploads a file, receives a jobId, polls job status until it is
Done, then downloads the returned files.
该 API 在基础路径 /v1 下提供四个端点。典型集成流程为:上传文件,获得
jobId,轮询任务状态直到变为 Done,然后下载返回的文件。
| Environment | Base URL |
|---|---|
| Production | https://ext-api.oneskyai.net |
| 环境 | Base URL |
|---|---|
| 生产环境 | https://ext-api.oneskyai.net |
All requests and responses use application/json unless noted (file
uploads use multipart/form-data). All endpoints must be called on the
ext-api host above — requests to any other OneSky host are rejected.
除特别说明外,所有请求和响应均使用 application/json(文件上传使用
multipart/form-data)。所有端点必须通过上方的 ext-api 主机调用——发往其他
OneSky 主机的请求会被拒绝。
Authentication身份验证
Every request must include your API key in the x-api-key header. Keys are
generated in the OneSky MTPE Portal (one-time reveal on creation) and scope which projects and
languages you may access.
每个请求都必须在 x-api-key 请求头中携带你的 API key。Key 在 OneSky MTPE
Portal 生成(创建时仅显示一次),并决定你可访问的项目与语言范围。
curl https://ext-api.oneskyai.net/v1/projects \ -H "x-api-key: osk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
401 Unauthorized. Requests that do not reach the API through
the official host return 403 Forbidden.401 Unauthorized。未通过官方主机访问的请求会返回 403 Forbidden。Create an API key创建 API key
API keys are self-managed in the OneSky MTPE Portal.
API key 由你在 OneSky MTPE Portal 自助管理。
| Environment | Portal URL |
|---|---|
| Production | https://api.oneskyai.net/mtpe-portal/mtpe-platform/api-keys |
| 环境 | Portal URL |
|---|---|
| 生产环境 | https://api.oneskyai.net/mtpe-portal/mtpe-platform/api-keys |
- Sign in to the MTPE Portal with your OneSky account, then open the API Keys page from the top navigation (or go directly to the URL above).
- Click Generate Key, enter a descriptive label (e.g.
integration-prod) to identify the key later, and confirm. - The full key (
osk_…) is shown once. Copy it immediately and store it in a secret manager — it is never displayed again and cannot be recovered. - Send it in the
x-api-keyheader of every request.
- 用你的 OneSky 账号登录 MTPE Portal,从顶部导航打开 API Keys 页面(或直接访问上方 URL)。
- 点击 Generate Key,填写一个便于识别的 label(例如
integration-prod),然后确认。 - 完整的 key(
osk_…)只会显示一次。请立即复制并保存到密钥管理工具——之后不会再显示,且无法找回。 - 在每个请求的
x-api-key请求头中携带它。
401 Unauthorized. To rotate, create a
new key, switch your integration over, then disable the old one.401 Unauthorized。轮换时:先创建新 key,切换集成,再禁用旧 key。Conventions约定
HTTP status codesHTTP 状态码
| 200 | Success. |
| 400 | Invalid request (missing/invalid parameter, unsupported language or file type). |
| 401 | Missing or invalid API key. |
| 403 | Project not in your scope, or request did not reach the API host. |
| 404 | Job not found. |
| 413 | Uploaded file exceeds the 30 MB binary limit. |
| 500 | Unexpected server error. |
| 200 | 成功。 |
| 400 | 请求无效(参数缺失/无效、不支持的语言或文件类型)。 |
| 401 | 缺失或无效的 API key。 |
| 403 | 项目不在你的权限范围内,或请求未到达 API 主机。 |
| 404 | 找不到任务。 |
| 413 | 上传文件超过 30 MB 二进制上限。 |
| 500 | 服务器异常。 |
Error body shapes错误响应结构
Errors raised during authentication use a message field; errors raised
by an endpoint use an error field.
身份验证阶段产生的错误使用 message 字段;端点产生的错误使用 error 字段。
// auth-layer error (401 / 403 / 500 before reaching an endpoint)
{ "message": "Unauthorized" }
// endpoint error (validation, not found, etc.)
{ "error": "projectId is required" }
Typical workflow典型流程
1. GET /v1/projects → pick a projectId
2. GET /v1/languages → confirm supported languages
3. POST /v1/upload → returns { "jobId": "..." }
4. GET /v1/jobs/status?jobId=... (poll every ~5s)
status: Pending → Processing → Done
5. When status = Done, download each URL in the "files" array
1. GET /v1/projects → 选择一个 projectId
2. GET /v1/languages → 确认支持的语言
3. POST /v1/upload → 返回 { "jobId": "..." }
4. GET /v1/jobs/status?jobId=... (约每 5 秒轮询一次)
status: Pending → Processing → Done
5. 当 status = Done 时,下载 "files" 数组中的每个 URL
List projects列出项目
Returns the projects accessible to your API key. Use a returned id as the
projectId when uploading.
返回你的 API key 可访问的项目。上传时使用返回的 id 作为 projectId。
{
"projects": [
{ "id": "recGItPC9oapMIyyX", "name": "My Project" }
]
}
401 — Unauthorized401 — 未授权
{ "message": "Unauthorized" }
List languages列出语言
Returns the source → target language pairs allowed for your account
(the pairs array — the source of truth), plus flattened sourceLanguages /
targetLanguages lists for convenience (e.g. dropdowns). Codes are lowercase and must be
used when uploading XLSX files. (XLIFF files carry their own language attributes.) An account whose
organization configured no pairs gets empty lists — meaning no pair restriction on upload.
返回你账号允许的源 → 目标语言语言对(pairs 数组——以此为准),
另外附带扁平化的 sourceLanguages / targetLanguages 列表以便使用(例如下拉框)。语言代码为小写,
上传 XLSX 文件时必须使用。(XLIFF 文件自带语言属性。)若你的组织未配置任何语言对,则返回空列表——
即上传时不做语言对限制。
{
"pairs": [
{ "source": { "code": "en", "name": "English" }, "target": { "code": "zh-cn", "name": "Chinese Simplified" } },
{ "source": { "code": "en", "name": "English" }, "target": { "code": "ja", "name": "Japanese" } },
{ "source": { "code": "zh-tw", "name": "Chinese Traditional" }, "target": { "code": "ko", "name": "Korean" } }
],
"sourceLanguages": [
{ "code": "en", "name": "English" },
{ "code": "zh-tw", "name": "Chinese Traditional" }
],
"targetLanguages": [
{ "code": "zh-cn", "name": "Chinese Simplified" },
{ "code": "ja", "name": "Japanese" },
{ "code": "ko", "name": "Korean" }
]
}
500 — Server error500 — 服务器错误
{ "error": "Failed to fetch languages" }
Upload a file上传文件
Uploads an XLIFF, XLSX, DOCX or PPTX file and starts the automation pipeline
(Source Upload → Word Count → Machine Translation → Export). Provide the file either as a binary
multipart/form-data upload or as a public fileUrl (JSON body).
Returns a jobId to poll.
上传 XLIFF、XLSX、DOCX 或 PPTX 文件并启动自动化流程(Source Upload → Word Count → Machine Translation →
Export)。文件可通过二进制 multipart/form-data 上传,或提供可公开访问的 fileUrl
(JSON body)。返回用于轮询的 jobId。
Parameters参数
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | either / or | The file itself (multipart/form-data). .xliff, .xlf, .xlsx, .docx, or .pptx. Max 30 MB. |
fileUrl | string | either / or | Public URL to the file (JSON body). Use this for files larger than 30 MB. |
projectId | string | required | A project id from GET /projects. |
sourceLanguage | string | XLSX / DOCX / PPTX | Source language code. Required for XLSX, DOCX and PPTX; ignored for XLIFF (read from the file). |
targetLanguages | string | XLSX / DOCX / PPTX | Comma-separated target codes, e.g. zh-CN,ja. Required for XLSX, DOCX and PPTX; ignored for XLIFF. |
columnsSchema | object | XLSX only | Maps a language code to its column letter, e.g. { "en": "A", "zh-CN": "B" }. Must include the source language (its column is the source text). Target-language columns are optional — include one only when the sheet already has pre-translated text to import; omit it for a plain MT job (MT generates the translation). Required for XLSX. For multipart/form-data, send it as a JSON string. |
sheetNames | string[] | XLSX only | Which sheet(s) to read — column letters are sheet-agnostic, so this is mandatory. JSON array ["Sheet1"] or comma-separated Sheet1,Sheet2. Required for XLSX. |
keyCol | string | XLSX optional | Column letter holding a string ID/key. When omitted, keys fall back to <sheet>-<row>. |
importExistingTranslation | boolean | XLIFF only | When true, existing <target> values in the XLIFF are imported as already-translated segments. Default false. |
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | binary | 二选一 | 文件本体(multipart/form-data)。.xliff、.xlf、.xlsx、.docx 或 .pptx。最大 30 MB。 |
fileUrl | string | 二选一 | 文件的公开 URL(JSON body)。大于 30 MB 的文件请用此方式。 |
projectId | string | 必填 | 来自 GET /projects 的项目 id。 |
sourceLanguage | string | XLSX / DOCX / PPTX | 源语言代码。XLSX、DOCX、PPTX 必填;XLIFF 会忽略(从文件读取)。 |
targetLanguages | string | XLSX / DOCX / PPTX | 逗号分隔的目标语言代码,例如 zh-CN,ja。XLSX、DOCX、PPTX 必填;XLIFF 会忽略。 |
columnsSchema | object | 仅 XLSX | 将语言代码映射到其列字母,例如 { "en": "A", "zh-CN": "B" }。必须包含源语言(其列为原文)。目标语言的列为选填——仅当表格中已有可导入的预翻译文本时才填写;纯 MT 任务可省略(由 MT 生成译文)。XLSX 必填。使用 multipart/form-data 时请以 JSON 字符串传入。 |
sheetNames | string[] | 仅 XLSX | 要读取的工作表——列字母与工作表无关,因此必须指定。JSON 数组 ["Sheet1"] 或逗号分隔 Sheet1,Sheet2。XLSX 必填。 |
keyCol | string | XLSX 选填 | 存放字符串 ID/键的列字母。省略时,键回退为 <sheet>-<row>。 |
importExistingTranslation | boolean | 仅 XLIFF | 为 true 时,XLIFF 中已有的 <target> 值会作为已翻译片段导入。默认 false。 |
<file> blocks with different target-language attributes. The
server parses each and creates an independent task per target language. Each source → target
pair is validated against your organization's allowed pairs (case-insensitive); when your
organization configured no pairs, no pair restriction is applied.target-language 属性的 <file> 块。服务器会逐个解析,并为每个目标语言创建独立任务。
每个源 → 目标语言对会与你组织的允许语言对校验(不区分大小写);若你的组织未配置任何语言对,则不做语言对限制。columnsSchema must tell
the server which column letter holds the source text (the sourceLanguage entry, always
required). A target-language column is only needed when the sheet already contains pre-translated
text — omit it and MT will generate the translation. Column letters are case-insensitive and apply
across every sheet listed in sheetNames.columnsSchema 告诉服务器原文在哪一列(sourceLanguage
对应项,必填)。仅当表格中已有预翻译文本时才需要填写目标语言的列;省略则由 MT 生成译文。列字母不区分大小写,
并对 sheetNames 中列出的每一张工作表生效。sourceLanguage and
targetLanguages. Unlike XLSX it needs no columnsSchema,
sheetNames or keyCol — the whole document is a single implicit source and
the parser reads every text run. Each source → target pair is validated against your
organization's allowed pairs, same as XLSX.sourceLanguage 与 targetLanguages。但与 XLSX 不同,
它无需 columnsSchema、sheetNames 或 keyCol——整份文档即
单一原文,解析器会读取每一个文本 run。每个源 → 目标语言对同样会与你组织的允许语言对校验。Example — by URL (DOCX)示例 — 通过 URL(DOCX)
curl -X POST https://ext-api.oneskyai.net/v1/upload \
-H "x-api-key: osk_xxx" \
-H "Content-Type: application/json" \
-d '{
"fileUrl": "https://example.com/file.docx",
"projectId": "recGItPC9oapMIyyX",
"sourceLanguage": "en",
"targetLanguages": "zh-CN,ja"
}'
PPTX is identical — just point fileUrl at a .pptx
(or send a .pptx binary via -F "file=@..."). No column or sheet fields apply.
PPTX 完全相同——只需将 fileUrl 指向 .pptx
(或用 -F "file=@..." 上传 .pptx 二进制)。不涉及任何列或工作表字段。
Example — binary upload (XLIFF)示例 — 二进制上传(XLIFF)
curl -X POST https://ext-api.oneskyai.net/v1/upload \ -H "x-api-key: osk_xxx" \ -F "file=@/path/to/merge_en.xliff" \ -F "projectId=recGItPC9oapMIyyX" \ -F "importExistingTranslation=false"
Example — by URL (XLSX)示例 — 通过 URL(XLSX)
curl -X POST https://ext-api.oneskyai.net/v1/upload \
-H "x-api-key: osk_xxx" \
-H "Content-Type: application/json" \
-d '{
"fileUrl": "https://example.com/file.xlsx",
"projectId": "recGItPC9oapMIyyX",
"sourceLanguage": "en",
"targetLanguages": "zh-CN,ja",
"columnsSchema": { "en": "A" },
"sheetNames": ["Sheet1"]
}'
Source-only mapping (above) is the typical MT case — no target column,
MT generates the translations. To import pre-translated text, add the target column(s), e.g.
"columnsSchema": { "en": "A", "zh-CN": "B" }, and optionally "keyCol": "D".
仅映射源语言(如上)是常见的 MT 场景——不填目标列,由 MT 生成译文。如需导入预翻译文本,
请加上目标列,例如 "columnsSchema": { "en": "A", "zh-CN": "B" },并可选填 "keyCol": "D"。
{ "jobId": "20260618153243-8528" }
400 — Language pair not allowed400 — 语言对不被允许
{ "error": "Language pair(s) not supported: en>fr" }
Each source → target pair must be in your organization's allowed pairs (configured by OneSky). This is separate from the project auto-MT check below — a pair can be allowed for your account yet still be rejected if the project itself does not support MT for it. When your organization configured no pairs, this check is skipped.
每个源 → 目标语言对都必须在你组织的允许语言对内(由 OneSky 配置)。这与下方的项目自动 MT 校验是两回事——某语言对可能在你账号允许范围内,但若项目本身不支持该语言对的 MT,仍会被拒绝。若你的组织未配置任何语言对,则跳过此校验。
400 — Project not found400 — 项目未找到{ "error": "Project not found: rectMWcKtHHymDygX" }
400 — Auto-MT not supported for language pair400 — 该语言对不支持自动 MT
{ "error": "MT not support for en to ja" }
Every upload is an auto-MT job, and auto-MT support is project-specific. The request is rejected up front if the resolved project does not support machine translation for a requested source → target pair.
每次上传都是自动 MT 任务,而自动 MT 的支持范围因项目而异。若所解析的项目不支持某个 源 → 目标语言对的机器翻译,请求会被提前拒绝。
403 — Project not accessible403 — 无项目权限{ "error": "projectId is not accessible" }
413 — File too large413 — 文件过大
{ "error": "File too large. Max 30MB for binary upload. Use fileUrl for larger files." }
Check job status查询任务状态
Polls the automation job returned by POST /upload. Poll roughly every
5 seconds until status is a terminal value.
轮询 POST /upload 返回的自动化任务。约每 5 秒轮询一次,直到 status
变为终态。
| Query param | Required | Description |
|---|---|---|
jobId | required | The jobId returned from POST /upload. |
| 查询参数 | 必填 | 说明 |
|---|---|---|
jobId | 必填 | POST /upload 返回的 jobId。 |
files array appears
only when the job is Done and the export files are ready. If the job is
otherwise complete but exports are still generating, the aggregate status is
reported as Processing — keep polling.files 数组仅在任务为
Done 且导出文件就绪时出现。如果任务其余部分已完成但导出仍在生成中,聚合
status 会显示为 Processing——请继续轮询。serverTime field (ISO 8601 UTC, e.g. 2026-06-24T08:15:30.123Z) set to the
moment the server produced the response. While a job stays in Processing the rest of
the payload may look unchanged — a moving serverTime confirms the response is fresh,
not cached.serverTime
字段(ISO 8601 UTC,例如 2026-06-24T08:15:30.123Z),即服务器生成该响应的时刻。当任务长时间
停留在 Processing 时,其余字段看起来可能没有变化——不断变化的 serverTime
可确认响应是实时的,而非缓存。errorMessage field only when that language's status is
Failed. It describes why that language failed (e.g. MT is not supported for the language
pair). The field is omitted for all non-failed languages.status 为
Failed 时,该条目才会包含 errorMessage 字段,用于说明该语言失败的原因(例如该语言
对不支持机器翻译)。非失败的语言不会返回该字段。{
"jobId": "20260618153243-8528",
"status": "Done",
"languages": [
{ "sourceLanguage": "en", "targetLanguage": "zh-cn", "status": "Done" }
],
"files": [
"https://file.oneskyai.net/mtpe-export/f02cd3b9-.../merge-en.xliff"
],
"serverTime": "2026-06-24T08:15:30.123Z"
}
200 — Processing200 — Processing
{
"jobId": "20260618153243-8528",
"status": "Processing",
"languages": [
{ "sourceLanguage": "en", "targetLanguage": "zh-cn", "status": "Done" },
{ "sourceLanguage": "en", "targetLanguage": "ja", "status": "Processing" }
],
"serverTime": "2026-06-24T08:15:30.123Z"
}
200 — Failed (per-language error)200 — Failed(分语言错误)
{
"jobId": "20260618153243-8528",
"status": "Failed",
"languages": [
{ "sourceLanguage": "en", "targetLanguage": "zh-cn", "status": "Done" },
{ "sourceLanguage": "en", "targetLanguage": "ja", "status": "Failed",
"errorMessage": "MT is not supported for this language pair" }
],
"serverTime": "2026-06-24T08:15:30.123Z"
}
404 — Job not found404 — 找不到任务
{ "error": "Job not found" }
Job statuses任务状态
Each per-language task and the aggregate job carry one of these statuses:
每个分语言任务以及聚合任务都会是以下状态之一:
| Status | Terminal? | Meaning |
|---|---|---|
Pending | no | Queued, not started. |
Processing | no | In progress (or exports still generating). |
Done | yes | Completed; files available. |
Failed | yes | A step failed; the job will not complete. |
Stopped | yes | Manually stopped. |
| 状态 | 终态? | 含义 |
|---|---|---|
Pending | 否 | 已排队,尚未开始。 |
Processing | 否 | 处理中(或导出仍在生成)。 |
Done | 是 | 已完成;files 可用。 |
Failed | 是 | 某步骤失败;任务无法完成。 |
Stopped | 是 | 已手动停止。 |
The aggregate status is derived from all per-language tasks: Stopped if any
is stopped, else Failed if any failed, else Processing if any is still
running, else Done when all are done.
聚合 status 由所有分语言任务推导:任一为 Stopped 则为 Stopped;
否则任一为 Failed 则为 Failed;否则任一仍在运行则为 Processing;
全部完成则为 Done。
Error reference错误参考
Authentication (all endpoints)身份验证(所有端点)
| Status | Body | Cause |
|---|---|---|
| 401 | { "message": "Unauthorized" } | Missing / invalid / disabled API key. |
| 403 | { "message": "Forbidden" } | Request did not reach the API through the official host. |
| 500 | { "message": "Internal server error" } | Server misconfiguration / account lookup failure. |
| 状态 | 响应体 | 原因 |
|---|---|---|
| 401 | { "message": "Unauthorized" } | 缺失 / 无效 / 已禁用的 API key。 |
| 403 | { "message": "Forbidden" } | 请求未通过官方主机到达 API。 |
| 500 | { "message": "Internal server error" } | 服务器配置错误 / 账号查询失败。 |
POST /upload
| Status | Example error |
|---|---|
| 400 | projectId is required · Either file (binary) or fileUrl is required · Unsupported file type. Must be .xliff, .xlf, .xlsx, .docx, or .pptx · XLIFF file has no translation units · Language pair(s) not supported: <source>><target> · Project not found: <projectId> · MT not support for <source> to <target> |
| 400 xlsx | sourceLanguage is required for xlsx files · targetLanguages is required for xlsx files · At least one targetLanguage is required · columnsSchema is required for xlsx files, e.g. { "en": "A", "cn": "B" } · columnsSchema must be valid JSON, e.g. { "en": "A", "cn": "B" } · columnsSchema must contain a valid column letter for source language '<x>' · columnsSchema column for target language '<x>' must be a column letter (e.g. "B") · sheetNames is required for xlsx files, e.g. ["Sheet1"] · keyCol must be a column letter (e.g. "A"), got '<x>' |
| 403 | projectId is not accessible |
| 413 | File too large. Max 30MB for binary upload. Use fileUrl for larger files. |
| 状态 | error 示例 |
|---|---|
| 400 | projectId is required · Either file (binary) or fileUrl is required · Unsupported file type. Must be .xliff, .xlf, .xlsx, .docx, or .pptx · XLIFF file has no translation units · Language pair(s) not supported: <source>><target> · Project not found: <projectId> · MT not support for <source> to <target> |
| 400 xlsx | sourceLanguage is required for xlsx files · targetLanguages is required for xlsx files · At least one targetLanguage is required · columnsSchema is required for xlsx files, e.g. { "en": "A", "cn": "B" } · columnsSchema must be valid JSON, e.g. { "en": "A", "cn": "B" } · columnsSchema must contain a valid column letter for source language '<x>' · columnsSchema column for target language '<x>' must be a column letter (e.g. "B") · sheetNames is required for xlsx files, e.g. ["Sheet1"] · keyCol must be a column letter (e.g. "A"), got '<x>' |
| 403 | projectId is not accessible |
| 413 | File too large. Max 30MB for binary upload. Use fileUrl for larger files. |
GET /jobs/status
| Status | Example error |
|---|---|
| 400 | jobId query parameter is required |
| 403 | Forbidden (job's project is out of your scope) |
| 404 | Job not found |
| 500 | Failed to get job status |
| 状态 | error 示例 |
|---|---|
| 400 | jobId query parameter is required |
| 403 | Forbidden(任务的项目不在你的权限范围内) |
| 404 | Job not found |
| 500 | Failed to get job status |