docs

Strings API

These endpoints power the dashboard's strings editor. They use the signed-in user's organization membership. A project build token or browser publishable key does not authorize string editing.

Authentication and scope

Send the dashboard session cookie to the API, subject to its configured origin policy. OWNER, ADMIN, EDITOR, and VIEWER can read. OWNER, ADMIN, and EDITOR can write when the project and organization are active. Unauthorized access uses 404 PROJECT_NOT_FOUND to avoid disclosing project existence.

All paths below start with /api/v1. :project is the project ID. :message is the string's database id returned by the list, not its stable key. :environment in the list accepts an environment ID or name. Writes affect project translation versions; they do not select a published environment release.

Method and pathPurpose
GET /projects/:project/environments/:environment/stringsList strings in the latest ready build with selected target translations and language statistics.
GET /projects/:project/strings/:messageRead source context, locations, translation history, glossary matches, and memory suggestions.
PUT /projects/:project/strings/:message/translations/:localeSave a validated human translation as a new accepted version.
POST /projects/:project/strings/bulk-reviewApply one decision to a selection of translation IDs, with per-item results.

List strings

Example request
GET /api/v1/projects/PROJECT_ID/environments/development/strings?locale=fr,de&status=review&limit=50
QueryContract
localeOptional comma-separated project target locale codes. Defaults to enabled target locales. Unknown codes, including the source locale, return 400 LOCALE_NOT_IN_PROJECT.
statusall (default), missing, review, rejected, or accepted. accepted requires acceptance in every selected locale; other status filters match at least one selected locale.
qCase-insensitive search in the stable key or source text. Trimmed; maximum 200 characters. It does not search target translations.
fileSource-location file filter; maximum 1,000 characters.
cursorOpaque pagination value from nextCursor. Keep the same scope and filters while paging.
limitInteger 1–200; defaults to 50.

The response contains:

FieldMeaning
stringsRows sorted by stable key. Each has id, key, sourceText, sourceLocale, placeholders, context, locations, and translations.
strings[].translationsMap from selected locale code to its latest translation view, or null when missing.
localesPer-locale totals: code, total, translated (accepted), needsReview, rejected, and missing. These are whole-build statistics, not counts for just the current page or search.
totalNumber of strings matching the selected filters before pagination.
manifestLatest ready build's id and createdAt, or null.
nextCursorCursor for the next page, or null.

With no ready build, the API returns an empty strings array, zero statistics, total: 0, manifest: null, and nextCursor: null.

A translation view includes id, text, status, version, origin, authorId, updatedAt, and outdated. outdated compares the version's source content hash to the current string. Status values include ACCEPTED, REVIEW_REQUIRED, and REJECTED. None of these fields identifies what is currently live.

Inspect a string

Example request
GET /api/v1/projects/PROJECT_ID/strings/MESSAGE_ID?environment=development

environment is optional and accepts a project environment ID or name. When a ready build exists in that environment, locations come from it; without that build, the current implementation can fall back to the string's latest recorded build location. Without the query, the latest recorded location is used. Translation history is project-wide rather than restricted to the chosen environment.

The response has:

  • string: source text, stable key, placeholders, context, hashes, and timestamps.
  • manifest and locations: recorded build context for the source string.
  • locales: project target locale codes and their statuses.
  • translations: versions grouped by locale, newest first. Each includes the translation view, approvalKind, jobId, validation, author, and review records with reviewer, decision, note, and replacement version ID.
  • glossary: active terms that match the source text, with target wording, locale, rule, case sensitivity, and notes.
  • suggestions: up to five translation-memory suggestions per target locale. A match of exact or source describes compatibility or matching normalized source; suggestions are not automatically accepted.

Save a human translation

Example request — replace IDs and use your session
PUT /api/v1/projects/PROJECT_ID/strings/MESSAGE_ID/translations/fr
Content-Type: application/json
Idempotency-Key: UNIQUE_KEY_FOR_THIS_EDIT

{
  "text": "Bienvenue, {name}",
  "expectedVersion": 3,
  "note": "Use the same greeting as the sign-in screen."
}

The sample assumes the source contains {name}. Use the actual source placeholders and latest version from the read response.

Body fieldContract
textRequired string, 1–20,000 characters. Must preserve source placeholders, ICU syntax, named rich slots, and applicable glossary rules.
expectedVersionOptional integer, 0 or greater. Send the latest version you read; use 0 when no version exists for this string and locale.
noteOptional trimmed note, maximum 2,000 characters. Recorded with the edit and, when applicable, its review.

The locale must be a target language added to the project. It cannot be the source locale. Saving creates a new ACCEPTED version with origin: HUMAN and approvalKind: human_edit; it records the author and audit event and updates translation memory. A pending or rejected predecessor receives an edit review; a pending predecessor leaves the review queue.

Concurrent edits

When expectedVersion differs from the latest stored version, the API returns 409 with code: STALE_TRANSLATION. No replacement version is saved for that stale attempt. Keep the draft, fetch the string again, compare the latest wording, then submit the resolved edit with the new version and a new idempotency key. Omitting expectedVersion omits this comparison; editor clients should send it.

Idempotency

Idempotency-Key is required. Retry the same logical edit with the same key and identical body after a transport failure. A key reused for different content returns 409 IDEMPOTENCY_CONFLICT. A successful replay returns the recorded translation, replay: true, and catalog: null; it does not create another version or rerun catalog preparation.

A normal success returns translation plus catalog containing ready, per-build results, and optional jobCatalogReady. A saved edit can return catalog.errorCode: CATALOG_REBUILD_FAILED with ready: false. The translation is still saved; inspect catalog state before trying to publish. Readiness depends on the other required strings too.

Structural problems return 422 VALIDATION_FAILED with details.issues. An extreme length ratio is a nonblocking warning stored with a human edit. Successful validation and acceptance do not publish a release or modify the contents of a published catalog.

Review a selection

Example request — translation IDs, not message IDs
POST /api/v1/projects/PROJECT_ID/strings/bulk-review
Content-Type: application/json
Idempotency-Key: UNIQUE_KEY_FOR_THIS_SELECTION

{
  "translationIds": ["TRANSLATION_ID_A", "TRANSLATION_ID_B"],
  "decision": "APPROVED",
  "note": "Checked against the checkout screen."
}
Body fieldContract
translationIdsRequired array of 1–200 nonempty translation IDs. Duplicate IDs are deduplicated.
decisionAPPROVED, REJECTED, or SOURCE_FALLBACK.
noteOptional string, maximum 2,000 characters.

Approval and source fallback create accepted replacement versions. Source fallback uses the original source text. Rejection marks the selected wording rejected. Approval validates the wording before accepting it. Each decision is recorded, and eligible catalogs are rebuilt after the batch. None of these decisions publishes a release.

The response contains results, summary: { succeeded, failed }, and catalogs. Each result includes id, ok, and status; success can include reviewId, replacementTranslationId, and replay, while failure includes code and message. Catalog results contain jobs and locales, and may include errorCode: CATALOG_REBUILD_FAILED.

The batch is not all-or-nothing. An HTTP success can contain failed items, including missing IDs, superseded versions, already accepted versions, validation failures, or concurrent write conflicts. Inspect every result and refresh failed rows. Use a new key for a changed selection or decision, and the same key for an unchanged retry.

For a single review, the dashboard also uses POST /api/v1/translations/:translation/review. Its body can carry APPROVED, REJECTED, EDITED, or SOURCE_FALLBACK; it also requires a session and an idempotency key. Use the PUT string endpoint for editor saves with expectedVersion.

Errors to handle

HTTP / codeRecovery
400 INVALID_STRINGS_QUERYCorrect locale, status, cursor, or limit filters.
400 IDEMPOTENCY_KEY_REQUIREDSupply a key for the logical write.
400 INVALID_TRANSLATION / INVALID_BULK_REVIEWCorrect the request body and size limits.
400 LOCALE_NOT_IN_PROJECTChoose a project target language.
404 PROJECT_NOT_FOUND / ENVIRONMENT_NOT_FOUND / STRING_NOT_FOUNDCheck the selected scope and membership; do not assume the resource exists.
409 STALE_TRANSLATIONReload current version, reconcile your draft, and submit with the current expected version.
409 IDEMPOTENCY_CONFLICTUse the original body for a retry or a new key for a new action.
Per-item 409 TRANSLATION_SUPERSEDED / TRANSLATION_ALREADY_ACCEPTEDRefresh the selection and review only current pending work.
422 VALIDATION_FAILED / per-item STRUCTURAL_VALIDATION_FAILEDRestore required placeholders, rich slots, ICU syntax, and glossary terms.

API errors include code, message, requestId, and optional details. Keep the code and request ID for diagnostics.

Did this page get you to a working result?

On this page

No Headings