POST /v1/localizations
GET /v1/localizations/jobs/:jobId
Translate and culturally localize an app’s store metadata — title, subtitle, keywords, promotional text, description, and what’s new — into up to 10 languages in a single run. An LLM adapts each field for native speakers (not a word-for-word translation) and respects App Store character limits.
The work runs asynchronously on a background job, so POST /v1/localizations returns a jobId immediately (HTTP 202). Poll GET /v1/localizations/jobs/:jobId for the per-locale results.
When the app is connected in your Appeeky account, each translation is saved as an editable draft (visible in the dashboard Localizations tab). Set publish: true to push each translation straight to the live App Store Connect listing after translating. Direct publishing requires a connected App Store Connect key — see App Store Connect.
Create a run
Request Body
| Field | Type | Required | Default | Description |
|---|
appId | string | Yes* | — | App Store numeric id (preferred). Provide this or userAppId. |
userAppId | string | Yes* | — | Appeeky user_apps row id (uuid). Alternative to appId. |
locales | string[] | Yes | — | BCP-47 target locales, e.g. ["tr","de-DE","ja","pt-BR"]. 1–10 entries. |
sourceLocale | string | No | en-US | Locale to translate from. |
publish | boolean | No | false | When true, publish each translation to the live App Store Connect listing. |
source | object | No | — | Source copy override (see below). Falls back to the app’s existing draft / base metadata when omitted. |
* Provide either appId or userAppId.
source object (all fields optional, all string \| null):
| Field | Description |
|---|
title | App name |
subtitle | Subtitle |
description | Long description |
keywords | Comma-separated keyword field |
promotional_text | Promotional text |
whats_new | Release notes / what’s new |
Cost is metered at 3 credits per requested locale (one LLM call each). A 5-language run costs 15 credits. The poll endpoint is free.
Code Examples
curl -X POST "https://api.appeeky.com/v1/localizations" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"appId": "913335252",
"locales": ["tr", "de-DE", "ja", "pt-BR"],
"sourceLocale": "en-US",
"publish": false
}'
Response (202 Accepted)
{
"data": {
"jobId": "f3c1a2b4-...",
"triggerRunId": "run_...",
"status": "queued",
"locales": ["tr", "de-DE", "ja", "pt-BR"],
"publish": false,
"tracked": true
}
}
| Field | Type | Description |
|---|
jobId | string | Use this to poll for results. |
triggerRunId | string | Underlying background run id (for support/debugging). |
status | string | Always queued on creation. |
tracked | boolean | Whether the app is connected in Appeeky (drafts are saved when true). |
Poll for results
GET /v1/localizations/jobs/:jobId
Response
{
"data": {
"jobId": "f3c1a2b4-...",
"status": "completed",
"appId": "913335252",
"sourceLocale": "en-US",
"locales": ["tr", "de-DE", "ja"],
"publish": false,
"results": [
{
"locale": "tr",
"status": "translated",
"saved": true,
"published": false,
"fields": {
"title": "Block Blast! - Blok Bulmaca",
"subtitle": "Rahatlatıcı blok oyunu",
"keywords": "blok,bulmaca,puzzle,zeka,rahatlatıcı,oyun",
"promotional_text": "Milyonlarca oyuncuya katıl!",
"description": "...",
"whats_new": null
}
},
{
"locale": "ja",
"status": "failed",
"saved": false,
"published": false,
"fields": null,
"error": "..."
}
],
"error": null,
"createdAt": "2026-06-20T21:00:00.000Z",
"updatedAt": "2026-06-20T21:00:42.000Z"
}
}
Job Fields
| Field | Type | Description |
|---|
status | string | queued | processing | completed | failed |
results | array | One entry per locale (see below); null until processing. |
error | string | Set only if the whole job failed. |
Result Fields (per locale)
| Field | Type | Description |
|---|
locale | string | The target locale. |
status | string | translated (draft ready) | published (pushed to store) | failed. |
fields | object | The localized metadata, or null on failure. |
saved | boolean | Whether the translation was saved as a draft (only when the app is tracked). |
published | boolean | Whether it was published to the live App Store Connect listing. |
error | string | Failure reason for this locale, when applicable. |
| Tool | Description |
|---|
localize_app_metadata | Start a batch translation run; returns a jobId. |
get_localization_job | Poll status and per-locale results for a run. |
Errors
| Status | Code | When |
|---|
| 400 | BAD_REQUEST | locales empty, or neither appId nor userAppId provided |
| 400 | TOO_MANY_LOCALES | More than 10 locales requested in one run |
| 400 | NO_SOURCE | No source copy to translate and the app isn’t connected |
| 401 | UNAUTHORIZED | Missing or invalid credentials |
| 403 | FORBIDDEN | Polling a job that belongs to another account |
| 404 | APP_NOT_FOUND | userAppId not found for this user |
| 404 | JOB_NOT_FOUND | Unknown jobId |