The Lingo.dev localization API translates key-value data through a configured localization engine. One HTTP call - your strings go in, translated strings come back, with glossary rules, brand voice, and model selection applied automatically.
When to Use the API#
Use the localization API when translations happen at runtime or in a backend service - not at build time.
| Use case | Example |
|---|---|
| Dynamic content | Translate course descriptions, lesson titles, or quiz questions stored in a database |
| User-generated content | Translate reviews, comments, or forum posts on demand |
| API responses | Return localized content from your backend based on the user's locale |
| Notifications | Translate email subjects, push notifications, or in-app messages before sending |
Build-time vs runtime
If your content lives in static files (JSON, Markdown, .strings), the CLI or CI/CD integration is a better fit. The API is designed for localizing content on the backend.
Prerequisites#
Create a localization engine
Every API call runs through a localization engine - the configuration that determines which LLM model, glossary, brand voice, and instructions apply. Create one in the Lingo.dev dashboard.
Generate an API key
API requests authenticate with an X-API-Key header. Generate a key in the API Keys section. Keys are shown once at creation - store yours securely.
Localizing Content#
Send a POST request to the localize endpoint with your source locale, target locale, and key-value data. The full request/response schema is documented in the API reference.
This example translates a paragraph from a JavaScript course into Spanish:
const content = {
intro: "JavaScript is a programming language that powers the interactive elements of most websites. When you click a button, submit a form, or see content update without the page reloading, JavaScript is making that happen.",
};
const response = await fetch("https://api.lingo.dev/process/localize", {
method: "POST",
headers: {
"X-API-Key": "your_api_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
engineId: "eng_abc123",
sourceLocale: "en",
targetLocale: "es",
data: content,
}),
});
const { data } = await response.json();
// {
// intro: "JavaScript es un lenguaje de programacion que impulsa los elementos interactivos de la mayoria de los sitios web. Cuando haces clic en un boton, envias un formulario o ves contenido actualizarse sin que la pagina se recargue, JavaScript lo esta haciendo posible."
// }Keys are preserved: you send intro and get intro back. The engine translates only the values.
Structuring Keys#
The data object is flat - each key maps to a single string. Structure your keys so they carry semantic context:
const content = {
"variables.intro": "Variables are containers for storing data values. In JavaScript, you declare them with let, const, or var.",
"variables.example": "Use const for values that never change, and let for values that do.",
"variables.exercise": "Declare a variable called age and assign it your age as a number.",
};Semantically grouped keys help the localization engine produce more coherent translations. The engine sees all keys in a single request as related context - variables.intro and variables.example translate more consistently when sent together than separately.
Technical terms
Terms like "const" or "let" are programming lingo that should not be translated. Use a glossary to mark terms as non-translatable, or map them to locale-specific equivalents. If you use an AI coding assistant like Claude Code or Cursor, the Localization MCP can help configure glossary rules as part of your development workflow.
Localizing on Save#
The typical pattern is to translate content when it's created or updated - not when it's read. This way, translated content is already in the database when a user requests it.
app.post("/api/lessons", async (req, res) => {
const lesson = await db.lessons.create(req.body);
const content = {
intro: lesson.intro,
example: lesson.example,
exercise: lesson.exercise,
};
const targetLocales = ["es", "fr", "de", "ja"];
const translations = await Promise.all(
targetLocales.map(async (targetLocale) => {
const response = await fetch("https://api.lingo.dev/process/localize", {
method: "POST",
headers: {
"X-API-Key": process.env.LINGODOTDEV_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
sourceLocale: "en",
targetLocale,
data: content,
}),
});
const { data } = await response.json();
return { locale: targetLocale, data };
})
);
await db.lessonTranslations.insertMany(
translations.map((t) => ({
lessonId: lesson.id,
locale: t.locale,
...t.data,
}))
);
res.json(lesson);
});Reading localized content then becomes a simple database lookup - no API call needed at read time:
app.get("/api/lessons/:id", async (req, res) => {
const locale = req.query.locale || "en";
if (locale === "en") {
const lesson = await db.lessons.findById(req.params.id);
return res.json(lesson);
}
const translation = await db.lessonTranslations.findOne({
lessonId: req.params.id,
locale,
});
res.json(translation);
});