Skip to main content
Build a plugin that sends source content from a third-party system into Phrase TMS (Translation Management System) for localization, tracks progress, and pulls finished translations back. A TMS plugin is software that lives in a third-party system and connects it to Phrase TMS. It sends source content for localization, monitors translation progress, and retrieves completed translations into the source system.
Looking to translate app strings or software copy instead? See the Phrase Strings guides. This guide covers Phrase TMS plugins only.

Quickstart

The fastest way to confirm your plugin can reach Phrase TMS is to authenticate and list project templates. A 200 response means your token and base URLs are correct, before you build anything specific to your integration. Set your base URLs once and reuse them:
Exchange your API token for a short-lived access token:
Call one read-only endpoint to confirm the connection:
A 200 response with a list of templates confirms your plugin can reach Phrase TMS. The rest of this guide builds the full plugin flow on top of that.

Prerequisites

Do not hardcode EU endpoints unless your tenant runs on EU infrastructure.

Key concepts

These localization-specific terms appear throughout this guide. These file types are common in plugin integrations. For import parsing behavior, see file import settings.

Build the plugin

A production plugin usually follows this lifecycle:
  1. Select source content in the third-party system.
  2. Authenticate with Phrase Platform and call TMS APIs.
  3. Create a project from a project template.
  4. Create one or more jobs by uploading source content.
  5. Monitor job progress with webhooks, async status, or job-part polling.
  6. Export translated files when jobs complete.
  7. Set job status (for example DELIVERED) after a successful import.

1. Authenticate

Exchange your API token for a short-lived access token and send it as Authorization: Bearer <token>. Cache the token and refresh it before expiry, or on a single retry after a 401. Centralize refresh logic in production to avoid refresh storms under load.
If a call returns 401 after a fresh token, the token exchange itself is failing. Check the API token value and that grant_type is set to the token-exchange value. Do not retry in a tight loop; surface an actionable auth error instead.
Reference: Platform authentication, OAuth token endpoint.

2. Import content into TMS

  1. List project templates: GET /api2/v1/projectTemplates
  2. Create a project from a template: POST /api2/v2/projects/applyTemplate/{templateUid}
  3. Create a job in the project: POST /api2/v1/projects/{projectUid}/jobs
Persist templateUid, projectUid, job.uid, and any returned asyncRequest.id. You need these IDs in later steps.
A 404 on create-project usually means the templateUid is wrong or the token lacks access to that template. Verify the ID against the list-templates response and confirm the account scope before retrying.
Reference: List project templates, Create project from template, Create job.

Optional: expose content listing and download endpoints

If your integration uses TMS pull behavior from the third-party system:
  • Expose a list endpoint that returns selectable content.
  • Expose a download endpoint that returns encoded content for import.
  • Validate auth and return clear HTTP errors for invalid requests.
Keep endpoint responses deterministic. Stable IDs and filenames reduce duplicate imports and cut debugging time.

Optional: workflow extensions

If your lifecycle needs vendor automation and project manager workflow support, add these operations after job creation:
  • Assign providers from template: POST /api2/v1/projects/{projectUid}/applyTemplate/{templateUid}/assignProviders
  • Create analyses by providers: POST /api2/v1/analyses/byProviders
  • Notify assigned users: POST /api2/v1/projects/{projectUid}/jobs/notifyAssigned
Reference: Assign providers from template, Create analyses by providers, Notify assigned users.

3. Monitor job progress

Use this priority order:
  1. Webhooks (recommended for production). Configure webhook subscriptions for job, part, and async lifecycle events. Verify the sender token or header, store events idempotently, acknowledge quickly, and process asynchronously.
  2. Async request status polling. Poll GET /api2/v1/async/{asyncRequestId} for completion when the workflow uses async endpoints.
  3. Job-part polling fallback. Poll GET /api2/v1/projects/{projectUid}/jobs/{jobUid}/parts with backoff and jitter.

Callback pattern (alternative to polling)

Many async endpoints support a callbackUrl. The callback payload includes async request metadata and the action result.
  • Validate the sender, persist the event, and return 200 quickly.
  • If the callback URL is unreachable, Phrase retries after 2, 4, 8, 16, and 30 minutes, up to 10 failed retries.
  • Callback delivery counts as successful only when your endpoint returns HTTP 200.
If your endpoint is slow or returns a non-200 status, Phrase treats delivery as failed and stops retrying after 10 attempts. Acknowledge with 200 first, then process the event asynchronously so slow work never blocks delivery.
Reference: Get asynchronous request, Webhooks (support article).

Job status reference

4. Export translated content

  1. Start the async export: PUT /api2/v3/projects/{projectUid}/jobs/{jobUid}/targetFile
  2. Wait for completion via webhook, callback, or polling.
  3. Download the file once ready: GET /api2/v2/projects/{projectUid}/jobs/{jobUid}/downloadTargetFile/{asyncRequestId}
  4. Import the result into the third-party system.
  5. Set the terminal status: POST /api2/v1/projects/{projectUid}/jobs/{jobUid}/setStatus with requestedStatus: DELIVERED.
Alternatively, expose a secure endpoint to receive translated payloads pushed from TMS and run your import mapping there.
The asyncRequestId for download is single-use. If a download fails midway, do not replay the same ID. Start a new export and consume the new ID.
Reference: Download target file async, Download target file by async request, Edit job status.

Optional: live preview

Live preview renders a visual representation of content in the editor so translators understand context. Use it when text meaning depends on layout, styling, or surrounding content: CMS pages with rich formatting, product or marketing pages with embedded UI copy, or content with many short strings. Option A: HTML file localization. If your source can be represented as HTML, upload HTML directly as the translatable file. This is the simplest setup and gives immediate visual context, but it is not always feasible for CMS models with complex field structures and may need custom conversion logic. Option B: preview package via API. If HTML-as-source is not feasible, upload a preview package and reference it during job creation:
  1. Build a ZIP package with one HTML entry point plus relative assets.
  2. Upload the package: POST /api2/v1/projects/{projectUid}/jobPreviewPackage
  3. Use the returned preview file UID in job creation metadata (jobPreviewPackageFileUidRef in the Memsource header. See Plugin metadata).
Preview uploads fail on malformed ZIP structure, missing assets, incorrect relative paths, or oversized packages. Validate the ZIP and run package integrity checks in your continuous integration pipeline before upload, and regenerate the package when the content schema changes.
Reference: Upload job preview package, Create job.

Optional: continuous updates

For continuous localization, update source content on existing jobs and re-run the workflow:
  • Update the source: POST /api2/v1/projects/{projectUid}/jobs/source.
  • Monitor completion with callbacks, webhooks, or async polling.
  • Re-export translated output when the updates finish.
Reference: Update source.

Plugin metadata

Send plugin metadata in the Memsource header payload when creating jobs:
clientType is required and must be registered with Phrase. clientVersion and hostVersion are optional.

Rate limits

  • Phrase TMS documents an API limit of 6,000 requests per minute for logged-in users.
  • Async workflows can queue under load, so avoid aggressive status polling.
  • Webhooks reduce polling load and should be your primary production signal.
Use exponential backoff with jitter for retries on 429 and 5xx responses. Treat the support documentation limits as the source of truth for current values.
Reference: Handling API rate limits, Handling concurrent API limits, Phrase TMS limits (support).

Production hardening

Idempotency

Implement idempotency for all create and delivery operations: Build a deterministic operation key before each API call, store it in durable storage with the operation state, and return the stored result instead of replaying when a duplicate key appears.

Logging

Log these fields for every API call and lifecycle event:

Plugin variants

Operational hardening checklist

  • Retry transient errors (429, 5xx) with exponential backoff and jitter.
  • Avoid duplicate create and export actions with idempotency keys or dedupe logic.
  • Log correlation IDs, project and job IDs, endpoint, status, and latency.
  • Track success and error rates for create, monitor, and export operations.
  • Add alerts for repeated failures and webhook delivery issues.
  • Add fallback polling for missed webhook events.

Testing expectations

  • Happy path: create, monitor, export, DELIVERED.
  • Failure path: auth errors, validation errors, rate limits, service errors.
  • Resilience path: a missed webhook with polling fallback.
  • Update path (if enabled): source updates and a repeated export.

Error reference

Handle these HTTP status codes. For full payload schemas and the canonical error catalog, see the TMS API reference. Validate file type and size before upload, split very large submissions into smaller batches, and fail fast with actionable feedback when a file is unsupported. See file import settings and limits.

Endpoint reference

Every endpoint this guide calls, in one place. Paths are relative to TMS_BASE_URL, except the token endpoint, which uses PLATFORM_BASE_URL. For full request and response schemas, see the TMS API reference.

Troubleshooting and support

  • Check the Phrase status page first when calls fail unexpectedly across the board.
  • For Phrase TMS behavior, API access, or account questions, contact Phrase support.
  • For issues with an AI coding tool or agent you use to build the plugin, use that tool’s own support channel. Phrase support cannot debug third-party tools.

Next steps

Reference

Last updated: September 7, 2026. Track documentation changes in the changelog.