API keys authenticate requests to the localization API and the MCP server. Lingo.dev supports two flavours — pick the one that matches who or what is calling the API.
Two kinds of keys#
| Personal | Service | |
|---|---|---|
| Owner | The user who created it | None — meant for automation |
| Authorization | Inherits the creator's RBAC role + engine grants | Carries its own role and/or per-engine scope |
| If the owner loses access | Key loses access too | Unaffected; controlled by the key's own role / scope |
| Plan | Any plan | Enterprise (requires the RBAC entitlement) |
| Typical use | Local development, MCP, ad-hoc scripts | CI/CD pipelines, production integrations |
Personal keys are the default. Service keys are an organization-level artifact decoupled from any single human, which is what you want for credentials that should outlive employees and survive role changes.
Creating a key#
Open the API Keys page in the dashboard. Personal and Service live on separate tabs — the Service tab only appears when your organization has the Enterprise plan.
Click Create API key, give it a name (e.g., "Local MCP", "Max's staging key"), and copy the key from the success dialog. The key inherits your current RBAC role and per-engine grants.
Key visibility
The full API key is shown only once at creation. Copy and store it securely — it cannot be retrieved after you close the dialog.
Service keys and RBAC#
Service keys mirror the user model: a user can have an org-level role (umbrella permissions via Roles & Permissions) AND/OR per-engine grants from being added to specific engines. A service key works the same way:
- Role only — the role's permissions apply org-wide. If it includes
engine:access, the key reaches every engine in the organization. - No role + engine scope — the key is restricted to the engines you check during creation. Update the list later from the Engines x/y button next to the key.
- Role + engine scope — both authorities are additive. The role's umbrella wins if it grants
engine:access; otherwise the per-engine list is consulted. - Neither — the key authenticates but cannot reach any engine. Useful as a placeholder while you wire up the scope, but pointless in production.
Anti-escalation guards apply at create-time and on edit:
- The chosen role must belong to the same organization.
- The role's permission set must be a subset of
engine:access— broader roles (for example one that includesorg:manage_team) are rejected. - You can only add an engine to the key's scope if you yourself already have access to that engine.
If your Enterprise plan lapses
Service keys are part of the RBAC entitlement. If the entitlement is removed, every service key in the organization is deactivated — requests come back with a 403 and a message pointing at the plan, not at the engine scope. Personal keys are unaffected. Either restore the Enterprise plan or rotate to a Personal API key.
Using a key#
Pass the API key in the X-API-Key header on every request — the wire format is the same for both flavours:
curl -X POST https://api.lingo.dev/process/localize \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{"engineId": "eng_abc123", "sourceLocale": "en", "targetLocale": "de", "data": {"greeting": "Hello"}}'The same key works for both the localization API and the MCP server.
Security#
- Keys are stored as hashes — Lingo.dev cannot retrieve a key after creation. Rotate by deleting and recreating.
- Personal keys follow their creator's permissions in real time. If the creator's role is demoted or an engine grant is revoked, the key loses the same access on the next call.
- A personal key whose creator was removed from the organization keeps working only while RBAC is off (legacy behaviour). The moment RBAC is on, it is denied — rotate it before it becomes orphaned.
- Service keys carry their own authority. Editing the role or scope from the Service tab takes effect immediately; deleting the key revokes it.
- There is no limit on the number of keys per organization.
