Send the JSON you already return. Get the same shape back in the locale you asked for.
API base URL: use http://localhost:3000 with local Compose, or https://api.modelocale.com when hosted.
Get an API key
A — In the app (humans)
Best when you are signing up yourself.
- Open Sign up and enter your email.
- Open the magic link — we verify, then send you to set a password.
- From
/app, complete billing when you want a durableml_live_…key.
The trial key is minted when you verify. It lasts about one hour and is capped (25 ensure misses, 10 000 characters, 10 distinct endpoint URLs). Over cap → 402. The browser never shows the trial key; if an agent started this signup, it already has the key from the status poll.
B — Agent-friendly trial (magic link)
Best when a human is watching an agent in the terminal.
# 1) Start signup
curl -s -X POST 'https://api.modelocale.com/api/v1/signup/start' \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]"}'
# → { "signup_id":"…", "expires_at":"…" }
# 2) Human opens the magic-link email (or the link printed in API logs locally)
# Verify mints the trial key, then the browser opens /app/set-password
# 3) Poll until ready — trial_api_key is returned ONCE
curl -s 'https://api.modelocale.com/api/v1/signup/status/SIGNUP_ID'
# → { "status":"ready", "trial_api_key":"ml_trial_…", "trial_expires_at":"…", … }
export MODELOCALE_API_KEY='ml_trial_…'C — Durable live key (after billing)
In /app, activate billing (Stripe Checkout), then mint a durable ml_live_… key for .env. Live keys require billing to be active on the team.
export MODELOCALE_API_KEY='ml_live_…'D — Local seed (dev only)
After Compose + prisma:seed, you can use ml_live_dev_seed_modelocale_local against http://localhost:3000 without signup.
Want product updates without signing up yet? Use the waitlist.
Ensure (create or refresh)
Every translations request needs your project API key:
Authorization: Bearer ml_…You have an English menu payload. Ask Modelocale for French:
curl -sS -X PUT 'https://api.modelocale.com/api/v1/translations' \
-H "Authorization: Bearer $MODELOCALE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"endpoint_url": "https://api.acme.com/v1/menus",
"lang": "fr",
"source_lang": "en",
"data": {
"id": "m1",
"title": "Lunch",
"description": "Soups and sandwiches",
"sku": "LNCH"
},
"skip_paths": ["id", "sku"]
}'What comes back — same keys and ids, translated string leaves:
{
"data": {
"id": "m1",
"title": "Déjeuner",
"description": "Soupes et sandwiches",
"sku": "LNCH"
},
"meta": {
"status": "created",
"endpoint_url": "https://api.acme.com/v1/menus",
"lang": "fr",
"source_lang": "en",
"leaf_change_count": 2,
"expires_at": "2026-07-30T12:00:00.000Z"
}
}id and sku stayed put because of skip_paths. meta.status is created on first write, updated when source changes, or cache_hit when nothing needed MT.
Get (pure read)
When the locale is already warm and you do not have (or need) the source body again:
curl -sS -G 'https://api.modelocale.com/api/v1/translations' \
-H "Authorization: Bearer $MODELOCALE_API_KEY" \
--data-urlencode 'endpoint_url=https://api.acme.com/v1/menus' \
--data-urlencode 'lang=fr'Response is the localized JSON only (no meta wrapper). GET never translates and never uses your character or endpoint allowance. Missing or expired → 404 — fall back to your source language.
Next
Read Concepts for URL identity, trial vs live keys, TTL, and sibling invalidation. Language codes: Languages. Match volume to a plan on Pricing. For a fuller walkthrough, see Localize a JSON API response.