HomeGuidesAPI Reference
ChangelogHelp CenterCommunityContact Us
API Reference

Translations API overview

OpenAPI Spec

Machine-readable spec for the Translations API: stable/categories/translations.json

Before you begin

Check out our general API overview before getting started with specific endpoints.

The Translations API lets you manage multilingual content across campaigns, flows, templates, and universal content programmatically. While Klaviyo's Smart Translations feature provides an in-app localization experience, the Translations API gives you a "bring your own translation" path: export source strings, translate them using your own tools or Translation Management System (TMS), and import the results back into Klaviyo.

📘

When calling the Translations API, your authentication key must have the appropriate scopes: translations:read for GET operations, translations:write for POST, PATCH, and DELETE operations.

Use cases

The Translations API supports the following use cases:

  • TMS integration: Export source content from Klaviyo, send it to an external TMS (e.g., Smartling, Phrase, Lokalise), and import the translated strings back, without reverse-engineering template HTML.
  • Bulk translation management: List all translations across your account, filter by channel or resource type, and audit which resources are localized.
  • Translation setup automation: Programmatically enable translations on campaigns, flows, templates, or universal content, setting source locale, target locales, and fallback locale.
  • Localized content updates: Update translation settings (add or remove target locales) or import new translated values for existing translations.
  • Translation cleanup: Delete translation collections when they are no longer needed.

Supported channels and resources

The Translations API supports the following channel and resource combinations:

Resource typeSupported channelsDescription
campaign-variationemail, sms, mobile_pushA variation of a campaign message.
flow-messageemail, sms, mobile_pushA message within a flow.
templateemail, whatsappA reusable email or WhatsApp template.
template-universal-contentemailA universal content block used across templates.

📘

WhatsApp templates have additional constraints: translations can only be created, updated, or deleted when the WhatsApp template is in DRAFT status, due to Meta's approval workflow.

Data model

A translation has the following structure:

  • id

    A composite identifier, for example campaign-variation::email::01KH00000000000000000000AB.

  • attributes

    • source_locale

      The BCP 47 locale code of the original source content (e.g., "en").

    • target_locales

      An array of locale codes that the content is translated into (e.g., ["fr", "es", "de"]). Must contain at least one item.

    • fallback_locale

      The locale used when translated content is unavailable for a target locale at render time (e.g., "en").

    • channel

      The communication channel: email, sms, mobile_push, or whatsapp.

    • metadata

      Optional, channel-specific metadata. null by default. Populated for WhatsApp translations with Meta-specific information such as template approval status.

    • created

      ISO 8601 timestamp of when the translation was created.

    • updated

      ISO 8601 timestamp of when the translation was last modified.

    • values (additional field)

      An array of translatable content blocks with their translations. Only returned when you request additional-fields[translation]=values on a Get Translation request. Not available on the list endpoint. See Export and import translation values for details.

  • relationships

    Each translation has exactly one relationship to the Klaviyo resource it belongs to. The relationship key matches the resource type: campaign-variation, flow-message, template, or template-universal-content.

Quick start: export and import workflow

A typical export-translate-import workflow looks like this:

Step 1: Find the translation for your resource.

curl --request GET \
     --url 'https://a.klaviyo.com/api/translations/?filter=equals(related_resource_id,"YOUR_RESOURCE_ID")' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'revision: 2026-10-15'

Step 2: Export the translation values.

curl --request GET \
     --url 'https://a.klaviyo.com/api/translations/campaign-variation::email::01KH00000000AB?additional-fields[translation]=values' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'revision: 2026-10-15'

The response includes the values array with source content and existing translations:

{
   "data": {
      "id": "campaign-variation::email::01KH00000000AB",
      "type": "translation",
      "attributes": {
         "source_locale": "en",
         "target_locales": ["fr", "es"],
         "fallback_locale": "en",
         "channel": "email",
         "metadata": null,
         "created": "2026-03-01T12:00:00+00:00",
         "updated": "2026-03-15T09:30:00+00:00",
         "values": [
            {
               "id": "scheduled_message::01KH00000000AB::subject",
               "source_value": "Spring Sale starts now!",
               "translations": {
                  "fr": "",
                  "es": ""
               }
            },
            {
               "id": "scheduled_message::01KH00000000AB::body",
               "source_value": "Shop our biggest sale of the season.",
               "translations": {
                  "fr": "",
                  "es": ""
               }
            }
         ]
      },
      "relationships": {
         "campaign-variation": {
            "data": {
               "type": "campaign-variation",
               "id": "01KH00000000AB"
            }
         }
      },
      "links": {
         "self": "https://a.klaviyo.com/api/translations/campaign-variation::email::01KH00000000AB"
      }
   }
}

📘

Empty strings ("") in the translations object indicate that a translation has not yet been provided for that locale.

Step 3: Translate the content using your TMS, translation team, or any tool of your choice.

Step 4: Import the translated values by sending a PATCH request with the updated values array. The payload format is symmetric with the export: you can take the exported values, fill in the translations, and send them back.

curl --request PATCH \
     --url 'https://a.klaviyo.com/api/translations/campaign-variation::email::01KH00000000AB' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'revision: 2026-10-15' \
     --data '{
  "data": {
    "type": "translation",
    "id": "campaign-variation::email::01KH00000000AB",
    "attributes": {
      "values": [
        {
          "id": "scheduled_message::01KH00000000AB::subject",
          "translations": {
            "fr": "Les soldes de printemps commencent maintenant !",
            "es": "Las rebajas de primavera empiezan ahora!"
          }
        },
        {
          "id": "scheduled_message::01KH00000000AB::body",
          "translations": {
            "fr": "Profitez de nos plus grandes promotions de la saison.",
            "es": "Compra en nuestra mayor venta de la temporada."
          }
        }
      ]
    }
  }
}'

📘

Partial imports

Import is a partial update: only the content blocks and locales you include in the values array are updated. Omitted blocks and locales remain unchanged. Re-importing the same translations is safe and idempotent.

🚧

target_locales is a full replacement

Unlike values, the target_locales attribute is not additive. Sending "target_locales": ["it"] replaces the entire list, removing any previously set locales. To add a locale, include all existing locales in the array. For example, if your current targets are ["es", "fr"] and you want to add Italian, send "target_locales": ["es", "fr", "it"].

Note that removing a locale from target_locales does not delete its translation values. If you have translations for ["es", "fr"] and update to ["it"], the es and fr values are retained. Updating back to ["es", "fr", "it"] restores access to all three locales with their existing translations intact.

Create a translation

To enable translations on a resource, send a POST request to Create Translation. You must specify exactly one relationship to identify the resource being translated.

curl --request POST \
     --url 'https://a.klaviyo.com/api/translations/' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'revision: 2026-10-15' \
     --data '{
  "data": {
    "type": "translation",
    "attributes": {
      "source_locale": "en",
      "target_locales": ["fr", "es"],
      "fallback_locale": "en",
      "channel": "email"
    },
    "relationships": {
      "campaign-variation": {
        "data": {
          "type": "campaign-variation",
          "id": "01KFXS23TVJH0ZWPZW644CRV"
        }
      }
    }
  }
}'
{
   "data": {
      "id": "campaign-variation::email::01KFXS23TVJH0ZWPZW644CRV",
      "type": "translation",
      "attributes": {
         "source_locale": "en",
         "target_locales": ["fr", "es"],
         "fallback_locale": "en",
         "channel": "email",
         "metadata": null,
         "created": "2026-04-15T12:00:00+00:00",
         "updated": "2026-04-15T12:00:00+00:00"
      },
      "relationships": {
         "campaign-variation": {
            "data": {
               "type": "campaign-variation",
               "id": "01KFXS23TVJH0ZWPZW644CRV"
            }
         }
      },
      "links": {
         "self": "https://a.klaviyo.com/api/translations/campaign-variation::email::01KFXS23TVJH0ZWPZW644CRV"
      }
   }
}

🚧

A resource can only have one translation collection. Attempting to create a translation for a resource that already has one returns a 409 Conflict error.

Update translation settings

Use Update Translation to modify translation settings such as adding or removing target locales. All attributes are optional in a PATCH request.

curl --request PATCH \
     --url 'https://a.klaviyo.com/api/translations/campaign-variation::email::01KFXS23TVJH0ZWPZW644CRV' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'revision: 2026-10-15' \
     --data '{
  "data": {
    "type": "translation",
    "id": "campaign-variation::email::01KFXS23TVJH0ZWPZW644CRV",
    "attributes": {
      "target_locales": ["fr", "es", "de"]
    }
  }
}'

📘

If you change source_locale to a locale that is currently in target_locales, that locale is automatically removed from the target list.

Export and import translation values

Export values

To export translation values, use the additional-fields[translation]=values query parameter on a Get Translation request. This returns the values attribute containing each translatable content block with its source text and current translations.

curl --request GET \
     --url 'https://a.klaviyo.com/api/translations/flow-message::email::01KGABCDEF?additional-fields[translation]=values' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'revision: 2026-10-15'

Each item in the values array has:

  • id — The identifier for the translatable content block.
  • source_value — The original text in the source locale.
  • translations — A map of target locale codes to their translated strings. Empty strings indicate missing translations.

🚧

The additional-fields[translation]=values parameter is only supported on the Get Translation (single resource) endpoint. It is not yet supported on Get Translations (list endpoint) and will return a 400 error if used there.

Import values

To import translations, include a values array in the attributes of a PATCH request to Update Translation. The import format mirrors the export format for payload symmetry: you can export, edit, and re-import with minimal transformation.

Each value object contains:

  • id (required) — Must match a valid translatable content block ID from the export.
  • source_value (optional) — The original source text. Not required for import, but included in the export response, so you can pass it through as-is.
  • translations (required) — A map of locale codes to translated strings. Only the locales you include are updated.
curl --request PATCH \
     --url 'https://a.klaviyo.com/api/translations/flow-message::email::01KGABCDEF' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'revision: 2026-10-15' \
     --data '{
  "data": {
    "type": "translation",
    "id": "flow-message::email::01KGABCDEF",
    "attributes": {
      "values": [
        {
          "id": "flow_message::01KGABCDEF::subject",
          "translations": {
            "fr": "Bienvenue !",
            "de": "Willkommen!"
          }
        }
      ]
    }
  }
}'

Delete a translation

To remove translations from a resource, use Delete Translation. This removes the translation collection and all associated localized values.

curl --request DELETE \
     --url 'https://a.klaviyo.com/api/translations/campaign-variation::email::01KFXS23TVJH0ZWPZW644CRV' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'revision: 2026-10-15'

A successful deletion returns 204 No Content.

Querying translations

Use the Get Translations list endpoint to find translations across your account. Check out the supported query parameters below:

ParameterDescriptionQuery example
filterRetrieve a subset of translations. Supported filter fields: id, resource_type, channel, related_resource_id. Learn about the filter query parameter.GET /api/translations?filter=equals(channel,"email")

GET /api/translations?filter=equals(related_resource_id,"01KFXS23TVJH")
sortSort translations. Supported field: id. Prefix with - for descending. Learn about the sort query parameter.GET /api/translations?sort=id

GET /api/translations?sort=-id
fieldsRequest only specified translation data. Learn more about sparse fieldsets.GET /api/translations?fields[translation]=source_locale,target_locales,channel
includeInclude related resources in the response (e.g., campaign-variation, flow-message, template, template-universal-content). Learn about the include query parameter.GET /api/translations?include=campaign-variation
page[size]Number of results per page (default: 20, max: 100).GET /api/translations?page[size]=50
page[cursor]Cursor for paginating through results.GET /api/translations?page[cursor]=abc123

Filtering examples

Get all email translations:

curl --request GET \
     --url 'https://a.klaviyo.com/api/translations/?filter=equals(channel,"email")' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'revision: 2026-10-15'

Get the translation for a specific resource:

curl --request GET \
     --url 'https://a.klaviyo.com/api/translations/?filter=equals(related_resource_id,"01KFXS23TVJH0ZWPZW644CRV")' \
     --header 'Authorization: Klaviyo-API-Key your-private-api-key' \
     --header 'accept: application/json' \
     --header 'revision: 2026-10-15'

Relationship endpoints

Each translation exposes a read-only relationship endpoint for the associated Klaviyo resource:

  • GET /api/translations/{id}/campaign-variation/
  • GET /api/translations/{id}/flow-message/
  • GET /api/translations/{id}/template/
  • GET /api/translations/{id}/template-universal-content/

These return the related resource data, useful for navigating from a translation back to the content it belongs to.

Additional resources