# Localizing using the Dyspatch API


You have completed building your email draft and are ready to localize the content! Follow along with this guide to understand a technical workflow example using the Dyspatch API.

This guide uses resources from the <a href="https://docs.dyspatch.io/api/" target="_blank">API documentation</a> to help outline which endpoints to use for each step in a programmatic localizations workflow. For more information on each endpoint, take a look at the <a href="https://docs.dyspatch.io/api/#tag/Drafts" target="_blank">Drafts API</a> section.

## Localizing Email State

In order to start this process, you will want to make sure your email draft is in the **Localizing** state.

To move to the **Localizing** draft state, select the **Localizations** tab and click on the **Lock for Translation** button.

![Lock for translation](https://docs.dyspatch.io/img/localizations/lock-for-translation.png)

There will be a marker to indicate the draft has been successfully locked for translations with the **Localizing** badge.

![Localizing Badge Marker](https://docs.dyspatch.io/img/localizations/localizing-badge-marker.png)

The draft is now locked to prevent any changes from being made during the translation process. These drafts are tagged specifically to allow your system to pull drafts in this state through the API.

## Get Drafts via API

Once the email draft is marked as **Localizing**, the draft is made available through the API. To retrieve a list of all drafts ready for translation, make a request to the `/drafts` API with the `awaitingLocalization` query parameter.

**Request URL:**

```bash
GET https://api.dyspatch.io/drafts?status=awaitingTranslation
```

**Response:**

```bash
{
  "cursor": {
    "hasMore": false,
    "next": ""
  },
  "data": [
    {
      "createdAt": "2026-03-01T18:57:06Z",
      "id": "tdft_01ds66130r2t2z4h47p7dt4",
      "name": "First Draft - Localizations",
      "path": "fdr_01hpj7ccxzfcg1m1d4oszf3k7s",
      "status": "LOCKED_FOR_TRANSLATION",
      "templateId": "tem_01ds63931fbsgcn0gmgh5zz",
      "templateName": "Tutorial Step 1: Using the Email Builder",
      "updatedAt": "2026-03-01T23:01:13Z",
      "url": "https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4",
      "workspaceId": "fdr_01hpj7ccxzdcg1m1d3mszf3k3s"
    },
    ...
  ]
}
```

**Sample Curl Request:**

```curl
curl --request GET \
  --url 'https://api.dyspatch.io/drafts?status=awaitingTranslation' \
  --header 'accept: application/vnd.dyspatch.2026.01+json' \
  --header 'authorization: Bearer API-KEY'
```

Replace the `API-KEY` to use the curl request.

## Localizing a Draft

To create a localization for the draft, make a request to the <a href="https://docs.dyspatch.io/api/#operation/saveLocalization" target="_blank">Create/Update a Localization</a> API. The request URL `/drafts/{draftId}/localizations/{languageId}` will take a `draftId` and a `languageId`.

The `draftId` will be the matching draft ID from the above request. The `languageId` will be any valid locale code (e.g. "en-US"). [Click here for a full list of supported locales](/localization/supported_languages/#supported-languages).

<div class="highlight note">
  Sending a request using this endpoint will either <b>overwrite</b> a previously created localization or create a new localization.
</div>

**Request URL:**

```bash
PUT https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizations/fr-FR
```

**Request Body:**

```bash
{
	"name": "French (France)"
}
```

**Response:**

```bash
200 OK
```

**Sample Curl Request:**

```curl
curl --request PUT \
  --url https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizations/fr-FR \
  --header 'accept: application/vnd.dyspatch.2026.01+json' \
  --header 'authorization: Bearer API-KEY' \
  --header 'content-type: application/json' \
  --data '{
	"name": "French (France)"
}'
```

Replace the Template Draft ID `tdft_` and the `API-KEY` to use the curl request.

![Created Localization from API](https://docs.dyspatch.io/img/localizations/created-localization-from-api.png)

## Get the Localizations Keys for a Draft

Once the localizations have been created on the draft, you will want to fetch the localization keys.

A localization key will be a content piece from your email draft. This typically includes content such as copy, but can also include any URLs and image sources. These keys will be the content you will want to translate and send to your translations team.

Set the `Accept` header to `application/vnd.dyspatch.2026.01+json` to get a **JSON object** with the keys.

Set the `Accept` header to `text/vnd.dyspatch.2026.01+x-gettext-translation` to get a **POT file** with the keys.

<div class="highlight note">
  The <b>2026.01</b> will be the version of the API you're targeting. Take a look at which versions are available: <a href="https://docs.dyspatch.io/api/changelog.html" target="_blank">API changelog</a>.
</div>

**Request URL:**

```bash
GET https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizationKeys
```

**Response - JSON object:**

```bash
[
  {
    "key": "thanks for signing up!"
  },
  {
    "key": "welcome to %(company_brand)s"
  },
  {
    "key": "Verify Account"
  },
  {
    "key": "https://app.dyspatch.io/welcome?lang=en-US",
    "comment": "localization for 'href' property of 'Verify Account'"
  },
]
```

OR

**Response - POT file:**

```bash
# GENERATED USING DYSPATCH
# FOR HELP CONTACT SUPPORT@DYSPATCH.IO
#
#, fuzzy
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#, python-format
msgid "welcome to %(company_brand)s"
msgstr ""

msgid "thanks for signing up!"
msgstr ""

msgid "Verify Account"
msgstr ""

#. localization for 'href' property of 'Verify Account'
msgid "https://app.dyspatch.io/welcome?lang=en-US"
msgstr ""
```

**Sample Curl Request:**

JSON Object

```curl
curl --request GET \
  --url https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizationKeys \
  --header 'accept: application/vnd.dyspatch.2026.01+json' \
  --header 'authorization: Bearer API-KEY' \
  --header 'content-type: application/json'
```

POT File

```curl
curl --request GET \
  --url https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizationKeys \
  --header 'accept: text/vnd.dyspatch.2026.01+x-gettext-translation' \
  --header 'authorization: Bearer API-KEY' \
  --header 'content-type: application/json'
```

Replace the Template Draft ID `tdft_` and the `API-KEY` to use the curl request.

## Send for Translations

You now have the localization keys! You will want to send these keys to be translated either by your translations team or a translation service.

## Update Translation Values in Dyspatch

After you have translated the keys, you can update the draft by making a request to the <a href="https://docs.dyspatch.io/api/#operation/setTranslation" target="_blank">Set translations for language</a> endpoint.

<div class="highlight note">
  Set Content-Type header to <b>application/json</b> for <b>JSON</b>, or <b>text/x-gettext-translation</b> for <b>PO</b> file.</div>

**Request URL:**

```bash
PUT https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizations/fr-FR/translations
```

**Request Body - JSON object:**

```bash
{
	"welcome to %(company_brand)s": "bienvenue en %(company_brand)s",
	"thanks for signing up!": "merci pour l'enregistrement!",
	"Verify Account": "Vérifier le Compte",
	"https://app.dyspatch.io/welcome?lang=en-US": "https://app.dyspatch.io/welcome?lang=fr-FR"
}
```

or

**Request Body - PO file:**

```bash
# GENERATED USING DYSPATCH
# FOR HELP CONTACT SUPPORT@DYSPATCH.IO
#
#, fuzzy
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#, python-format
msgid "welcome to %(company_brand)s"
msgstr "bienvenue en %(company_brand)s"

msgid "thanks for signing up!"
msgstr "merci pour l'enregistrement!"

msgid "Verify Account"
msgstr "Vérifier le Compte"

#. localization for 'href' property of 'Verify Account'
msgid "https://app.dyspatch.io/welcome?lang=en-US"
msgstr "https://app.dyspatch.io/welcome?lang=fr-FR"
```

**Response:**

```bash
200 OK
```

**Sample Curl Request:**

JSON Object

```curl
curl -i --request PUT \
  --url https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizations/fr-FR/translations \
  --header 'accept: application/vnd.dyspatch.2026.01+json' \
  --header 'authorization: Bearer API-KEY' \
  --header 'content-type: application/json' \
  --data '{
	"welcome to %(company_brand)s": "bienvenue en %(company_brand)s",
	"thanks for signing up!": "merci pour l'\''enregistrement!",
	"Verify Account": "Vérifier le Compte",
	"https://app.dyspatch.io/welcome?lang=en-US": "https://app.dyspatch.io/welcome?lang=fr-FR"
}'
```

PO File

```curl
curl -i --request PUT \
  --url https\://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/localizations/fr-FR/translations \
  --header 'Content-Type: text/x-gettext-translation' \
  --header 'Authorization: Bearer API-KEY' \
  --header 'Accept: application/vnd.dyspatch.2026.01+json' \
  --data msgid\ \"\"'
        'msgstr\ \"\"'
        '\"MIME-Version\:\ 1.0\\n\"'
        '\"Content-Type\:\ text/plain\;\ charset\=UTF-8\\n\"'
        '\"Content-Transfer-Encoding\:\ 8bit\\n\"'
        '\#\,\ python-format'
        'msgid\ \"welcome\ to\ \%\(company_brand\)s\"'
        'msgstr\ \"bienvenue\ en\ \%\(company_brand\)s\"'
        'msgid\ \"thanks\ for\ signing\ up\!\"'
        'msgstr\ \"merci\ pour\ l\'enregistrement\!\"'
        'msgid\ \"Verify\ Account\"'
        'msgstr\ \"V\érifier\ le\ Compte\"
```

Replace the Template Draft ID `tdft_` and the `API-KEY` to use the curl request.

This action will update the specified language code with the translated keys.

![Localized Keys Updated](https://docs.dyspatch.io/img/localizations/localized-keys-updated.png)

## Submit Email for Approval (Optional)

You can optionally submit the email for approval via the API. If you choose not to do this automatically, you can still manually [submit for approval via the dashboard](https://docs.dyspatch.io/emails/submitting_an_email/#submit-for-approval).

**Request URL:**

```bash
POST https://api.dyspatch.io/drafts/tdft_01ds66130r2t2z4h47p7dt4/publishRequest
```

**Response:**

```bash
200 OK
```

All set! Your email draft will now be [waiting for approval](/emails/submitting_an_email/#awaiting-approval). Your email stakeholders will be able to review the email, reject the approval to provide comments and feedback, or approve and publish the draft.


## Fully Automated Localization Workflow

Need to make translation changes to an email that has already been published? Here's what a fully automated workflow would look like in action:

#### Phase 1: Creating & Approving the Design
1. **Retrieve the Target Email**: Make a Get Template by ID `(GET /templates/{templateId})` request to grab the `publishedDraftId`.
2. **Duplicate the Draft**: Using the `publishedDraftId` from step 1 as `{draftId}`, make a Duplicate Draft request `(POST /drafts/{draftId}/duplicate)`. Be sure to pass a name for your newly duplicated draft!
3. **Pass the "Design" Stage** (Optional): If your team has [two-step approvals enabled](/emails/submitting_an_email/#localization-approval-workflow), you will need to clear the design phase. Use the API to Submit Draft for Approval `(POST /drafts/{draftId}/publishRequest)`, and then immediately Approve the Draft `(POST /drafts/{draftId}/publish/approve)`.

#### Phase 2: Kicking Off Localization
1. **Lock the Draft**: Once the design is approved, use the Lock Draft for Translation `(PUT /drafts/{draftId}/lockForTranslation)`.
2. **Trigger Your Translation Pipeline**: Locking the draft will [trigger a webhook](/integrations/setting_up_webhooks/) (`template_locked_for_translation`) from Dyspatch. You can use this webhook to automatically trigger your external localization process. [Get the localizable content](/localization/localizing_workflow/#localizing-a-draft) and send the content to a Translation Management System or external agency.

#### Phase 3: Finalizing the Localized Email
1. **Final Review & Approval**: Once the localization process is completed and synced back, use the API to Submit the Draft for Approval once more.
2. **Publish**: For the final approval, you have ultimate flexibility. You can have a stakeholder review and approve the finalized, translated email manually in the Dyspatch app, OR you can keep it fully automated by hitting the Approve Draft endpoint one last time to ready it for production.