Skip to content

Quickstart · Node.js

Updated: September 15, 2026

Target: a Node service serving translated strings, in under ten minutes.

Use azbox-node 0.2.0 or newer. 0.1.0 and 0.1.1 never worked against the API. If you have one of them installed, npm install azbox-node@latest is the whole fix: the class and methods are the same.

What the client does

azbox-node is one class:

const client = new AzboxClient({ apiKey, projectId, language })
await client.getTranslations({ afterUpdatedAt? }) // { "home.title": "Bienvenido", … }
await client.getKeywords({ afterUpdatedAt? })     // the raw API response

Three things to know:

  • It only reads. Keywords are created in the dashboard; there is no upload method.
  • One language per client. For several languages, one client each.
  • No t() function. You get the dictionary and look strings up yourself. That is step 4.

Before you start

  • Node 18 or newer — the client uses the global fetch
  • An AZbox project with its Project ID and an API key (dashboard → Settings → API keys)

1 · Create the project and import your strings

In the dashboard: Create Project, then import your en.json (i18next format is read natively, nested keys included) or add keywords with Add Keyword.

2 · Install

npm install azbox-node

Works with both import and require.

3 · Fetch

import { AzboxClient } from "azbox-node";

const client = new AzboxClient({
  apiKey: process.env.AZBOX_API_KEY,
  projectId: process.env.AZBOX_PROJECT_ID,
  language: "ES",
});

const translations = await client.getTranslations();
// { "home.title": "Bienvenido", … }

One call to GET /v1/projects/:id/keywords. Keywords that have no text yet in that language are left out. If you need everything the API returns, getKeywords() gives you [{ id, data: { keyword, translation, … } }]; the key is data.keyword, and id is an internal identifier.

4 · Build the lookup

Calling the API per string would be one HTTP request per string. Load once at startup:

import { AzboxClient } from "azbox-node";

const dictionaries = new Map<string, Record<string, string>>();

export async function loadLanguage(language: string) {
  const client = new AzboxClient({
    apiKey: process.env.AZBOX_API_KEY!,
    projectId: process.env.AZBOX_PROJECT_ID!,
    language,
  });
  dictionaries.set(language, await client.getTranslations());
}

export function t(language: string, key: string, params?: Record<string, string | number>) {
  const value = dictionaries.get(language)?.[key];
  if (value === undefined) return key;
  return params
    ? value.replace(/\{(\w+)\}/g, (m, p) => String(params[p] ?? m))
    : value;
}

Interpolation is yours: the API returns the string as stored, placeholders included.

5 · Refresh only what changed

const changed = await client.getTranslations({ afterUpdatedAt: lastSync });
dictionaries.set("ES", { ...dictionaries.get("ES"), ...changed });

This is what makes over-the-air work on the server: correct a string in the dashboard and the next refresh picks it up without a deploy. Store the time of the response you last applied, not the current clock. A failed refresh is not fatal — you still hold the previous dictionary in memory.

6 · In CI

env:
  AZBOX_API_KEY: ${{ secrets.AZBOX_API_KEY }}
  AZBOX_PROJECT_ID: ${{ secrets.AZBOX_PROJECT_ID }}

If all you need in CI is to write translation files to disk, the CLI does it without writing code.

If something fails

Errors are thrown as AzboxError, with status and the API’s detail.

  • 401 — the API key is wrong or was revoked. Create a new one in the dashboard.
  • 403 — the key has no access to that project, or is bound to a different one.
  • An empty dictionary — either the project has no keywords yet (getKeywords() returns []), or the language code is not one the project uses. An unknown code is not an error: every keyword comes back without a translation. Check the codes in the project’s settings.
  • fetch is not available — Node older than 18.

Next

Call to action background

Start Global Growth Today

Upload your language files, get them translated, and keep every locale in sync as your product keeps changing.

Get Started - It's Free