What we doPricing
Login
Language operations API

Run translation inside the systems you already have.

Your CMS, your repository, your PIM — content goes in as segments with your own identifiers, and comes back translated against the terminology and style rules your company has already approved. Held server-side and applied to every call, not attached to each request. One project can route one language through a machine and the next through a human, and you are told when either finishes.

TextUnited · API
POST/segments/projects

customId: "catalogue-2026.08"

taskId: "release-notes"

targetLanguages: ["de-AT", "pl-PL"]

segments: 12,400

Translation in progress6 languages

The shape of the integration

Four facts, so you can decide in thirty seconds whether to keep reading.

Segments, not documentsPOST /segments/projects takes an array of segments and an array of target languages. Plain text or HTML, so markup from a CMS survives the round trip. Content in a database, a PIM or a repository goes in as it is held.
Your identifiers throughoutSet customId on the project and on every segment, then use it for every subsequent call — read, pull segments, check progress, comment, delete. You never store an ID of ours.
taskId scopes the updateSend what changed and the project updates in place rather than being recreated — which is what makes the second run cost less than the first.
One header, three schemesBasic with company ID and API key, or a bearer JWT, chosen per request from the Authorization header. Which company you are is read from the credential, never from the request.

Context travels with the segment, not around it.

Notes attach to a segment, and can be overridden per target language; so the instruction the German translator needs is not the one the Polish translator gets. Comments work the same way: on a segment, in one language, or in all of them, addressable by your own segment ID. The character limit, the screenshot reference, the note that this string appears on a button reaches the person doing the work instead of sitting in the ticket that triggered the job.

jsonjson
Authorization: Basic <companyId:apiKey>

{
  "customId": "catalogue-2026.08",
  "name": "Product catalogue — August release",
  "taskId": "release-notes",
  "sourceLanguageCode": "en-US",
  "domainId": 7,
  "endDateUtc": "2026-08-28T17:00:00Z",
  "eventUrl": "https://your-system/hooks/textunited",
  "targetLanguages": [
    { "targetLanguageCode": "de-AT",
      "serviceTranslation": true, "serviceProofreading": true,
      "styleGuideId": 412 },
    { "targetLanguageCode": "pl-PL",
      "serviceAutomaticTranslation": true, "serviceScoring": true }
  ],
  "segments": [
    { "customId": "sku-4471.name",
      "content": "Telescopic mast, 12 m",
      "notes": "Product title — 40 character limit" },
    { "customId": "sku-4471.desc",
      "content": "<p>Rated to <b>12 m</b> working height.</p>" }
  ]
}

That single call is the integration. Everything after it is your own customId and a webhook.

What this usually gets wired to.

  • A repository through CI, so strings are translated on merge and localized builds ship with the release.
  • A headless CMS, so one editorial action publishes in every market instead of in one and a backlog.
  • Documentation in Markdown, rebuilt in every language with each release rather than once a year.
  • A product catalogue from a PIM, refreshed each cycle rather than re-exported whole.

The smallest possible first step

You can call it before you commit to any of this.

POST /segments/Translation takes segments and target languages and returns the translations in the response. No project is created, nothing is scheduled, nothing is persisted — but it runs against your account, so approved terminology and style rules are already applied.

That makes it the honest way to evaluate us: point it at a hundred of your own strings, in your own domain, and compare the output to whatever you are using now.

And when you do want both, you do not have to choose. Set instantTranslation on a real project and a first pass comes back immediately while the human work continues behind it.

What the segments run against

Any model can translate. None of them can know what your company already decided.

It does not know which of three defensible terms your company uses, that legal rejected one of them for a market, or that this string has been through review twice already.

Segments posted here run against the record your organisation has accumulated: approved terminology, memory of what people have already confirmed, and style rules that exist as configuration rather than a PDF somebody was meant to read.

Both terminology and style are applied while the translation is produced — not checked against it afterwards, and not re-sent with every request. Which is also why they hold when you change model.

Neither is a flat list. Terminology is grouped into domains you define — the vocabulary of your service manuals is not the vocabulary of your marketing site, and a term that is correct in one can be wrong in the other. Style guides sit one level lower again, selected per target language, because the register your German market signed off on is not automatically the one your Japanese market did.

So there are parameters, but they are pointers: a domainId on the project, a styleGuideId on each target language. What they point at (the approved terms, the rejected ones, the rules) stays on your account. You are naming which body of decisions governs this content, not shipping it with the request and hoping the model reads all of it.

Every decision is stored at the level where it was made — company, domain, language, segment. A request points at them. It does not carry them.

Omit the domain and nothing lapses. Your account-wide terminology is still enforced. The domain narrows which set governs a project; it is not the switch that turns governance on. An integration written in a hurry, by someone who has since left, does not quietly stop applying the terms your company approved.

For structured content that distinction is not aesthetic. One attribute rendered two ways across five hundred products is not a quality problem; it is a filter that stops matching.

Set per language, not per integration

Not every language deserves the same money.

Most integrations force one answer for the whole payload: everything machine-translated, or everything routed to people. That is rarely what the content deserves.

The service is chosen on each target language inside the same project, in the same request — so the decision is content strategy rather than an architectural constraint.

de-AT

Human, then proofread

The market that reads your manuals closely: translation and proofreading against the style guide legal approved.

pl-PL

Automatic, and scored

Volume that has to exist in the language but does not need a person on every string.

fr-FR

Adaptive, managed by us

Where the volume is real and the team is not: adaptive translation against your record, run as a managed project.

You can also change your mind per release. The methodology lives on the target language of a project, not in your integration code — so moving a market from machine to human is a field in the next request, not a sprint.

And a third answer, between the two: let the score decide.

Set serviceScoring on a target language and every machine-translated segment gets a quality estimate. The threshold beneath which a segment is routed to a human for revision is configured rather than passed — on the account, per domain, and per language pair — so the call says score this, and your settings say how good is good enough, at whatever level you actually made that decision. Above the line, the segment passes. Below it, a person sees it before anyone else does.

That is the option most pipelines do not have, and it is usually the one that pays. The choice stops being review everything or review nothing — a decision made per language, in advance, on a guess — and becomes review what measurably needs it, on a proportion you can watch. Raise the bar for the domain that carries liability and lower it for the internal knowledge base; raise it again for the language pair your machine translation is weakest in. Your risk tolerance stops being a policy nobody reads and becomes a number that decides who touches the segment.

Where you want people on it, the people can be yours.

team takes usernames with roles attached (project manager, translator, proofreader, in-country reviewer) and rates and currency where they apply. A project created by an API call arrives with its team already assigned, so nobody has to open the interface to hand out work that the calling system already knew about.

Where those people are freelancers, the costing is done for you. Rates against the volume actually assigned, in the project currency, calculated the same way whether the job was created by a person or by an HTTP request — so an automated pipeline does not turn into a spreadsheet somebody reconciles at month end.

How you know where it is

Translation comes back in pieces, and the pieces improve.

Creating a project returns an acknowledgment rather than a finished translation — the work continues behind the response, because a request that waited for four hundred segments to be proofread would be a request that timed out. But that is not the same as waiting for the end. Where a language is machine-translated, the translation exists almost immediately. Where people are involved, segments are upgraded one at a time as they are translated and reviewed, in the same project, under the same IDs you sent.

So there is no single moment when a project is finished and you go and fetch it. There is a stream of segments moving up through statuses, and you decide which status you are willing to publish from. Take the automatic output today for an internal preview or a low-stakes market, and pick up the proofread versions of those same strings as they land — same project, same customId, same call with a different filter.

Set eventUrl on the project and we call you when segments or settings change, so your side pulls the corrected version rather than discovering it later. No polling loop, no cron job that runs every fifteen minutes and is still running in 2031. If you would rather ask, GET /segments/projects/{id}/progress returns a single overall percentage plus a breakdown per task and per target language — which is the number that goes on your dashboard without you computing it.

jsonjson
[
  {
    "source": { "customId": "sku-4471.name",
                "content": "Telescopic mast, 12 m" },
    "translations": [
      { "languageCode": "de-AT",
        "content": "Teleskopmast, 12 m",
        "status": "proofread",
        "comments": [ ... ] }
    ]
  }
]

The status filter is the useful part. Ask only for what is proofread and you can publish continuously without waiting for the slowest language in the release.

Every segment sits at one of six statuses, and they are not synonyms.

StatusMeaning
untranslatedNo translation exists yet.
draftSomeone has started. Not a state to publish from.
automaticMachine output. No person has looked at it.
pretranslatedFilled from your translation memory.
translatedA person produced it.
proofreadA second person checked it. Safe to publish.

Machine output and proofread output are both "finished." Only one of them is safe to publish.

When it comes back wrong

A project created by API is the same object as one created by hand.

Which means the failure path is not an error code and a shrug. Your own translators and reviewers can be assigned to a project the API created, they see it where they see everything else, and what they change goes back into the record rather than into a response body and out of existence.

The correction path runs in both directions. Your system can post a comment onto a specific segment — by your own segment ID, in one target language or in all of them — so a bug report from a market lands on the string it concerns rather than in an email. What comes back on that segment comes back with its comments attached.

That is the part that is hard to build rather than merely tedious. Posting content to a model is a week. A pipeline whose human step is still being completed two years later is a different problem, and it is usually the one that decides whether an integration survives its first year.

Security and legal

What security and legal will ask before anyone writes code.

SOC 2 compliant, GDPR ready

AES-256 encryption at rest and in transit.

Hosted on Microsoft Azure

Your data stays in the region you select.

Isolated per tenant

Your language data is never used to train anything outside your account.

Granular RBAC and audit trails

Who did what, to which segment, when.

Scope is not a parameterWhich company you are is read from the credential, never from the request. Every project and segment lookup is filtered by it server-side. There is no field an integration can get wrong, or a curious engineer can change, that returns another tenant's content.
Failures come with a handleA rejected request returns the business reason in plain text. An unexpected one returns an error signature — a GUID recorded against the server-side log. Quote it to support and the exact request is found, without you reproducing anything or sending us your content.

The whole surface

Twelve endpoints. You will use four.

This is not a platform you have to learn. Create, update, read back, check progress — the rest exists for the cases you have not hit yet. Paths shown against the segments service; every one that takes an {id} has a custom/{customId} twin.

MethodEndpointPurpose
POST/segments/projectsCreate a project from segments and target languages. Returns on acceptance; preparation continues in the background.
PUT/segments/projectsUpdate in place — identified by the id or customId in the body, not the path. appendContent adds to a task rather than replacing it.
GET/segments/projectsEvery segment project in your company.
GET/segments/projects/{id}One project and its settings. Or /projects/custom/{customId}.
GET/segments/projects/{id}/segmentsSource segments with their translations. Filter by ?status= and ?taskId= to take only what is finished.
GET/segments/projects/{id}/progressOverall percentage, plus a breakdown per task and per target language.
POST/segments/projects/{id}/segments/commentsComment on a segment — one target language, or all of them. Addressable by your segment customId.
POST/segments/TranslationInstant translation with no project created and nothing persisted. Segments in translations back in the same response.
DELETE/segments/projects/{id}Remove a project. Also by customId.

Interactive schema is served from the service itself, so the contract you test against is the one that is deployed rather than a document that drifted from it. Every request accepts Basic or bearer credentials on the same path.

Start with the reference

Read it, then a short call about what triggers what.

Most integrations are settled in one conversation: which event on your side creates a project, what happens when quality does not hold, and who needs to know. That is shorter than the code.

Not a new productThese are the endpoints TextUnited has run on internally for more than ten years — the same interface behind the web application our own customers have been working in that whole time. What changed is that we are opening them directly to clients. You are integrating against something load-bearing, not against a beta that was written to have an API story.
No separate API priceAPI access is part of the OnePlatform plan, and it consumes the word allowance in your subscription exactly as translating a document through the interface does. The same words cost the same whether a person uploads them or your CMS posts them. There is no per-call charge to model and no second contract to negotiate.

Before the technical call

FAQs

Do we have to send files?

No. The API takes segments as objects with target languages attached to the project. Content held in a database, a PIM or a repository goes in as it is held.

Do we have to store your IDs?

No. Set your own `customId` on the project and on each segment, then use them for every subsequent call.

What does the second run cost?

Less, because `taskId` determines what a request updates. Send what changed and the project updates in place.

What does API access cost?

Nothing on top of your plan. API access is included in OnePlatform and consumes the same word allowance as translating through the interface.

How long has this been running?

More than ten years, internally. These are the endpoints the TextUnited web application itself is built on.

How do we authenticate?

Basic authentication with your company ID and API key, or a JWT bearer token, selected from the `Authorization` header.

Does the response contain the translations?

For `POST /segments/Translation`, yes — inline. For a project, translations arrive progressively afterwards.

How do we know when a language is finished?

Use the `eventUrl` webhook or `GET /segments/projects/{id}/progress` for progress per task and language.

Can different languages take different routes?

Yes. Machine, adaptive, human, proofreading, scoring and managed service are each set on the individual target language.

How are language variants handled?

`de-DE` and `de-AT` can run as separate targets, each with its own terminology, style guide and reviewer.

Can segments contain HTML?

Yes. Segment content is plain text or HTML, so markup from a CMS or documentation build survives the round trip.

Do we have to pass our glossary with every request?

No. The request names a `domainId` and a `styleGuideId`; the terms and rules stay on your account.

Can our own translators work on projects the API creates?

Yes. It is the same project object, and the same people can be assigned to it.

Close

The integration is small. What it connects to is not.

Posting content to a model and getting content back was never the hard part, and you already know that. Read the reference, and bring the case where it stops being simple.