guides

Bilingual file round trip

Export one work unit as a bilingual XLIFF file, change its translations in your own system (for example with machine translation or an AI review), and import the file back into the same work unit.

A work unit is one file in one target language at one workflow step. The same file at the next step is a different work unit, with its own segments.

1. Find the work unit

2. Download the XLIFF

Download Work Unit Bilingual File returns the work unit's XLIFF in the response, with no job to wait for:

curl -OJ "https://app.wxrks.com/api/v3/project/$PROJECT_UUID/translation-kit-job/work-unit/$WORK_UNIT_UUID/bilingual" \
  -H "X-AUTH-TOKEN: $WXRKS_TOKEN"

-OJ saves the file under the name wxrks gives it. It is the same XLIFF 1.2 file an export kit holds for the work unit. Every <trans-unit> carries a bwx:ts-id attribute: the id of the segment in wxrks, which the import uses to find the segment again. It also carries the segment's status, bwx:locked and bwx:confirmed (yes or no), independent of each other: a segment can be locked without being confirmed, for example when the lock comes from the original file.

<trans-unit id="..." bwx:ts-id="9b0c..." bwx:locked="no" bwx:confirmed="yes" xml:space="preserve">
  <source xml:lang="en-US">Planning worksheet</source>
  <target xml:lang="fr-CA">Feuille de planification</target>
  <note from="Ana Souza" bwx:date="2026-10-19T14:02:11Z">Keep the product name in English.</note>
</trans-unit>

Work units with more than 20,000 segments are refused with 413. Export those with a job (step 3).

3. Large work units, or many at once: export kits

Call Request Export Project:

{
  "workUnitUuids": ["<work unit uuid>"],
  "locKitTypeJob": "XLIFF"
}

Call Check Translation Kit Job Status with the job id every few seconds.

The ZIP holds one XLIFF file per exported work unit, the same file step 2 returns.

4. Change the translations

5. Upload and import the edited file

Import File to Work Unit uploads the file and starts the import in one call. Send it as multipart/form-data, with the file in file:

curl -X POST "https://app.wxrks.com/api/v3/project/$PROJECT_UUID/translation-kit-job/work-unit/$WORK_UNIT_UUID/import" \
  -H "X-AUTH-TOKEN: $WXRKS_TOKEN" \
  -F 'file=@homepage_de-DE.xlf' \
  -F 'importType=XLIFF' \
  -F 'confirmOnlyChangeSegments=true'

The file name needs an extension wxrks supports, such as .xlf or .xliff; an XLSX import needs an .xlsx file. The answer is the import: keep its id for step 7.

Uploading the file separately

When the file has to be uploaded from somewhere else, for example a browser, upload it first and import it in a second call:

  1. Call Create Import Kit Resource with the file name, for example {"name": "homepage_de-DE.xlf"}. Keep the resource uuid from the answer.
  2. Call Get Import Kit Upload URL with that resource uuid. The answer has an upload url, the headers to send with it, and urlExpiresAt.
  3. Send the file with a PUT to that url within 60 minutes (before urlExpiresAt), with every header listed in headers. The URL points straight to storage, so do not send X-AUTH-TOKEN.
curl -X PUT "$UPLOAD_URL" \
  -H 'x-amz-server-side-encryption: aws:kms' \
  -H "x-amz-server-side-encryption-aws-kms-key-id: $KMS_KEY" \
  --data-binary @homepage_de-DE.xlf
  1. Call Import Kit to Work Unit with the work unit and the resource, and the parameters of step 6 as JSON, for example {"importType": "XLIFF", "confirmOnlyChangeSegments": true}. The answer is the import.

A 200 answer to the PUT means the file is stored. The expiryDate field of the upload URL answer does not tell when the URL expires: urlExpiresAt does.

6. Choose what the import writes

Both import calls take the same parameters. The two confirmation flags decide what is written and confirmed; both default to false.

confirmOnlyChangeSegmentsconfirmAllNotEmptySegments writtenConfirmation
falsefalseevery segment with a non-empty targetsegments whose text changed become unconfirmed
truefalseonly segments whose text changedchanged segments are confirmed
falsetrueevery segment with a non-empty targetall of them are confirmed
truetruesame as confirmOnlyChangeSegments alone

Leave both false when a person should review your changes in wxrks. Use confirmOnlyChangeSegments when your changes are final.

Whatever the flags:

Status and comments from the file

With applyStatusFromFile: true (XLIFF only), the file also decides each segment's status and adds its notes as comments, so the same file can be exported, changed and imported back with its locks, confirmations and comments:

The import's segmentsUpdated counts the segments whose text or status changed.

7. Wait for the import

The import runs in the background. Both import calls answer right away with the import:

{
  "id": "6f1c2b0e-8a47-4f3e-9d61-2c5b7a9e0d14",
  "workUnitId": "…",
  "importType": "XLIFF",
  "status": "STARTED",
  "creationDate": 1791900000000
}

Call Get Work Unit Import with that id every few seconds until status is IMPORTED or ERROR. Once it has ended, the import reports how many segments the file had (segmentsInFile), how many it wrote (segmentsUpdated) and confirmed (segmentsConfirmed), and how many it skipped because they were locked (segmentsLocked) or had no bwx:ts-id (segmentsWithoutId).

When status is ERROR, error says why:

errorMeaning
WORK_UNIT_READ_ONLYThe work unit cannot be written: for example its task was cancelled, or the previous workflow step is still open.
WRONG_WORK_UNITThe file was exported from another work unit.
FILE_UNREADABLEThe file could not be read as the importType given, or it names no work unit: it is not a file exported from wxrks.
NO_SEGMENTSThe file has no segments.
TARGET_LANGUAGE_MISMATCHThe file's target language is not the work unit's.
NO_SEGMENT_IDSNo segment in the file has a bwx:ts-id.
FAILEDAn unexpected error.

A file that writes no segment, for example an unchanged file imported with confirmOnlyChangeSegments, the same file sent again, or a file whose segments are all locked, ends IMPORTED with segmentsUpdated 0. Older imports may still show NOTHING_UPDATED for that case.

One import runs at a time in a work unit. While one runs, another import into the same work unit is rejected with 409: wait for the running import to end, then send yours again.

Check Work Unit Import Status still reports the latest import of a work unit, for integrations written before imports had an id.

Many work units at once

To import several work units in one call, upload a ZIP of their XLIFF files as one resource (step 5), then call Bulk Import Kit with importType, the same flags, and optionally workUnitUuids to limit the import to some of them. It returns a job you follow with Check Translation Kit Job Status. The job does not report a failure of a single work unit: check each one with Check Work Unit Import Status.