The MultiLocale REST API lets your integration read and manage localization projects, phrase keys, and per-locale translation values. Import existing dictionaries, download current translation files for a build, machine-translate missing values, and keep every application reading one shared workspace.
All endpoints are relative to https://api.multilocale.com. Create an API key in your MultiLocale dashboard, then authenticate every request with it. Keys are read-only by default, can be limited to a single project, and every response carries RateLimit headers so clients can pace themselves.
apiKey — HTTP Basic auth carrying only the API key secret: Authorization: Basic base64(<key secret>).
accessToken — Operator session token issued by the MultiLocale dashboard: Authorization: Token <access token>.
oauth2 — Authrice authorization-code flow with PKCE for delegated access.
You can evaluate the API without an account: the keyless sandbox at /api/v1/sandbox/phrases returns demonstration phrases in the authenticated response shape, and the sandbox translation job demonstrates the asynchronous 202-and-poll pattern end to end.
Example requests
Read the keyless sandbox, no account or key needed:
curl https://api.multilocale.com/api/v1/sandbox/phrases
List the French phrases of one project with a scoped API key:
curl "https://api.multilocale.com/api/v1/phrases?project=my-app&language=fr&limit=10" \ -H "Authorization: Basic $(printf %s "$MULTILOCALE_API_KEY" | base64)"
Create a phrase with a write-scoped key, safely retryable with an idempotency key:
curl -X POST https://api.multilocale.com/api/v1/phrases \
-H "Authorization: Basic $(printf %s "$MULTILOCALE_API_KEY" | base64)" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 1f0e5a1e-add-welcome" \
-d '{"key":"Welcome","value":"Welcome","language":"en","projects":["my-app"]}'The guides, the CLI and the React and Next.js integration are documented on the developer documentation site.
Phrases
List phrases
Lists the phrases of your organization. A phrase is one {key, value, language} triple belonging to one or more projects. Filter with project, key and language. Requires the phrases:read scope. A key scoped to a project only ever sees that project's phrases. For stable traversal, set pagination=cursor; the response becomes {items, nextCursor} and is ordered by _id. Pass nextCursor back as cursor until it is null. Existing array responses and offset pagination remain available when cursor pagination is not requested.
| Name | In | Type | Description |
|---|---|---|---|
| project | query | string | Project name |
| key | query | string | Phrase key (URL-encoded) |
| language | query | string | |
| fields | query | string | Comma-separated projection of fields to return |
| pagination | query | string (cursor) | Set to cursor for a stable page envelope |
| cursor | query | string | Opaque nextCursor from the preceding cursor page |
| limit | query | integer | Optional bounded page size (maximum 2001; defaults to 100 in cursor mode) |
| skip | query | integer | Optional page offset (maximum 10000) |
| sortField | query | string (_id | key | language) | |
| sortDirection | query | string (ASC | DESC) |
| Status | Meaning |
|---|---|
| 200 | Array of phrases, or {items, nextCursor} in cursor mode |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the phrases:read scope |
| 429 | API key rate limit exceeded |
Create or update phrases
Upserts one phrase or an array of phrases. Emits phrase.created for rows that did not exist and phrase.updated for rows that did — one event per row, not per request. Requires the phrases:write scope. Send Idempotency-Key to make retries safe for 24 hours.
| Name | In | Type | Description |
|---|---|---|---|
| Idempotency-Key | header | string | Unique retry key retained for 24 hours (maximum 255 characters) |
| Status | Meaning |
|---|---|
| 200 | The upserted phrase, or the array of upserted phrases |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the phrases:write scope |
| 409 | Idempotency key is in flight or was reused with different input |
| 429 | API key rate limit exceeded |
Delete phrases
Deletes every translation of one key in one project — all languages at once — and emits one phrase.deleted per deleted row. Requires the phrases:write scope. Send Idempotency-Key to make retries safe for 24 hours.
| Name | In | Type | Description |
|---|---|---|---|
| keyrequired | query | string | Phrase key (URL-encoded) |
| Idempotency-Key | header | string | Unique retry key retained for 24 hours (maximum 255 characters) |
| projectrequired | query | string | Project name |
| Status | Meaning |
|---|---|
| 200 | The deleted phrases |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the phrases:write scope |
| 404 | Nothing matched |
| 409 | Idempotency key is in flight or was reused with different input |
| 429 | API key rate limit exceeded |
Create or update a batch of phrases
Upserts an array of phrases in one authenticated request and returns the resulting array in input order. Each row emits its own created or updated webhook event. Requires the phrases:write scope. Send Idempotency-Key to make retries safe for 24 hours.
| Name | In | Type | Description |
|---|---|---|---|
| Idempotency-Key | header | string | Unique retry key retained for 24 hours (maximum 255 characters) |
| Status | Meaning |
|---|---|
| 200 | The upserted phrases in input order |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the phrases:write scope |
| 409 | Idempotency key is in flight or was reused with different input |
| 429 | API key rate limit exceeded |
Update a phrase
Replaces a phrase you own and emits phrase.updated. Answers 404 — not 403 — for a phrase belonging to another organization, so ids cannot be probed. Requires the phrases:write scope. Send Idempotency-Key to make retries safe for 24 hours.
| Name | In | Type | Description |
|---|---|---|---|
| phraseIdrequired | path | string | |
| Idempotency-Key | header | string | Unique retry key retained for 24 hours (maximum 255 characters) |
| Status | Meaning |
|---|---|
| 200 | The updated phrase |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the phrases:write scope |
| 404 | No such phrase in your organization |
| 409 | Idempotency key is in flight or was reused with different input |
| 429 | API key rate limit exceeded |
Projects
List projects
Lists the projects of your organization. Requires the projects:read scope. A key scoped to a project sees only that project.
| Status | Meaning |
|---|---|
| 200 | Array of projects |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the projects:read scope |
| 429 | API key rate limit exceeded |
Create a project
Creates a project in your organization and emits project.created. Requires the projects:write scope. Send Idempotency-Key to make retries safe for 24 hours.
| Name | In | Type | Description |
|---|---|---|---|
| Idempotency-Key | header | string | Unique retry key retained for 24 hours (maximum 255 characters) |
| Status | Meaning |
|---|---|
| 200 | The created project |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the projects:write scope |
| 409 | Idempotency key is in flight or was reused with different input |
| 429 | API key rate limit exceeded |
Get a project by id
Answers 404 — not 403 — for a project belonging to another organization, so ids cannot be probed. Requires the projects:read scope.
| Name | In | Type | Description |
|---|---|---|---|
| projectIdrequired | path | string |
| Status | Meaning |
|---|---|
| 200 | The project |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the projects:read scope |
| 404 | No such project in your organization |
| 429 | API key rate limit exceeded |
Update a project
Updates a project you own and emits project.updated. Answers 404 — not 403 — for a project belonging to another organization. Requires the projects:write scope. Send Idempotency-Key to make retries safe for 24 hours.
| Name | In | Type | Description |
|---|---|---|---|
| projectIdrequired | path | string | |
| Idempotency-Key | header | string | Unique retry key retained for 24 hours (maximum 255 characters) |
| Status | Meaning |
|---|---|
| 200 | The updated project |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the projects:write scope |
| 404 | No such project in your organization |
| 409 | Idempotency key is in flight or was reused with different input |
| 429 | API key rate limit exceeded |
Get a project by name
Project names are unique per organization, not globally, so the lookup is always scoped to your organization. Requires the projects:read scope.
| Name | In | Type | Description |
|---|---|---|---|
| projectNamerequired | path | string |
| Status | Meaning |
|---|---|
| 200 | The project |
| 401 | Missing or invalid credentials |
| 403 | API key is missing the projects:read scope |
| 404 | No such project in your organization |
| 429 | API key rate limit exceeded |
Sandbox
Read sandbox phrases without authentication
Returns a fixed set of demonstration phrases in the same {key, value, language} shape as authenticated phrase reads. No account, credential, or key is required, so agents can evaluate the API before onboarding. Responses carry the standard RateLimit response headers and the anonymous pacing limit applies.
| Status | Meaning |
|---|---|
| 200 | Demonstration phrases. |
| 429 | Anonymous rate limit exceeded; retry after Retry-After seconds. |
Start a demonstration asynchronous translation job
Demonstrates the API's asynchronous-job pattern without authentication. The response is 202 Accepted with a Location header pointing at the job resource and a body carrying the job _id and status. Poll the Location URL until the status is succeeded, then read the translations from the job body. The job is deterministic fixture work that completes about two seconds after creation.
| Status | Meaning |
|---|---|
| 202 | Job accepted; poll the Location URL for the result. |
| 429 | Anonymous rate limit exceeded; retry after Retry-After seconds. |
Poll a demonstration translation job
Reads the status of a demonstration job started at POST /api/v1/sandbox/translationjobs. While the job runs the status is running; afterwards it is succeeded and the body carries the translated phrases. No authentication is required.
| Name | In | Type | Description |
|---|---|---|---|
| jobIdrequired | path | string |
| Status | Meaning |
|---|---|
| 200 | Current job state. |
| 404 | Unknown job id. |