Skip to content

Query Task Status

Synchronously query the current status and progress of a translation task. Designed for polling — this endpoint does not write to call logs, so high-frequency polling is safe (recommended interval ≥ 3s).

When to use

  • Integrators without callback_url or unable to receive external webhooks
  • Agents / command-line scripts that need to wait synchronously for completion
  • Manual diagnosis when a task appears stuck

If you can receive webhooks, prefer callbacks (see Create Translation Task · Callbacks) — they are more efficient and require no polling.

Endpoint

GET {BASE_URL}/api/open/v1/tasks/status

POST is also accepted (place task_id in the JSON body).

Auth Headers

Same as Create Translation Task:

HeaderValue
X-Loxily-AppKeyProject App Key
X-Loxily-TimestampUnix seconds (5-min window)
X-Loxily-SignMD5(timestamp + "" + appSecret) — GET has no body; the empty string participates in the signature

Query Params

ParamTypeRequiredDescription
task_idstringYesThe task_id returned when creating the task

Response

Success (HTTP 200):

json
{
  "success": true,
  "code": 0,
  "msg": "ok",
  "trace_id": "8a3f12ab-4d2a-9f51-7e2c6d8a9101",
  "data": {
    "task_id": "68a12cb7e1f9a88b4ea23c77",
    "name": "Q2 onboarding strings",
    "status": "running",
    "current_stage": "translate",
    "current_step": "translateBatch",
    "source_language": "zh-hans",
    "target_languages": ["en", "ja", "ko"],
    "strings_count": 512,
    "words_count": 512,
    "progress": { "rows_total": 1536, "rows_done": 612 },
    "jobs": [
      {
        "job_id": "translate_68a12cb7_...",
        "job_type": "TRANSLATE",
        "status": "RUNNING",
        "step": "translateBatch",
        "row_count": 1536,
        "error": null,
        "created_at": "2026-04-22T10:22:35.001Z",
        "updated_at": "2026-04-22T10:25:11.301Z"
      }
    ],
    "smart_optimize_status": "pending",
    "requires_confirmation": false,
    "is_completed": false,
    "is_failed": false,
    "failure_reason": null,
    "failure_code": null,
    "accepted_at": "2026-04-22T10:22:31.123Z",
    "updated_at": "2026-04-22T10:25:11.301Z"
  }
}

The 9 possible values of status

statusMeaningTypical current_stage
pendingTask accepted; backend has not started yetpending
importingBackend parsing inputs, generating CSV, uploading to GCS, triggering first workflowimport
scanningTB_SCAN (term scan) workflow in progresstb_scan
term_translatingNewly scanned terms are being auto-categorized and translated before entering the term base (only when auto_apply_terms=true and new terms were found)tb_translate
waiting_confirmationTB_SCAN finished; waiting for /tasks/confirm-terms (only when auto_apply_terms=false)tb_scan
runningTRANSLATE workflow in progress. See current_step table belowtranslate
optimizingSmart Optimization (TRANSLATE_QA) workflow in progress. Translations exist but low-score rows are being re-translated — wait for completed before exportingtranslate_qa
completedAll stages done, including Smart Optimization — call /export/ini to download resultsdone
failedA stage terminated unsuccessfully; see failure_reason / failure_codefailed

completed is double-gated

completed requires both the translation and Smart Optimization to reach a terminal state. During the window right after translation finishes — while the system is still deciding whether Smart Optimization is needed — status stays optimizing instead of leaking an early completed. Once you see completed, it is safe to publish / export immediately.

smart_optimize_status — Smart Optimization's own state

ValueMeaning
pendingOptimization decision not made yet (translation still running, or just finished and low-score rows are being counted)
runningSmart Optimization (TRANSLATE_QA) workflow in progress
completedSmart Optimization finished
skippedNo low-score rows; this task needs no optimization
failedSmart Optimization failed (does not affect the task's overall completed; translations remain usable, just unoptimized)
nullLegacy task created before this feature shipped

When status='completed', this field is guaranteed terminal (completed / skipped / failed).

Fully-automatic term pipeline with auto_apply_terms=true

With scan_terms=true + auto_apply_terms=true, newly scanned terms are automatically categorized, translated into all project target languages, and written to the term base — before the task translation starts, so the current task already benefits from the enforced term translations. If the term-translation stage fails, the pipeline degrades gracefully to "import source terms only and continue", so the task never gets stuck.

The 7 possible values of current_step (only when status='running')

The 7 sub-steps within the TRANSLATE workflow — matches the callback event names in Create Task docs:

stepstep_index
tmMatching1
tbMatching2
kbExtraction3
translateBatch4
lqaBatch5
translateEnhanceBatch6
aiScoringBatch7

progress field

FieldTypeDescription
rows_totalnumberTotal rows in the current stage (typically strings_count × target_languages.length)
rows_donenumberRows processed (sourced from the latest RUNNING job's detail.rows_processed)

Semantics of rows_done

Progress reflects only the current sub-step — it resets to 0 when a sub-step transitions. For an overall completion view, use current_step's step_index (1–7).

Extra fields on failure

When status='failed':

FieldDescription
failure_reasonHuman-readable error message
failure_codeInternal HTTP code (400 / 422 / 500 / 502, etc.)

Error Codes

codeMeaning
400Missing task_id
401Invalid signature / expired timestamp
403Task does not belong to this App Key (cross-project access)
404task_id not found
500Internal server error

Examples

cURL (GET)

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

TIMESTAMP=$(date +%s)
# GET has no body; empty string participates in the signature
SIGN=$(printf '%s' "${TIMESTAMP}${APP_SECRET}" | md5)

curl -s "${BASE_URL}/api/open/v1/tasks/status?task_id=${TASK_ID}" \
  -H "X-Loxily-AppKey: ${APP_KEY}" \
  -H "X-Loxily-Timestamp: ${TIMESTAMP}" \
  -H "X-Loxily-Sign: ${SIGN}"

Node.js — poll until done

javascript
import crypto from 'crypto';

async function waitForTask(taskId, { timeoutMs = 30 * 60 * 1000, intervalMs = 3000 } = {}) {
  const start = Date.now();
  while (Date.now() - start < timeoutMs) {
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const sign = crypto.createHash('md5')
      .update(`${timestamp}${process.env.LOXILY_APP_SECRET}`, 'utf8')
      .digest('hex');

    const resp = await fetch(
      `${process.env.LOXILY_BASE_URL}/api/open/v1/tasks/status?task_id=${taskId}`,
      {
        headers: {
          'X-Loxily-AppKey': process.env.LOXILY_APP_KEY,
          'X-Loxily-Timestamp': timestamp,
          'X-Loxily-Sign': sign,
        },
      },
    );
    const { data } = await resp.json();

    if (data.is_completed) return data;
    if (data.is_failed) throw new Error(`Task failed: ${data.failure_reason}`);

    await new Promise((r) => setTimeout(r, intervalMs));
  }
  throw new Error(`Polling timeout (${timeoutMs}ms)`);
}

const final = await waitForTask('68a12cb7e1f9a88b4ea23c77');
console.log('Done at stage', final.current_stage);

FAQ

Q: How is this different from the term_scan.completed / task.completed callbacks? Callbacks are pushed; this endpoint is pulled. Callbacks are real-time but require a public endpoint. Polling works in any environment — local scripts, Agent sandboxes, CLI tools. The data sources are identical.

Q: How do I get the translated content once a task is completed? Call /export/ini (or other export endpoints) to download results. This endpoint does not return translation content — it stays small for safe polling.

Q: Is there a rate limit? This endpoint does not write call logs and has no dedicated rate limit. We recommend polling no faster than once every 3 seconds — more frequent polling will not return results sooner.