Skip to content

Publish Translation Task

Promote a fully-translated task's strings to the project level — writing into translation_strings_aggregated (project-level aggregated strings) and tm_records_aggregated (TM index). Equivalent to the "Publish" button on the task detail page.

Highlights

  • Async: API returns job_id + execution_id + trace_id immediately; real publish runs in a GCP Workflow in the background
  • Both success and failure are delivered via callbacks: task.publish.completed / task.publish.failed
  • Pollable: environments that cannot receive webhooks can poll Query Publish Status with the job_id until a terminal state
  • No sub-step events: only terminal events are emitted
  • Independent trace_id: each publish is its own call + its own callback stream, disjoint from the original /tasks/create trace

When to call

Typical integration flow:

  1. POST /tasks/create → task enters translation
  2. Receive the task.completed callback (or poll task status until completed) → task strings are translated but not yet project-level (SDK / other APIs can't read them yet)
  3. Call this endpoint → triggers the PUBLISH_TASK workflow
  4. Receive task.publish.completed (or poll publish status until completed) → strings are now project-level; only then will /export/ini reflect this publish

Endpoint

POST {BASE_URL}/api/open/v1/tasks/publish

Authentication Headers

Identical to Create Translation Task.

Body

ParamTypeRequiredDescription
task_idstringYesTask to publish; must be an open-platform task under the same App Key
callback_urlstringNoPer-invocation callback URL override. Empty → use the callback_url registered with /tasks/create
callback_eventsstring[]NoSubscription whitelist: task.publish.completed / task.publish.failed. Empty → both

Source language is read from the task (task.source_languages[0]); not a parameter.

Target languages always use the task's full target_languages set; not a parameter. Subset selection and conflict resolution are driven by the task itself — this endpoint just publishes whatever is in the task.

Response (sync)

Success (HTTP 200):

json
{
  "success": true,
  "code": 0,
  "msg": "ok",
  "trace_id": "b4e82a1c...",
  "data": {
    "task_id": "68a12cb7e1f9a88b4ea23c77",
    "job_id": "publish_open_...",
    "accepted_at": "2026-04-23T09:15:22.117Z",
    "source_language": "zh-cn",
    "target_languages": ["en", "ja"]
  }
}
  • job_id: PUBLISH_TASK workflow's identifier
  • accepted_at: UTC time the server accepted the request
  • source_language: source language used (= task's source language)
  • target_languages: languages being published (= task's target_languages in full)

Callbacks

task.publish.completed (success)

Fired at workflow completion. detail carries stats (rows processed, success / fail counts, etc.).

json
{
  "event": "task.publish.completed",
  "task_id": "68a12cb7e1f9a88b4ea23c77",
  "project_id": "...",
  "trace_id": "b4e82a1c...",
  "delivery_id": "...",
  "timestamp": "2026-04-23T09:16:05.442Z",
  "status": "SUCCEEDED",
  "detail": {
    "message": "Publish task workflow completed successfully"
  },
  "error": null
}

task.publish.failed (failure)

json
{
  "event": "task.publish.failed",
  "task_id": "68a12cb7e1f9a88b4ea23c77",
  "trace_id": "b4e82a1c...",
  "status": "FAILED",
  "detail": {
    "error": "…backend error detail…"
  },
  "error": "…human-readable reason…"
}

Signing, retry schedule (4 inline attempts: immediate / 16s / 32s / 64s), and SSRF guard are identical to the /tasks/create callbacks.

Error Codes

codeDescription
400Invalid params (missing task_id / bad callback_url / callback_events has unknown event)
401Signature invalid / timestamp expired
403Task does not belong to this App Key
404Task not found
422Task has no source language configured / no target_languages
500Internal error (sync phase)

Failures in the async phase (workflow trigger / execution errors) do not flip the sync response's success: true — they are only reported via task.publish.failed.

Examples

bash
APP_KEY="5685414646a54423c891d87194d87f3f"
APP_SECRET="<your App Secret>"
TASK_ID="68a12cb7e1f9a88b4ea23c77"
BASE_URL="https://api.loxily.com"

TIMESTAMP=$(date +%s)
BODY='{"task_id":"'"${TASK_ID}"'"}'
SIGN=$(printf '%s' "${TIMESTAMP}${BODY}${APP_SECRET}" | md5)

curl -s -X POST "${BASE_URL}/api/open/v1/tasks/publish" \
  -H "Content-Type: application/json" \
  -H "X-Loxily-AppKey: ${APP_KEY}" \
  -H "X-Loxily-Timestamp: ${TIMESTAMP}" \
  -H "X-Loxily-Sign: ${SIGN}" \
  --data "${BODY}"

With a dedicated callback_url

bash
BODY='{
  "task_id": "68a12cb7e1f9a88b4ea23c77",
  "callback_url": "https://my-hooks.example.com/loxily/publish",
  "callback_events": ["task.publish.completed", "task.publish.failed"]
}'

Console Parity

  • The "Publish" button on the task detail page triggers the same GCP Workflow (WORKFLOW_PUBLISH, job_type=PUBLISH_TASK)
  • publish_type is fixed to simple in this API; if the task has publish conflicts (some strings already published by another task), the backend's default strategy (overwrite with latest) applies
  • For explicit conflict resolution (choosing which version to keep), use the console UI

Idempotency

There is no idempotency key. Calling the API multiple times on the same task launches independent PUBLISH_TASK workflows, each with its own job_id + trace_id. Subsequent publishes overwrite the previous result.

We recommend waiting for the previous task.publish.completed callback before triggering the next publish to avoid concurrent PUBLISH_TASK workflows.