> ## Documentation Index
> Fetch the complete documentation index at: https://weaverse.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Weaverse component configuration uses `settings`. `inspector` is deprecated; never generate it.
> Weaverse Hydrogen themes use React Router v7: import from `react-router`, never `react-router-dom` or `@remix-run/*`.
> Define component schemas with `createSchema()` from `@weaverse/hydrogen` (React Router themes) or `@weaverse/next` (Next.js themes).
> These docs cover @weaverse/hydrogen, @weaverse/react and @weaverse/core 5.x, and @weaverse/next 1.x. Do not use APIs from other major versions.
> For live project data (pages, theme settings, translations), use the Weaverse MCP server: https://docs.weaverse.io/developer-tools/weaverse-mcp

# Apply translations for one page and locale

> Writes translation overrides for an owned page and one configured, non-default target locale. Send the entries read from `GET` with `translation` replaced; `source` and `targetGeneration` must be the values `GET` returned.

- Only `Translation` rows change. Base page content, its items and every other locale are untouched.
- The project default language is rejected (400): it is the source other locales translate from.
- Each entry is compare-and-set on both its `source` and its `targetGeneration`, so a delayed agent can never overwrite a source the merchant edited or a newer translation another writer stored. Refused entries are counted in `stale` and were not written; re-read and resubmit them. `applied + stale = requested`.
- `translation: ""` clears a key, keeping the tombstone row that distinguishes "cleared" from "never translated".
- `targetGeneration` is required on every entry (`null` when `GET` returned `null`); omitting it is a 400, not a blind write.
- At most 250 entries per request; duplicate `itemId` + `key` pairs are rejected.
- A request that applies nothing advances no project revision and flushes no cache.
- If the write committed but cache invalidation failed, the response is a 500 whose message states how many entries were applied. Verify with `GET`; retrying the same entries will not flush the cache, because they then lose the target compare-and-set as no-ops.

Required scope: `content:write`



## OpenAPI

````yaml https://studio.weaverse.io/api/v1/content/openapi.json post /projects/{projectId}/page-translations/{pageId}
openapi: 3.1.0
info:
  title: Weaverse Content API
  version: 1.0.0
  description: >-
    Authenticated REST API for querying Weaverse-managed content (projects,
    pages, theme settings, languages) and for reading and writing per-locale
    translations.
servers:
  - url: https://studio.weaverse.io/api/v1/content
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Projects
    description: List, read, rename, create, copy and delete projects.
  - name: Pages
    description: List, read, create, update and delete the pages of a project.
  - name: Drafts and publishing
    description: >-
      Edit page drafts, then publish, schedule, restore and manage page
      versions.
  - name: Global sections
    description: Read, edit and publish sections shared across pages.
  - name: Page settings
    description: Read and edit page-level settings such as SEO metadata.
  - name: Assignments
    description: Map Shopify resources and routes to Weaverse pages and templates.
  - name: Theme settings
    description: Read and update a project's theme settings.
  - name: Languages and localization
    description: List project languages and manage locales, static text and glossary.
  - name: Translations
    description: >-
      Read and write per-locale translations, built for external translation
      agents.
  - name: Project structure
    description: Manage project variants and the project hierarchy.
  - name: Backups and portability
    description: Back up, restore, export and import project content.
  - name: Previews and hostnames
    description: Create preview links and manage the hostnames a project accepts.
  - name: Specification
    description: This OpenAPI document.
paths:
  /projects/{projectId}/page-translations/{pageId}:
    post:
      tags:
        - Translations
      summary: Apply translations for one page and locale
      description: >-
        Writes translation overrides for an owned page and one configured,
        non-default target locale. Send the entries read from `GET` with
        `translation` replaced; `source` and `targetGeneration` must be the
        values `GET` returned.


        - Only `Translation` rows change. Base page content, its items and every
        other locale are untouched.

        - The project default language is rejected (400): it is the source other
        locales translate from.

        - Each entry is compare-and-set on both its `source` and its
        `targetGeneration`, so a delayed agent can never overwrite a source the
        merchant edited or a newer translation another writer stored. Refused
        entries are counted in `stale` and were not written; re-read and
        resubmit them. `applied + stale = requested`.

        - `translation: ""` clears a key, keeping the tombstone row that
        distinguishes "cleared" from "never translated".

        - `targetGeneration` is required on every entry (`null` when `GET`
        returned `null`); omitting it is a 400, not a blind write.

        - At most 250 entries per request; duplicate `itemId` + `key` pairs are
        rejected.

        - A request that applies nothing advances no project revision and
        flushes no cache.

        - If the write committed but cache invalidation failed, the response is
        a 500 whose message states how many entries were applied. Verify with
        `GET`; retrying the same entries will not flush the cache, because they
        then lose the target compare-and-set as no-ops.


        Required scope: `content:write`
      operationId: applyPageTranslations
      parameters:
        - name: projectId
          in: path
          required: true
          schema:
            type: string
        - name: pageId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PageTranslationsUpdateRequest'
            example:
              locale: fr-fr
              translations:
                - itemId: clz8k3d2e0008poiu7ytr6ewq
                  key: data.buttonText
                  source: Shop now
                  translation: Acheter maintenant
                  targetGeneration: null
      responses:
        '200':
          description: >-
            Decision for the whole batch. `applied + stale = requested`; a
            non-zero `stale` means those keys must be re-read and resubmitted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageTranslationsUpdateResult'
              example:
                object: page_translations_update
                projectId: clz8k2m4n0001qwer7tyu8iop
                pageId: clz8k3a1b0004asdf5ghj6klz
                language:
                  id: clz8k2x7y0003lkjh4gfd3sap
                  code: fr-fr
                requested: 1
                applied: 1
                stale: 0
        '400':
          description: >-
            Malformed body, unconfigured locale, the project default language,
            or more than 250 entries
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            Project not found, page not owned by this project, or an item not on
            that page
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '405':
          description: Method not allowed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: >-
            Unexpected server error. Also returned when the translations
            COMMITTED but the cache fan-out failed: the message says how many
            were applied and that they may not be readable yet. Verify with GET;
            retrying the same entries will not flush the cache, because they
            then lose the target compare-and-set as no-ops.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    PageTranslationsUpdateRequest:
      type: object
      required:
        - locale
        - translations
      properties:
        locale:
          type: string
          description: >-
            Target locale, resolved through the same language identity the
            storefront uses. Must be a configured, non-default language.
        translations:
          type: array
          maxItems: 250
          description: >-
            Entries echoed from GET with `translation` replaced. `source` and
            `targetGeneration` must be the values GET returned.
          items:
            $ref: '#/components/schemas/PageTranslationEntry'
    PageTranslationsUpdateResult:
      type: object
      properties:
        object:
          type: string
          enum:
            - page_translations_update
        projectId:
          type: string
        pageId:
          type: string
        language:
          type: object
          properties:
            id:
              type: string
            code:
              type: string
        requested:
          type: integer
        applied:
          type: integer
          description: >-
            Entries that passed both the source and target compare-and-set and
            were written.
        stale:
          type: integer
          description: >-
            Entries refused because the source or the target moved since the
            read. Re-run GET and resubmit those keys; they were NOT written.
    Error:
      type: object
      required:
        - object
        - code
        - message
        - status
      properties:
        object:
          type: string
          enum:
            - error
        code:
          type: string
          enum:
            - UNAUTHORIZED
            - FORBIDDEN
            - INSUFFICIENT_SCOPE
            - PROJECT_NOT_FOUND
            - PAGE_NOT_FOUND
            - STALE_PAGE
            - STALE_PROJECT
            - STALE_TRANSLATION
            - TRANSLATION_UNIT_NOT_FOUND
            - SERVICE_UNAVAILABLE
            - CONFLICT
            - PRECONDITION_REQUIRED
            - INVALID_PARAMS
            - INTERNAL_ERROR
        message:
          type: string
        status:
          type: integer
        details:
          description: >-
            Optional machine-readable context, for example the clashing handles
            of a 409 CONFLICT.
    PageTranslationEntry:
      type: object
      required:
        - itemId
        - key
        - source
        - translation
        - targetGeneration
      properties:
        itemId:
          type: string
          description: The item the key belongs to.
        key:
          type: string
          description: >-
            The extraction path of the translatable field, rooted at the item
            data column (e.g. `data.title`). Use it verbatim; it is the stored
            translation key.
        source:
          type: string
          description: >-
            The text the translation answers for, resolved server-side from the
            item value, its component-schema default, or the project default
            language overlay — whichever the runtime actually translates FROM.
        translation:
          type:
            - string
            - 'null'
          description: >-
            The current target text. `""` is a deliberate clear; `null` means no
            row exists, or the stored one answers a source the merchant has
            since changed.
        targetGeneration:
          type:
            - string
            - 'null'
          description: >-
            The raw stored target value at read time, independent of freshness:
            `null` = no row, `""` = cleared. Replay it verbatim on write; it is
            the compare-and-set token that stops a delayed agent overwriting a
            newer translation.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: WEAVERSE_API_KEY
      description: >-
        Bearer authentication: a shop API key (WEAVERSE_API_KEY), a scoped API
        key, a delegated MCP OAuth token, or (translation-unit routes only) a
        project-bound translation agent token. Scopes: content:read — Read
        projects, pages, theme settings, versions, drafts and translation units.
        content:write — Save drafts and make non-destructive edits (page items,
        metadata, SEO, assignments, languages, glossary). Never publishes or
        deletes. content:publish — Publish drafts, schedule/reschedule/cancel
        publications, restore versions, publish global sections. content:delete
        — Delete pages, global sections, languages, static keys, override
        reverts; required with project:manage for project deletion.
        project:manage — Create/copy/delete projects, settings, variants,
        hierarchy, backups, restore-as-new, previews, hostname policy.
        translations:read — Read translation units only (no general content
        access). translations:write — Apply translation units only; never
        mutates page content. A legacy unscoped API key keeps
        read/write/translation baseline access and every pre-scope endpoint, but
        never gains publish/delete/project-manage implicitly.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.