Skip to content

JohnDoeIsBack/azure-translator-llm-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Azure Translator Preview API — Complete Reference

API Version: 2025-10-01-preview Scope: Text Translation (/translate) only — transliterate excluded

Why this guide exists: The official Microsoft documentation has significant gaps for the LLM-based translation workflow. It tells you to use a Foundry resource but only shows the global endpoint, which doesn't authenticate with Foundry keys. The resource-specific endpoint path (/translator/text/translate) is not documented in the preview API pages. This guide fills those gaps with tested, working examples.

Prefer Python over curl? See translator.py — a ready-to-run Python script with all 16 examples below as callable functions, an interactive menu, and automatic NMT/LLM engine detection from the response.


Table of Contents


Critical Setup Guide (Read This First)

If you want to use LLM-based translation (GPT-4o / GPT-4o-mini) through the Translator API, you need to get several things right that the docs don't clearly explain. Here's the short version:

Prerequisites

  1. An Azure AI Foundry resource (Kind: AIServices) — not a standalone Azure OpenAI resource or a standalone Translator resource.

    • Check in Azure Portal: your resource > Overview > the "Kind" field must say AIServices
    • If it says OpenAI, it won't work — you need to create a Foundry multi-service resource instead
  2. A GPT-4o or GPT-4o-mini model deployed inside that Foundry resource

    • Deploy via: Azure AI Foundry > your project > Model deployments
    • Note the exact deployment name (e.g. gpt-4o-newtest) — this is what you pass as deploymentName, not the model name
  3. The resource-specific endpoint — you cannot use the global api.cognitive.microsofttranslator.com endpoint for LLM translation

    • Format: https://<your-resource>.cognitiveservices.azure.com/translator/text/translate?api-version=2025-10-01-preview
    • The /translator/text/translate path is not documented in the preview API docs but is required
  4. The Foundry resource's key — found in Azure Portal > your Foundry resource > Keys and Endpoint

What does NOT work (and why)

What you might try What happens Why
Global endpoint + Foundry key 401 Unauthorized Global endpoint doesn't accept Foundry/AIServices keys
Global endpoint + Translator key + deploymentName 400 "deployment not found" Standalone Translator resource can't see Foundry deployments
Standalone Azure OpenAI resource (Kind: OpenAI) 400 "deployment not found" Translator API only discovers deployments on AIServices/Foundry resources

What DOES work

Setup NMT LLM
Resource-specific endpoint + Foundry key Works Works
Global endpoint + Translator key (no deploymentName) Works N/A — NMT only

Endpoints

Resource-specific (required for AIServices/Foundry resources):

https://<your-resource>.cognitiveservices.azure.com/translator/text/translate?api-version=2025-10-01-preview

Global (works for Neural Machine Translations only + region header):

https://api.cognitive.microsofttranslator.com/translate?api-version=2025-10-01-preview

Regional data zones (NMT only, restricts data processing to specific geography):

Americas:     https://api-nam.cognitive.microsofttranslator.com/translate?api-version=2025-10-01-preview
Europe:       https://api-eur.cognitive.microsofttranslator.com/translate?api-version=2025-10-01-preview
Asia Pacific: https://api-apc.cognitive.microsofttranslator.com/translate?api-version=2025-10-01-preview

Authentication Methods

Method 1: Subscription Key (simplest)

Header Value Required?
Ocp-Apim-Subscription-Key Your resource key Yes
Ocp-Apim-Subscription-Region Your resource region (e.g. eastus) Only for global endpoint with regional/multi-service resources

Region header is not needed when using the resource-specific endpoint.

Method 2: Bearer Token (exchange key for short-lived token)

Step 1: Exchange your key for a token:

  • Global: POST https://api.cognitive.microsoft.com/sts/v1.0/issueToken
  • Regional: POST https://<region>.api.cognitive.microsoft.com/sts/v1.0/issueToken
  • Header: Ocp-Apim-Subscription-Key: <key>

Step 2: Use the token:

  • Header: Authorization: Bearer <token>

Token is valid for 10 minutes. Refresh every ~8 minutes for long-running operations.

Method 3: Microsoft Entra ID (Azure AD)

Global endpoint:

Header Value
Authorization Bearer <entra-token>
Ocp-Apim-ResourceId /subscriptions/<subId>/resourceGroups/<rgName>/providers/Microsoft.CognitiveServices/accounts/<resourceName>/
Ocp-Apim-Subscription-Region Your region (optional)

Resource-specific endpoint:

Header Value
Authorization Bearer <entra-token>

Requires Cognitive Services User role assigned on the resource.

Method 4: Managed Identity

Same headers as Entra ID, but the token is obtained from the managed identity endpoint instead of Entra ID.

Method 5: VNET / Private Endpoint

  • Must use resource-specific (custom domain) endpoint
  • Cannot use global endpoint or bearer tokens
  • Header: Ocp-Apim-Subscription-Key: <key>
  • Warning: LLM-based translation is NOT available with private endpoints

Request Headers

Header Required? Description
Content-Type Yes application/json or application/json; charset=UTF-8
Ocp-Apim-Subscription-Key Yes* Your resource key (*unless using Bearer/Entra/MI auth)
Ocp-Apim-Subscription-Region Conditional Required for global endpoint with regional/multi-service resources
Ocp-Apim-ResourceId Conditional Required for Entra ID / Managed Identity auth on global endpoint
Authorization Conditional Bearer <token> — for token/Entra/MI auth
X-ClientTraceId Optional Client-generated GUID to trace the request
Content-Length Optional Length of request body

Query Parameters

Parameter Required Value
api-version Yes 2025-10-01-preview

Request Body — inputs Fields

Field Type Required Description
inputs[].text string Yes Source text to translate
inputs[].language string No Source language code (auto-detected if omitted)
inputs[].script string No Script of the source text (e.g. Latn)
inputs[].textType string No plain (default) or html
inputs[].targets array Yes Array of target language objects

Request Body — targets Fields

Field Type Required Description
targets[].language string Yes Target language code (e.g. es, de, fr)
targets[].script string No Target script for transliteration
targets[].deploymentName string No general (default, NMT) | your LLM deployment name | categoryID (custom NMT)
targets[].tone string No formal | informal | neutral (LLM only)
targets[].gender string No female | male | neutral (LLM only)
targets[].profanityAction string No NoAction (default) | Marked | Deleted
targets[].profanityMarker string No Asterisk (default) | Tag (only when profanityAction=Marked)
targets[].allowFallback boolean No true (default) | false — fall back to NMT if LLM unavailable
targets[].referenceTextPairs array No Up to 5 source/target pairs for adaptive translation (LLM only)
targets[].referenceTextPairs[].source string Source text in reference pair
targets[].referenceTextPairs[].target string Target text in reference pair
targets[].adaptiveDatasetId string No Reference dataset ID (alternative to referenceTextPairs)

Response Body Structure

How to Tell Which Engine Handled Your Request

The response fields tell you whether NMT or LLM processed the translation. These fields are mutually exclusive — you'll see one set or the other, never both.

You see in response... Engine used Billing
"sourceCharacters": 19 NMT Per character
"instructionTokens", "sourceTokens", "responseTokens", "targetTokens" LLM (GPT-4o) Per token

If you requested a deploymentName but see sourceCharacters in the response, your request fell back to NMT (e.g. allowFallback was true and the LLM was unavailable).

NMT response example:

{
  "value": [
    {
      "translations": [
        {
          "language": "es",
          "text": "Hola, \u00bfqu\u00e9 tal?",
          "sourceCharacters": 19
        }
      ]
    }
  ]
}

LLM response example:

{
  "value": [
    {
      "translations": [
        {
          "language": "es",
          "text": "El doctor est\u00e1 disponible el pr\u00f3ximo lunes. \u00bfQuieres programar una cita?",
          "instructionTokens": 298,
          "sourceTokens": 14,
          "responseTokens": 10,
          "targetTokens": 15
        }
      ]
    }
  ]
}

Auto-detected language (appears when inputs[].language is omitted):

{
  "value": [
    {
      "detectedLanguage": { "language": "fr", "score": 1.0 },
      "translations": [ "..." ]
    }
  ]
}

LLM Token Breakdown

Field Meaning
instructionTokens System prompt tokens — the internal prompt the Translator service sends to GPT-4o (you don't control this)
sourceTokens Your input text tokenized
responseTokens The model's raw response tokens
targetTokens The translation output tokens

Response Headers

Header Description
X-requestid Service-generated GUID for troubleshooting
X-mt-system Custom or Team (indicates which system was used)
X-metered-usage Number of characters charged (NMT)
sourceTokensCharged Source tokens billed (LLM)
targetTokensCharged Target tokens billed (LLM)

Service Limits

NMT LLM (GPT-4o / GPT-4o-mini)
Free tier Yes — F0: 2M chars/month free No — no free tier for LLM translation
Paid tier S1 (pay-as-you-go) + commitment tiers for volume Standard pay-as-you-go, Provisioned (PTU), or Batch (50% discount)
Billing unit Per character Per token (input + output)
Max array elements 1,000 50
Max chars per element 50,000 5,000
Max referenceTextPairs N/A 5
Pricing page Azure Translator Pricing Azure OpenAI Pricing

Note: S2, S3, and S4 Translator tiers have been deprecated by Microsoft. Only F0 (free) and S1 (paid) remain active.


Migration from v3.0 — Breaking Changes

What changed v3.0 (old) 2025-10-01-preview (new)
API version api-version=3.0 api-version=2025-10-01-preview
Target language ?to=es (query param) targets[].language (in body)
Source language ?from=en (query param) inputs[].language (in body)
Request body wrapper [{"Text":"..."}] {"inputs":[{"text":"..."}]}
Response body wrapper [{"translations":[...]}] {"value":[{"translations":[...]}]}
Text field casing "Text" (capital T) "text" (lowercase t)

Removed endpoints (no longer exist in preview):

  • /breaksentence — Use sentence delimiters or an NLP library
  • /detect — Use Azure AI Language detection API
  • /dictionary/lookup — Removed
  • /dictionary/examples — Removed

New features (not in v3.0):

  • LLM model selection via deploymentName (GPT-4o, GPT-4o-mini)
  • Tone control (formal / informal / neutral)
  • Gender control (female / male / neutral)
  • Adaptive custom translation (referenceTextPairs / adaptiveDatasetId)
  • Token-based billing for LLM responses

Example curl Commands

Variables

ENDPOINT="https://newgpt-4o-project-resource-llm.cognitiveservices.azure.com/translator/text/translate?api-version=2025-10-01-preview"
KEY="<your-foundry-resource-key>"

1. Basic NMT Translation (no deployment, uses default NMT)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Hello, how are you?","language":"en","targets":[{"language":"es"}]}]}'

2. LLM Translation (GPT-4o via deploymentName)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Doctor is available next Monday. Do you want to schedule an appointment?","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]}]}'

3. LLM with Tone and Gender

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Doctor is available next Monday. Do you want to schedule an appointment?","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","tone":"formal","gender":"female"}]}]}'

4. Profanity — Allow All (NoAction = pass through as-is)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"What the hell is going on here?","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","profanityAction":"NoAction"}]}]}'

5. Profanity Marked with Asterisks

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"What the hell is going on here?","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","profanityAction":"Marked","profanityMarker":"Asterisk"}]}]}'

6. Profanity Marked with XML Tags

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"What the hell is going on here?","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","profanityAction":"Marked","profanityMarker":"Tag"}]}]}'

7. Profanity Deleted (removed from output)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"What the hell is going on here?","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","profanityAction":"Deleted"}]}]}'

8. Auto-Detect Source Language (omit "language" field)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Bonjour, comment allez-vous?","targets":[{"language":"en","deploymentName":"gpt-4o-newtest"}]}]}'

9. Multi-Target (translate to multiple languages in one call)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"The meeting is at 3pm tomorrow.","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"},{"language":"fr","deploymentName":"gpt-4o-newtest"},{"language":"de","deploymentName":"gpt-4o-newtest"}]}]}'

10. Multi-Input (translate multiple texts in one call)

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Good morning.","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]},{"text":"See you later.","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]}]}'

11. HTML Text Type

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"<p>Hello <b>world</b>, how are you?</p>","language":"en","textType":"html","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]}]}'

12. Adaptive Translation with Reference Pairs (LLM only)

Provide up to 5 example source/target pairs to guide translation style:

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Click Save to continue.","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","referenceTextPairs":[{"source":"Click OK to proceed.","target":"Pulse Aceptar para continuar."},{"source":"Click Cancel to go back.","target":"Pulse Cancelar para volver atr\u00e1s."}]}]}]}'

13. The Kitchen Sink — All LLM Options Combined

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"Hey, what the hell? The doctor said your appointment is next Monday at 10am. Do not forget it!","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest","tone":"formal","gender":"female","profanityAction":"NoAction","allowFallback":true,"referenceTextPairs":[{"source":"Do not forget your appointment.","target":"No olvide su cita m\u00e9dica."}]}]}]}'

14. NMT vs LLM Comparison (run both, compare output)

NMT version:

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"The quick brown fox jumps over the lazy dog.","language":"en","targets":[{"language":"es"}]}]}'

LLM version (same text):

curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d '{"inputs":[{"text":"The quick brown fox jumps over the lazy dog.","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]}]}'

15. Bearer Token Auth

# Step 1: Get token (valid 10 min, refresh every ~8 min)
curl -X POST "https://eastus.api.cognitive.microsoft.com/sts/v1.0/issueToken" \
  -H "Ocp-Apim-Subscription-Key: $KEY" \
  -d ""

# Step 2: Use the token (replace <TOKEN> with response from step 1)
curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{"inputs":[{"text":"Hello","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]}]}'

16. Microsoft Entra ID Auth (resource-specific endpoint)

# Obtain token via: az account get-access-token --resource https://cognitiveservices.azure.com
curl -X POST "$ENDPOINT" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ENTRA_TOKEN>" \
  -d '{"inputs":[{"text":"Hello","language":"en","targets":[{"language":"es","deploymentName":"gpt-4o-newtest"}]}]}'

Python Script (translator.py)

If you prefer Python over curl, translator.py provides all 16 examples above as ready-to-run functions.

Setup

pip install requests python-dotenv

Create a .env file (or copy .env.example):

AZURE_TRANSLATOR_ENDPOINT="https://<your-resource>.cognitiveservices.azure.com"
AZURE_TRANSLATOR_KEY="<your-foundry-resource-key>"
AZURE_DEPLOYMENT_NAME="gpt-4o-newtest"
AZURE_LOCATION="eastus2"

Usage

python translator.py          # Interactive menu — pick any example
python translator.py all      # Run all 16 examples sequentially
python translator.py 3        # Run a specific example (e.g. #3: Tone + Gender)

What's included

# Example Engine
1 Basic NMT translation NMT
2 LLM via deploymentName LLM
3 Tone + Gender LLM
4–7 Profanity handling (NoAction, Asterisk, Tag, Deleted) LLM
8 Auto-detect source language LLM
9 Multi-target (one text → multiple languages) LLM
10 Multi-input (batch texts in one call) LLM
11 HTML text type LLM
12 Adaptive translation (reference pairs) LLM
13 Kitchen sink (all options combined) LLM
14 NMT vs LLM side-by-side comparison Both
15 Bearer token authentication LLM
16 Mixed NMT + LLM targets in one call Both

The script auto-detects which engine handled each response — if the response contains sourceCharacters it was NMT, if it contains instructionTokens/sourceTokens/responseTokens/targetTokens it was LLM.

You can also import translator and call the functions directly (e.g. translator.translate(...)) to integrate into your own code.


Endpoint + Key Compatibility Matrix

Confirmed via testing:

Scenario Result
Resource-specific endpoint + Foundry key + NMT Works (sourceCharacters in response)
Resource-specific endpoint + Foundry key + LLM Works (token fields in response)
Global endpoint + Foundry key + NMT 401 Unauthorized
Global endpoint + Foundry key + LLM 401 Unauthorized
Global endpoint + Translator key + NMT Works (sourceCharacters in response)
Global endpoint + Translator key + LLM 400 "deployment not found"

Conclusion: For LLM translation, you must use the resource-specific endpoint with the Foundry (AIServices) resource key. The global endpoint cannot see Foundry deployments. The Foundry key on the resource-specific endpoint handles both NMT and LLM. The standalone Translator key on the global endpoint is NMT-only.


Troubleshooting and Gotchas

"Failed to get information on deployment. Please double check that the deployment exists."

This is the most common error. It means the Translator API can't find your LLM deployment. Check:

  1. Are you using the resource-specific endpoint? The global endpoint (api.cognitive.microsofttranslator.com) cannot discover Foundry deployments. Use https://<your-resource>.cognitiveservices.azure.com/translator/text/translate instead.

  2. Is your resource Kind AIServices? Go to Azure Portal > your resource > Overview. The Kind must be AIServices (Foundry multi-service). If it's OpenAI (standalone Azure OpenAI), the Translator API can't see its deployments.

  3. Does the deployment name match exactly? The deploymentName in the API call must match the deployment name in your Foundry resource exactly -- not the model name. If you deployed GPT-4o and named it my-gpt4o, use my-gpt4o, not gpt-4o.

  4. Is the deployment in the same resource as the key you're using? If you have multiple resources, make sure the key belongs to the resource that contains the deployment.

"The request is not authorized because credentials are missing or invalid." (401)

  • You're using a Foundry/AIServices key on the global endpoint. The global endpoint doesn't accept those keys.
  • Switch to the resource-specific endpoint: https://<your-resource>.cognitiveservices.azure.com/translator/text/translate?api-version=2025-10-01-preview

The /translator/text/translate path — where did it come from?

The preview API docs only document the global endpoint path (/translate). When using a resource-specific endpoint with an AIServices/Foundry resource, Azure Cognitive Services namespaces APIs by service. The Translator service path becomes /translator/text/translate. This pattern is documented in the older GA Translator v3.0 docs but is missing from the preview API documentation.

I have a separate Translator resource AND a Foundry resource — which key do I use?

  • For NMT only via global endpoint: Use the Translator resource key + Ocp-Apim-Subscription-Region header
  • For LLM (or both NMT and LLM): Use the Foundry resource key + resource-specific endpoint
  • You cannot mix them (Translator key on Foundry endpoint or vice versa)

Linux vs PowerShell syntax

  • Linux/macOS: Use curl with \ for line continuation
  • PowerShell: Use curl.exe with ` (backtick) for line continuation
  • Windows cmd: Use curl with ^ for line continuation

Notes

  • LLM-only features: tone, gender, referenceTextPairs, adaptiveDatasetId
  • LLM billing: token-based (instructionTokens + sourceTokens + targetTokens)
  • NMT billing: character-based (sourceCharacters)
  • Max 50 array elements for LLM (vs 1,000 for NMT)
  • Max 5,000 chars per element for LLM (vs 50,000 for NMT)
  • Max 5 referenceTextPairs per target
  • LLM translation is NOT available with private endpoints
  • LLM requires an AIServices (Foundry) resource, not a standalone Azure OpenAI resource
  • Resource-specific endpoint (/translator/text/translate) is required for AIServices/Foundry resources; global endpoint requires Ocp-Apim-Subscription-Region header
  • 100+ languages supported; LLM/adaptive may support fewer -- check the language support page
  • LLM latency depends on computing resources allocated during model deployment
  • This is a preview API -- features may change before GA