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.