API Keys
API keys authenticate automation — the CLI, CI/CD pipelines, webhook receivers calling back into Comvi, custom scripts. Every key is scoped to a single project and carries its own set of API scopes. At runtime, access is also bounded by the creator’s current project access.
Humans authenticate with sessions instead. For the full picture of the two paths, see the auth diagram in Roles & Permissions.
When to create one
Section titled “When to create one”- Running
comvi push/comvi pullfrom a developer machine or CI - Triggering exports or imports from a build system
- Admin scripts that manage projects, keys, namespaces programmatically
- Any server-to-server integration calling the REST API
If your use case is “load published translations into an app”, you do not need an API key — the production CDN is unauthenticated. Keys are for authoring and tooling.
How they work
Section titled “How they work”An API key is a string that looks like comvi_<random>. On every request you pass it in the X-API-Key header. Comvi checks:
- The key exists and is active
- The key is not expired (if
expiresAtwas set) - The key has the specific permission the endpoint requires
Only then is the request authorized. API keys use project-scoped scopes that map to the API operations they can perform. The supported scopes are project:read, translations:read, translations:write, and schema:read.
Picking permissions
Section titled “Picking permissions”Follow the principle of least privilege — grant only what the integration genuinely needs. Common bundles:
| Integration | Scopes |
|---|---|
comvi pull (read only) | project:read, translations:read, schema:read |
comvi push (write) | above + translations:write |
| Import/export automation | project:read, translations:read, translations:write |
| Schema/type generation | schema:read |
| Read-only reporting scripts | project:read, translations:read |
The REST API docs under Authentication show which scope each API-key endpoint requires. In the dashboard, the create-key UI groups scopes into categories so you tick the rows you need instead of typing strings.
Creating a key
Section titled “Creating a key”-
Open API Keys
Project Settings → API Keys.
-
Create
Click Create API Key. Give it a descriptive name — the name shows up in logs and “last used” tracking, so pick something like
github-actions-releaseorsupport-agent-admin-scriptrather thankey1. -
Pick permissions
Tick only the rows you need. You can refine later.
-
(Optional) Set an expiration
Keys can auto-expire on a date you pick. Strongly recommended for CI keys and any non-permanent integration.
-
Copy the key
Comvi shows the full key once. Copy it now into your secrets manager or environment variable store. You cannot view it again after closing the dialog.
Keys start with the comvi_ prefix so they are easy to spot in logs, config files, and leaked secrets scanners.
Using a key
Section titled “Using a key”With the CLI
Section titled “With the CLI”export COMVI_API_KEY=comvi_…comvi pullOr via a config file that you keep out of git (or use environment substitution):
{ "apiKey": "comvi_…", "apiBaseUrl": "https://api.comvi.io", "translationsPath": "./src/locales"}With the REST API
Section titled “With the REST API”curl -H "X-API-Key: comvi_…" \ https://api.comvi.io/api/v1/projects/<id>/translationsAPI-key requests do not need CSRF tokens (sessions do). This makes server-to-server integration cleaner.
In CI/CD
Section titled “In CI/CD”Store the key as a CI secret and inject it as an env var.
- run: npx @comvi/cli pull env: COMVI_API_KEY: ${{ secrets.COMVI_API_KEY }}sync-translations: script: - npx @comvi/cli pull variables: COMVI_API_KEY: $COMVI_API_KEYSee CI/CD Integration for complete pipeline examples.
Rotating
Section titled “Rotating”Rotate on a schedule, after a team member departure, or if you suspect leakage.
-
Create a new key with the same permissions and an expiration that gives you a rollover window.
-
Update every consumer — CI secrets, deployed services, local
.envfiles. -
Verify the new key works — trigger one job or request.
-
Revoke the old key
Delete it in the dashboard. It becomes invalid immediately.
Key vs user identity
Section titled “Key vs user identity”An API key is a project credential created by a user, not a browser session. Implications:
- Keys are still bounded by the creator’s active account and current project permissions. If the creator is deleted, blocked, removed from the project, or loses required permissions, the key may stop working.
- A Manager can create a key with only
translations:readif that’s what the integration needs. If that Manager later loses translation read access, the key’s effective access is reduced too. - History entries and webhook deliveries attribute actions to the key, not to a user, so audit logs show “by API key
github-actions-release” rather than a human name.
Security best practices
Section titled “Security best practices”- Environment variables or secret managers. Never hardcode or commit keys.
- Least privilege. Resist the urge to grant
translations:writewhentranslations:readsuffices. - One key per integration. Rotate and revoke independently; identify usage in “last used”.
- Set expirations. Anything not explicitly permanent should auto-expire.
- Watch for leakage. Public git mirrors, error logs, screen shares — all common leak surfaces. The
comvi_prefix makes keys easy for scanners to spot. - Rotate on departure. When someone who created or had access to a key leaves, rotate affected keys.
Limits
Section titled “Limits”- Scope: project-scoped only; there are no organization-level API keys today.
- Header:
X-API-Keyonly. NoAuthorization: Bearerform. - Display: the key value is shown once, on creation.
Troubleshooting
Section titled “Troubleshooting”401 Unauthorized
Section titled “401 Unauthorized”Verify the X-API-Key header is present and contains the full token. Check the key is active in the dashboard and has not expired.
403 Forbidden
Section titled “403 Forbidden”The key is valid but lacks the specific permission for this endpoint. Compare the endpoint’s documented required permission to the key’s permissions and add what’s missing (edit the key — you don’t need to rotate for this).
The key disappeared from the dashboard
Section titled “The key disappeared from the dashboard”You are probably looking at the wrong project. Keys are project-scoped.
A key was accidentally leaked
Section titled “A key was accidentally leaked”Revoke it immediately. Create a replacement. Audit “last used” and webhook/delivery logs for unexpected activity. Rotate any downstream credentials the leak may have exposed.