POST/v1/public/document-translator/jobs/{jobId}/finalize
translator:translaterequired scopeStep 3 of the presigned upload flow — call it after the PUT to `uploadUrl` succeeds. Confirms the object landed in storage, debits the prepaid credits tier price, and enqueues the translation; returns `202` with the job snapshot. A PUT that never landed answers `400`; an object that beat the `content-length-range` cap answers `413`. Ownership follows the §9 rule — only the key that minted the intent may finalize it. Requires scope `translator:translate`.
| Name | In | Required | Description |
|---|---|---|---|
| jobId | path | ✓ | The job id returned by `POST /jobs` (uuidv7).e.g. 019a2c3d-4e5f-7a9b-8c0d-1e2f3a4b5c6d |
application/json
{
"jobId": "019a2c3d-4e5f-7a9b-8c0d-1e2f3a4b5c6d",
"state": "uploading",
"pagesTotal": null,
"pagesDone": 0,
"source": "auto",
"target": "km",
"pdfUrl": null,
"error": null,
"createdAt": "2026-10-16T18:30:00+07:00",
"completedAt": null
}application/json
{
"error": "invalid_request",
"message": "The upload has not landed in storage yet — retry after the PUT completes.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c"
}application/json
{
"error": "missing_authorization",
"message": "Send `Authorization: Bearer <api-key>`.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c"
}application/json
{
"error": "scope_missing",
"message": "This key lacks the required scope.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c",
"requiredScope": "translator:read"
}application/json
{
"error": "job_not_found",
"message": "No such job.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c"
}application/json
{
"error": "payload_too_large",
"message": "File exceeds the 100 MiB limit.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c",
"maxBytes": 104857600,
"nextStep": "split_or_contact"
}application/json
{
"error": "rate_limited",
"message": "Rate limit exhausted — retry after the interval.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c",
"retryAfter": 42
}application/json
{
"error": "internal_error",
"message": "Something went wrong — retry shortly.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c"
}application/json
{
"error": "upstream_unavailable",
"message": "A required upstream is unavailable — retry shortly.",
"requestId": "trk_01HKA1B2C3D4E5F6G7H8J9K0M1",
"correlationId": "019a1b2c-3d4e-7f8a-9b0c-1d2e3f4a5b6c"
}