Skip to main content
A translation is a satellite row attached to an article that carries the article’s title, content, and content_plain in a different language. The primary article’s language field is the canonical one; every other language lives as a translation.

When to use translations vs separate articles

Use translations

The two pieces of content are the same article in different languages — same canonical slug, same category, same intent. Translations share the parent article’s id, slug, category_id, visibility, and lifecycle.

Use separate articles

The content diverges by audience — different examples for different regions, different policies per market, a fully localized site structure. Each gets its own id and its own lifecycle.
Translations cannot have their own status. They are live whenever the parent article is published, and are removed from the index whenever the parent is unpublished.

How indexing works

Each translation is embedded under its own language, separately from the primary body. A chatbot answering in Spanish retrieves Spanish embeddings; an English chatbot retrieves English. Image re-hosting runs on translations too — external images in a translation’s content are pulled into the org’s storage on write, the same as on the primary article.

The translation object

{
  "object": "article_translation",
  "id": "5d694e14-5440-4f5d-9e8a-7c3b2a1d0f9e",
  "article_id": "8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e",
  "language": "es",
  "title": "Devoluciones y reembolsos",
  "content": "## Nuestra política\n\nAceptamos devoluciones...",
  "content_plain": "Nuestra política. Aceptamos devoluciones...",
  "created_at": "2026-05-22T14:10:00+00:00",
  "updated_at": "2026-05-22T14:10:00+00:00"
}
object
string
required
Always "article_translation".
id
uuid
required
The translation’s own id. The parent article’s id lives in article_id.
article_id
uuid
required
The primary article this translation belongs to.
language
string
required
ISO 639-1 two-letter language code. Must differ from the parent article’s language. Unique per article — there’s exactly one translation per language per article.
Supported codes: en, ja, de, fr, ko, zh, nl, sv, es, it, no. Sending any other value returns invalid_payload.
title
string
required
Translated title.
content
string
required
Translated body. External image URLs are rehosted on write.
content_plain
string | null
Plain-text mirror used for indexing. Derived server-side from content — not accepted as input.

Endpoints

MethodPathPurpose
GET/articles/{id}/translationsList all translations
POST/articles/{id}/translationsCreate a new translation
GET/articles/{id}/translations/{language}Get one by language code
PATCH/articles/{id}/translations/{language}Update title or content
DELETE/articles/{id}/translations/{language}Remove a translation

End-to-end workflow

Create the primary in English, then add Spanish and French.
1

Create the primary article

curl https://api.awardee.dev/v1/articles \
  -X POST \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Returns & refunds",
    "slug": "returns-and-refunds",
    "content": "## Our policy\n\nReturns are accepted within 30 days...",
    "language": "en",
    "status": "published"
  }'
2

Add Spanish + French translations

curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e/translations \
  -X POST \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{
    "language": "es",
    "title": "Devoluciones y reembolsos",
    "content": "## Nuestra política\n\nAceptamos devoluciones..."
  }'

curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e/translations \
  -X POST \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{
    "language": "fr",
    "title": "Retours et remboursements",
    "content": "## Notre politique\n\nLes retours sont acceptés..."
  }'
3

Read a translation at render time

curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e/translations/es \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e"

Updating a translation

PATCH with the fields you want to change. The translation’s language is in the URL and cannot be changed — delete and recreate to “rename” the language.
curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e/translations/es \
  -X PATCH \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Política de devoluciones actualizada" }'

Deleting a translation

DELETE /articles/{id}/translations/{language} returns 204 and removes the translation row and its embeddings. The primary article is untouched.