REST API reference

Every op, its input schema and a curl example, generated from the ops registry.

Every action in Glossa is an op. Call one with POST https://glossa-meterapp.vercel.app/api/v1/{op} and its input as a JSON body. Read-only ops also answer GET with the input as URL-encoded JSON in ?input=. This page is generated from the same registry that serves the API, so it lists exactly what the API accepts.

  • Auth: Authorization: Bearer gls_… (or X-Api-Key). With an OAuth token, pick a workspace with X-Glossa-Workspace: <slug>.
  • Errors are RFC 9457 application/problem+json with a code and request_id: see Errors.
  • Machine-readable: OpenAPI 3.1, the op catalog and llms-full.txt.
Your first call
curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_stats \  -H "Authorization: Bearer gls_…"

All ops

Workspace

Settings, stats and the activity log.

Get workspace · POST /api/v1/get_workspace or GET …?input=

The workspace this credential belongs to: name, source locale and the product context every AI prompt starts with. Call first to orient yourself.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_workspace \  -H "Authorization: Bearer gls_…"

update_workspace

writeowner or admin

Update workspace · POST /api/v1/update_workspace

Change the workspace name, source locale or product context. The product context (what the app is, who uses it, tone) is prepended to every translation and audit prompt, so a good one improves every translation.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/update_workspace \  -H "Authorization: Bearer gls_…"

Get stats · POST /api/v1/get_stats or GET …?input=

Counts across the workspace (projects, units, keys, open tasks) and per-locale translation coverage per project.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_stats \  -H "Authorization: Bearer gls_…"

List activity · POST /api/v1/list_activity or GET …?input=

Who changed what, from which surface (dashboard, api, mcp, cli, ai), newest first.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_activity \  -H "Authorization: Bearer gls_…"

Projects

Apps or repos, each with its source and target locales.

List projects · POST /api/v1/list_projects or GET …?input=

Every project (app) in the workspace with its target locales. Strings are shared across projects; files belong to one.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_projects \  -H "Authorization: Bearer gls_…"

Create project · POST /api/v1/create_project

Add a project (one app, site or service) with the locales it ships in. Push files to it with push_file.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/create_project \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"name":"CI"}'

Update project · POST /api/v1/update_project

Change a project's name, description, target locales or auto-translate. Adding a locale with auto_translate on queues translation of every existing string into it.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/update_project \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"project":"web"}'

Files

Push translation files in, pull any locale back out.

List files · POST /api/v1/list_files or GET …?input=

Files of a project. `path` is a pattern: `{locale}` (or `{android_locale}`) stands for each locale's copy, so one row covers en.json, es.json, ….

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_files \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"project":"web"}'

Push file · POST /api/v1/push_file

Upload a translation file in any format (JSON, YAML, xcstrings, .strings, stringsdict, strings.xml, PO, XLIFF, ARB, properties, RESX, CSV, or one Glossa learned). A source-locale file creates or updates keys and dedupes their strings into shared units across every project; another locale's file imports its translations. New strings are queued for AI translation. A format nobody can read yet starts a learn_format job instead.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/push_file \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"project":"web","path":"locales/en.json","content":"{\"home.title\": \"Welcome back\"}"}'

Pull file · POST /api/v1/pull_file or GET …?input=

Render one locale of a file in its own format, ready to write to disk. Returns {path, content}.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/pull_file \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"project":"web","path":"locales/en.json","locale":"es"}'

Formats

Detect, list and teach file formats.

Detect format · POST /api/v1/detect_format or GET …?input=

Which format Glossa would read a file as, with confidence and the runner-up candidates. Doesn't store anything.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/detect_format \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"filename":"en.json","content":"{\"home.title\": \"Welcome back\"}"}'

List formats · POST /api/v1/list_formats or GET …?input=

Built-in formats and the templates this workspace has learned, with their status.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_formats \  -H "Authorization: Bearer gls_…"

Learn format · POST /api/v1/learn_format

Ask the AI to write a template for a file format Glossa can't read yet, from a sample. Runs as a job (see get_job); the learned format is stored and reads every similar file from then on.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/learn_format \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"project":"web","path":"locales/en.json","content":"{\"home.title\": \"Welcome back\"}"}'

Save or retire a format · POST /api/v1/approve_format

Set a learned format's status (active reads files, retired stops). Optionally replace its template; the new template is validated against the stored sample first.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/approve_format \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"format":"format"}'

Strings

Deduplicated units, translations, merges and splits.

Search strings · POST /api/v1/search_units or GET …?input=

Full-text and fuzzy search across every source string, key name and translation in the workspace. Use it to find how a term is translated everywhere, spot inconsistencies, or find the unit behind a key.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/search_units \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"query":"checkout"}'

List strings · POST /api/v1/list_units or GET …?input=

Page through units (deduplicated source strings) with their translation in one locale. Filter by project and by translation status, e.g. status=missing to find what still needs translating or status=machine to review AI output.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_units \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"locale":"es"}'

Get string · POST /api/v1/get_unit or GET …?input=

One unit with every key that uses it (across projects and files), all its translations and their history.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_unit \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"unit":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Update string context · POST /api/v1/update_unit

Set a unit's description (context for translators and the AI), max length or tags. A good description fixes ambiguous strings in every locale at once; pass retranslate=true to redo its machine translations with the new context.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/update_unit \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"unit":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Set translation · POST /api/v1/set_translation

Write or correct a unit's translation in one locale. Every key sharing the unit gets it. Defaults to status reviewed; use approved for final copy. Placeholders must match the source.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/set_translation \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"unit":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10","locale":"es","text":"Bienvenido de nuevo"}'

Review translations · POST /api/v1/review_translations

Mark many translations reviewed, approved or needs_review at once, by unit and locale.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/review_translations \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"locale":"es","units":["6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"],"status":"reviewed"}'

Translate · POST /api/v1/translate

Queue AI translation. Without units: fills every missing translation of a project (or the whole workspace) in the given locales. With units: (re)translates exactly those, replacing machine output but never reviewed, approved, imported or human translations. Returns a job id (get_job).

curl -X POST https://glossa-meterapp.vercel.app/api/v1/translate \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"locales":["es"]}'

Merge strings · POST /api/v1/merge_units

Point every key of the `merge` units at the `into` unit, so they share one translation per locale. The kept unit's translations win; a merged unit's translation fills a locale the kept unit lacks. The merged units are deleted.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/merge_units \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"into":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10","merge":["6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"]}'

Split key · POST /api/v1/split_key

Give one key its own unit (a copy of the source and its translations) so it can be translated differently from the other keys that shared the string. Use when the same English means different things in different places.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/split_key \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"key_id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Scan for near-duplicates · POST /api/v1/scan_duplicates

Queue a scan for near-duplicate strings (same meaning, slightly different text) and file merge_suggestion tasks for them.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/scan_duplicates \  -H "Authorization: Bearer gls_…"

Review queue

Claim and resolve review tasks.

List review tasks · POST /api/v1/list_tasks or GET …?input=

The review queue, highest priority first. Each task has a kind, a title, a payload with everything needed to decide, and the actions it accepts (merge_review: keep_merged | split; merge_suggestion: merge_into_a | merge_into_b | keep_separate; learn_format: keep | retire | retry_with_hint | dismiss; translation_review: approve | edit | retranslate; audit_finding: apply | edit | dismiss; rule_suggestion: add | edit | dismiss; glossary_suggestion: add | dismiss).

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_tasks \  -H "Authorization: Bearer gls_…"

Claim review tasks · POST /api/v1/claim_tasks

Claim up to `limit` open tasks so parallel agents don't work the same ones. Claims expire after 30 minutes. Then decide each and call resolve_task.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/claim_tasks \  -H "Authorization: Bearer gls_…"

Resolve review task · POST /api/v1/resolve_task

Decide a task by naming one of its actions (merge_review: keep_merged | split; merge_suggestion: merge_into_a | merge_into_b | keep_separate; learn_format: keep | retire | retry_with_hint | dismiss; translation_review: approve | edit | retranslate; audit_finding: apply | edit | dismiss; rule_suggestion: add | edit | dismiss; glossary_suggestion: add | dismiss). The action is applied (split, merge, set translation, add rule, …) and the task is closed with your note. Pass text for edit actions, body for a rule edit, key_ids to choose which keys to split, hint for retry_with_hint.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/resolve_task \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"task":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10","action":"approve"}'

Glossary

Brand names and fixed terms.

List glossary · POST /api/v1/list_glossary or GET …?input=

Glossary terms: brand and product names that are never translated, and terms with a fixed translation per locale. Every translation prompt includes them.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_glossary \  -H "Authorization: Bearer gls_…"

Add or update glossary term · POST /api/v1/upsert_glossary_term

Add a term or change it. do_not_translate=true for brand names; translations maps locale → required translation (merged into the existing map).

curl -X POST https://glossa-meterapp.vercel.app/api/v1/upsert_glossary_term \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"term":"Glossa"}'

Delete glossary term · POST /api/v1/delete_glossary_term

Remove a glossary term; future translations no longer enforce it. Existing translations are unchanged.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/delete_glossary_term \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"term":"Glossa"}'

Rules

Standing instructions for every translation.

List translation rules · POST /api/v1/list_rules or GET …?input=

Standing instructions appended to every translation prompt, globally or for one locale. Audits propose new ones as rule_suggestion tasks.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_rules \  -H "Authorization: Bearer gls_…"

Add translation rule · POST /api/v1/add_rule

Add a standing instruction for future translations, e.g. "Spanish: use tú, never usted" or "Keep button labels under 20 characters". locale null applies to every language.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/add_rule \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"body":"Use tú, never usted."}'

Update translation rule · POST /api/v1/update_rule

Edit a translation rule's text, or set active=false to stop adding it to translation prompts.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/update_rule \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"rule":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Audits

Per-language quality reviews.

Run audit · POST /api/v1/run_audit

Ask the AI to review one locale holistically ("How is our Spanish? Are brand names consistent?"). It answers the question, scores the locale, and files audit_finding, glossary_suggestion and rule_suggestion tasks. Runs as a job; read the result with get_audit.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/run_audit \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"locale":"es"}'

Get audit · POST /api/v1/get_audit or GET …?input=

An audit's answer, score and findings (empty while its job runs; see job_status).

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_audit \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"audit":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

List audits · POST /api/v1/list_audits or GET …?input=

Past locale audits with their summary and score, newest first. Filter by locale.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_audits \  -H "Authorization: Bearer gls_…"

Jobs

Background AI work and its status.

Get job · POST /api/v1/get_job or GET …?input=

Status and output of a background job (translate, learn_format, audit, dedupe_scan).

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_job \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"job":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

List jobs · POST /api/v1/list_jobs or GET …?input=

Recent background jobs (translate, learn_format, audit, dedupe_scan) with status and errors, newest first.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_jobs \  -H "Authorization: Bearer gls_…"

API keys

Workspace keys for CLI, MCP and CI.

list_api_keys

readowner or admin

List API keys · POST /api/v1/list_api_keys or GET …?input=

API keys of this workspace (prefix only; the full key is shown once at creation).

curl -X POST https://glossa-meterapp.vercel.app/api/v1/list_api_keys \  -H "Authorization: Bearer gls_…"

create_api_key

writeowner or admin

Create API key · POST /api/v1/create_api_key

Create a workspace API key for the CLI, MCP or CI. The full key (gls_…) is returned only once; store it as a secret.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/create_api_key \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"name":"CI"}'

revoke_api_key

writeowner or admin

Revoke API key · POST /api/v1/revoke_api_key

Revoke an API key immediately; every CLI, CI job or MCP host using it stops working.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/revoke_api_key \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"key":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Billing

Plans, prices, checkout links and the subscription.

Get pricing · POST /api/v1/get_pricing or GET …?input=

The plans (Free, Pro, Team, Enterprise) with monthly and yearly prices in cents, AI translations included a month, member and project limits, features, and how to buy. Needs no credential over REST (GET /api/v1/get_pricing). Call before recommending or buying a plan.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_pricing \  -H "Authorization: Bearer gls_…"

Get billing · POST /api/v1/get_billing or GET …?input=

This workspace's plan, subscription status, renewal or end date, whether a card is saved (so subscribe can charge it), and usage this month against the plan (AI translations, members, projects). Pass refresh: true right after a human finished a checkout to pull the latest state from Stripe.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/get_billing \  -H "Authorization: Bearer gls_…"

subscribe

writeowner or admin

Subscribe · POST /api/v1/subscribe

Start or change this workspace's paid plan in one call, charging the card already saved for the workspace. Only after a human approved this plan and price: confirm must be true. Without a saved card (or if the card needs the human, e.g. 3-D Secure) nothing is charged and it returns status checkout_required with a checkout_url for a human to finish. A plan change is prorated and invoiced immediately. Returns {status: subscribed | changed | unchanged | checkout_required, billing}.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/subscribe \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"plan":"pro","confirm":false}'

cancel_subscription

writeowner or admin

Cancel subscription · POST /api/v1/cancel_subscription

Cancel the paid plan at the end of the current period (no refund; the plan stays until then, then the workspace is on Free). Only when a human asked: confirm must be true. resume_subscription undoes it before the period ends.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/cancel_subscription \  -H "Authorization: Bearer gls_…" \  -H "Content-Type: application/json" \  -d '{"confirm":false}'

resume_subscription

writeowner or admin

Resume subscription · POST /api/v1/resume_subscription

Undo a cancellation that has not taken effect yet, so the plan renews as before. Nothing is charged until the normal renewal date.

curl -X POST https://glossa-meterapp.vercel.app/api/v1/resume_subscription \  -H "Authorization: Bearer gls_…"