API Reference
Complete reference for the Movabase REST API. Use API keys to access project endpoints from CI/CD pipelines, CLI tools, and scripts.
Overview
Movabase provides a REST API for managing translations programmatically. All endpoints under /api/projects/{project-id}/... accept API key authentication via the Authorization: Bearer <key> header.
Base URL: https://app.movabase.com
Authentication
All endpoints in the Public API section accept API key authentication:
Authorization: Bearer loko_YOUR_API_KEYAPI keys are project-scoped — a key only grants access to the project it was created for.
Managing API Keys
# Create a key (via the web UI or session auth)
POST /api/projects/{project-id}/keys
{ "name": "My CI/CD Key" }
# List keys
GET /api/projects/{project-id}/keys
# Revoke a key
DELETE /api/projects/{project-id}/keys/{key-id}Keys are prefixed with loko_ and are shown only once at creation time. Store them immediately.
Quick Reference
| Endpoint | Methods | Description |
|---|---|---|
/api/projects/{id} | GET, PUT, DELETE | Project info and settings |
/api/projects/{id}/translations | GET, POST, PATCH, PUT, DELETE | Translation CRUD and export |
/api/projects/{id}/translations/trash | GET, POST, DELETE | Soft-deleted translations |
/api/projects/{id}/translations/keys | GET | List unique translation keys |
/api/projects/{id}/translations/history | GET | Change history |
/api/projects/{id}/files | GET, POST, PATCH, DELETE | File management |
/api/projects/{id}/languages | GET, POST, PATCH, DELETE | Language management |
/api/projects/{id}/keys | GET, POST | API key management |
/api/projects/{id}/keys/{key-id} | DELETE | Revoke API key |
/api/projects/{id}/bitbucket | GET, POST, DELETE | Bitbucket integration |
/api/projects/{id}/bitbucket/push | POST | Create PR with translations |
/api/projects/{id}/bitbucket/sync | POST | Import translations from repo |
Input Limits
| Field | Max Length |
|---|---|
| Translation key | 256 chars |
| Translation value | 8,192 chars |
| File name | 256 chars |
| Project name | 32 chars |
| API key name | 128 chars |
| Request body | 4 MiB |
CI/CD Examples
Export translations (JSON)
curl -H "Authorization: Bearer loko_YOUR_API_KEY" \
"https://app.movabase.com/api/projects/PROJECT_ID/translations" \
-o translations.jsonExport as ZIP
curl -H "Authorization: Bearer loko_YOUR_API_KEY" \
"https://app.movabase.com/api/projects/PROJECT_ID/translations?zip=true" \
-o translations.zipExport in PO (gettext) format
curl -H "Authorization: Bearer loko_YOUR_API_KEY" \
"https://app.movabase.com/api/projects/PROJECT_ID/translations?format=po&zip=true" \
-o translations.zipCreate a translation
curl -X POST \
-H "Authorization: Bearer loko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
"https://app.movabase.com/api/projects/PROJECT_ID/translations" \
-d '{
"key": "welcome.message",
"fileName": "common.json",
"values": { "en": "Welcome", "es": "Bienvenido" }
}'Bulk upsert translations
curl -X PUT \
-H "Authorization: Bearer loko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
"https://app.movabase.com/api/projects/PROJECT_ID/translations" \
-d '{
"operation": "bulk-upsert",
"fileName": "common.json",
"languageCode": "en",
"translations": [
{ "key": "greeting", "value": "Hello" },
{ "key": "farewell", "value": "Goodbye" }
]
}'GitHub Actions
name: Download Translations
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
download:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fetch translations
env:
MOVABASE_API_KEY: ${{ secrets.MOVABASE_API_KEY }}
MOVABASE_PROJECT_ID: ${{ secrets.MOVABASE_PROJECT_ID }}
run: |
curl -H "Authorization: Bearer $MOVABASE_API_KEY" \
"https://app.movabase.com/api/projects/$MOVABASE_PROJECT_ID/translations?zip=true" \
-o translations.zip
unzip -o translations.zip -d src/locales/
- name: Commit translations
run: |
git config user.name "Movabase Bot"
git config user.email "bot@movabase.com"
git add src/locales/
git diff --quiet && git diff --staged --quiet || git commit -m "chore: update translations"
git pushPython script
import requests
API_KEY = "loko_YOUR_API_KEY"
PROJECT_ID = "your-project-id"
BASE_URL = "https://app.movabase.com"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def export_translations(format="json", as_zip=False):
params = {"format": format}
if as_zip:
params["zip"] = "true"
resp = requests.get(
f"{BASE_URL}/api/projects/{PROJECT_ID}/translations",
headers=HEADERS, params=params,
)
resp.raise_for_status()
return resp.content if as_zip else resp.json()
def create_translation(key, file_name, values):
resp = requests.post(
f"{BASE_URL}/api/projects/{PROJECT_ID}/translations",
headers={**HEADERS, "Content-Type": "application/json"},
json={"key": key, "fileName": file_name, "values": values},
)
resp.raise_for_status()
return resp.json()
def list_languages():
resp = requests.get(
f"{BASE_URL}/api/projects/{PROJECT_ID}/languages",
headers=HEADERS,
)
resp.raise_for_status()
return resp.json()["languages"]Error Responses
{ "error": "Error message describing what went wrong" }| Status | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad request (validation error) |
| 401 | Unauthorized (missing or invalid API key) |
| 403 | Forbidden (API key doesn't match this project) |
| 404 | Not found |
| 500 | Internal server error |