Terms and translations

Fetch translations

Pull finished translations into your application via the Public API — endpoints, response shapes, and integration patterns.

Not verified yet

Once a namespace has translated terms and you have an API key, your application can fetch translations at build time or at runtime. The two read endpoints below are the whole runtime surface — see Public API for the reference view of the same thing.

Authentication

Every request carries the API key in the Authorization header:

Authorization: Apikey <your-api-key>

(Bearer <your-api-key> is also accepted for clients that hard-code the scheme.) Keys are organization-scoped — one key can read every namespace in the org.

1. Discover language IDs

Translations are fetched per language, by numeric ID. Get the IDs once and cache them — they never change:

curl -H "Authorization: Apikey $LANGSYNC_API_KEY" \
  "https://langsync.api.norcube.com/api/v1/namespaces/web-app/languages"
[
  {
    "id": 68,
    "code": "en",
    "name": "English",
    "isDefault": true,
    "isFallback": false,
    "isCustom": false
  },
  {
    "id": 31,
    "code": "de",
    "name": "German",
    "isDefault": false,
    "isFallback": false,
    "isCustom": false
  }
]

2. Fetch translations for one language

curl -H "Authorization: Apikey $LANGSYNC_API_KEY" \
  "https://langsync.api.norcube.com/api/v1/namespaces/web-app/terms/translations?langId=31"
{
  "meta": { "timestamp": "2026-07-10T12:00:00Z" },
  "cursors": {},
  "list": [
    { "mark": "welcome.title", "value": "Willkommen" },
    { "mark": "welcome.subtitle", "value": "Schön, dass Sie hier sind" },
    { "mark": "button.submit", "value": "Absenden" }
  ]
}

Everything you need is in list: one { mark, value } pair per term. Reduce it to whatever your i18n library expects, e.g. a flat map:

const res = await fetch(
  `https://langsync.api.norcube.com/api/v1/namespaces/${ns}/terms/translations?langId=${langId}`,
  { headers: { Authorization: `Apikey ${process.env.LANGSYNC_API_KEY}` } }
).then((r) => r.json());

const messages = Object.fromEntries(res.list.map((t) => [t.mark, t.value]));

Two behaviours to design around:

  • Only translated terms are returned. A term with no stored translation in the requested language is absent from list — not present with an empty value. Configure your i18n library to fall back to your default language for missing keys.
  • Always pass langId explicitly. If you omit it, the endpoint falls back to LangSync's built-in English language — almost never what you want.

Integration patterns

Fetch at build time

For static sites and SPAs, fetch during the build and ship the JSON with your bundle. No runtime dependency on LangSync, CDN-cacheable, and a broken network at 3 a.m. can't take your copy down:

# build script
for pair in "en:68" "de:31" "fr:45"; do
  lang="${pair%%:*}"; id="${pair##*:}"
  curl -sf -H "Authorization: Apikey $LANGSYNC_API_KEY" \
    "https://langsync.api.norcube.com/api/v1/namespaces/web-app/terms/translations?langId=$id" \
    | jq '[.list[] | {(.mark): .value}] | add' > "src/locales/$lang.json"
done

Fetch at runtime with caching

For server-rendered apps, fetch on startup, cache in memory, and refresh on a TTL you're comfortable with. Translations change on human timescales — minutes of staleness is almost always fine, so cache aggressively rather than fetching per request.

Keep files in the repo instead

If you'd rather review translation changes in pull requests, flip the model: keep <lang>.json files in the repo and run nrc langsync pull (or sync) to refresh them. Your app then reads local files and never talks to the API at runtime.

Errors

StatusWhen
401 UNAUTHORIZEDMissing/invalid/revoked API key, or the namespace name doesn't exist in the key's organization.
500 INTERNAL_ERRORTransient server problem — retry with backoff.

Error bodies follow the platform shape { "type": "...", "msg": "..." } — see Limits and errors.

  • Public API — the reference for these endpoints.
  • API keys — creating and rotating credentials.

On this page