Story translations
Create or link language versions, inspect a translation group, and unlink a story without deleting it.
A translated article is another story with its own UUID and culture. Translations form a flat group: every member is related to every other member, and the story you started from has no special ownership over the group.
Choose the operation based on what already exists. Create and link a separately authored story when you already have translated content. Use the translation-copy endpoint when you want Prezly to start a language version from an existing story.
Choose credentials for the operation
| Operation | Personal token support |
|---|---|
| Read a story and its translation fields | stories:read. |
| Create a story in another language, then link it | stories:write for the writes. |
| Link or unlink existing stories | stories:write. |
Copy/auto-translate through POST /stories/{story_id}/translate | Not supported by personal tokens; use an integration API key. |
| Read saved translation suggestions | Not supported by personal tokens; use an integration API key and an account with the feature. |
Scopes do not override account or newsroom permissions. The current personal-token allowlist does not cover every story endpoint, even when the SDK exposes the corresponding method. See Authentication.
Inspect a story's language versions
Replace YOUR_STORY_UUID:
curl --fail-with-body --silent --show-error 'https://api.prezly.com/v2/stories/YOUR_STORY_UUID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Accept: application/json; content-format=v6'story.translations reports same-site translations. Cross-site translations are a separate, optional field: when your account has the feature, request include=cross_site_translations to retrieve the available members from other sites. Do not infer that an account has no other language versions merely because that optional field was not requested.
Within one site, a group can contain a culture only once. The same culture can occur in different sites in the group, for example an English version on a global site and an English version on a regional site. Cross-site operations require the cross_site_translations feature, sites in the same account, and the access required for those sites. Cross-site linking also requires live sites.
Link a translation you already have
If the translated text exists outside Prezly, create a story in the target site's configured culture, with its own translated content. If it is already in Prezly, keep that story's UUID. Both stories must contain content; do not link empty, uninitialized shells.
Replace YOUR_STORY_UUID with a member of the destination group and YOUR_TRANSLATION_UUID with the separate story you want to add:
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/stories/YOUR_STORY_UUID/translations' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json; content-format=v6' \
--data '{"story":"YOUR_TRANSLATION_UUID"}'The response is 200 with the path story under story, not a newly created copy. No content is translated or overwritten. Linking changes group membership, so all group members' language switchers can be affected. Linking two stories that are already in the same group succeeds without changing their membership again.
The referenced story must be standalone; this operation does not merge two existing groups. An existing group may need to be reorganized deliberately before linking. Link Story Translation describes conflicts and the accepted reference forms.
Start a language version by copying a story
This optional path requires an integration key. Load it into PREZLY_INTEGRATION_KEY using the same hidden-prompt approach used for PREZLY_API_TOKEN; keep it on the server or in your local shell. A personal token with stories:write still cannot call this endpoint.
Replace YOUR_STORY_UUID and choose a culture configured for the target site:
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/stories/YOUR_STORY_UUID/translate' \
--header "Authorization: Bearer $PREZLY_INTEGRATION_KEY" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json; content-format=v6' \
--data '{"culture":"fr","auto":false}'The endpoint returns 200 with story. If that culture already exists in the target site's group, the existing story is returned. Otherwise, the new story starts as a draft copied from the source and is linked into its group. With auto: false, the body has not been machine-translated: replace or edit its content before publishing it as a translation.
auto: true requests machine translation and requires access to that feature. If translation is unavailable or fails, the endpoint can fall back to copied source content. Do not treat the flag or HTTP success as proof the body was translated; review the returned text. Translation does not publish the new story. See Translate Story.
To fill copied content from an external HTML translation, import into the new story's UUID rather than creating another unrelated story.
Unlink without deleting
Use the UUID of the member you want to remove:
curl --fail-with-body --silent --show-error --request DELETE 'https://api.prezly.com/v2/stories/YOUR_STORY_UUID/translations/YOUR_TRANSLATION_UUID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Accept: application/json; content-format=v6'The response is 200 with the path story. This removes the selected story from the entire group, not just a private pairwise relationship. The remaining members stay grouped. A group of one is dissolved, so removing one story from a pair leaves two independent stories.
Passing the path story's own UUID as the member UUID removes that story from its group. No story content is deleted. A request for stories that are not translations of each other can return 404; do not interpret unlink as story deletion. Unlink Story Translation reference →
Use suggestions as candidates, not automatic links
With an integration key and access to the suggestions feature:
curl --fail-with-body --silent --show-error 'https://api.prezly.com/v2/stories/YOUR_STORY_UUID/translation-suggestions' \
--header "Authorization: Bearer $PREZLY_INTEGRATION_KEY" \
--header 'Accept: application/json'The response contains suggestions. It reads saved candidates; it does not generate new matches, translate text, or link stories. An empty array is a valid result. Similarity scores are not probabilities that two stories are translations. Review the content and culture before linking a candidate. See Translation Suggestions for feature requirements and response fields.
Resolve group conflicts explicitly
| Code or response | What to check |
|---|---|
409 story_already_translated | The referenced story already has other translations; linking does not merge groups. |
409 translation_group_not_accessible | The existing group is outside your available site access. Someone with access must resolve it. |
409 translation_culture_taken | Another member already has that culture in the same site. |
409 story_uninitialized | One of the stories has no initialized content. Fill it before linking. |
403 | Check personal-token endpoint support, feature access, and site permissions. |
404 | Check story identifiers and account access, or whether the stories still share a group for unlinking. |
Preserve the source-to-story mapping for each language in a migration. Review the resulting group after changes, and keep publication decisions separate from grouping and machine translation.