Projects
A project belongs to an organization and holds translation keys, locales and namespaces. An API key is bound to one project, so it can read and update that project but cannot list or create projects.
Reading or writing mtSettings and cdnSettings needs the project.manage_settings permission. No scope grants it, so a key created from the scope list never sees those two objects and gets 403 FORBIDDEN when it sends them. To give a key the permission, name project.manage_settings in permissions when creating it through POST /v1/projects/{projectId}/api-keys; you can only grant a permission you hold. The key’s own project comes back from GET /v1/project.
Common errors on every endpoint: 401 AUTHENTICATION_REQUIRED (missing or invalid credentials, or a Bearer key on a session-only route), 403 FORBIDDEN, 403 READ_ONLY_MODE on writes, 409 TRANSACTION_CONFLICT on create, update and delete (retry the request). See Errors.
GET /v1/projects
Section titled “GET /v1/projects”List the projects of an organization, with integer cursor pagination.
Session cookie only.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
organizationId |
query | integer |
Yes | Organization to list |
cursor |
query | integer |
No | nextCursor from the previous response. An integer, unlike the string cursor of other lists |
limit |
query | integer |
No | 1 to 100, default 50 |
curl -b cookies.txt "https://api.comvi.io/v1/projects?organizationId=1&limit=10"{ "projects": [ { "id": 1, "organizationId": 1, "name": "my-web-app", "description": "Main web application translations", "sourceLocale": "en", "locales": [{ "id": 1, "code": "en", "name": "English", "nativeName": "English", "isCustom": false, "flagEmoji": "🇺🇸" }], "namespaces": [{ "id": 1, "projectId": 1, "namespace": "default", "description": null, "isDefault": true, "createdAt": "2025-01-15T10:30:00.000Z", "updatedAt": "2025-01-15T10:30:00.000Z" }] } ], "nextCursor": 2, "hasMore": true}hasMore is always present. nextCursor is null on the last page.
| Status and code | When |
|---|---|
403 ORGANIZATION_NOT_FOUND |
The caller is not a member of the organization |
422 FIELD_REQUIRED |
organizationId is missing |
GET /v1/projects/{id}
Section titled “GET /v1/projects/{id}”Read one project with its locales, namespaces and settings.
Session cookie or API key. A key reads its own project only.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
id |
path | integer |
Yes | Project ID |
curl -H "Authorization: Bearer $COMVI_API_KEY" https://api.comvi.io/v1/projects/1{ "id": 1, "organizationId": 1, "name": "my-web-app", "description": "Main web application translations", "aiContext": "A project management SaaS for small engineering teams.", "sourceLocale": "en", "locales": [{ "id": 1, "code": "en", "name": "English", "nativeName": "English", "isCustom": false, "flagEmoji": "🇺🇸" }], "namespaces": [{ "id": 1, "projectId": 1, "namespace": "default", "description": null, "isDefault": true, "createdAt": "…", "updatedAt": "…" }], "mtSettings": { "enabledProviders": ["google", "deepl"], "primaryProvider": "google", "autoApply": false, "aiTranslationInstructions": null, "aiModels": null }, "cdnSettings": { "enabled": true, "locales": ["en", "uk"], "namespaces": ["default"], "statuses": ["translated"], "format": "json", "baseUrl": null, "lastDeployedAt": null }}mtSettings and cdnSettings appear only when the caller holds project.manage_settings. Without it both keys are absent, not empty. locales[].aiContext holds the per-language context set through Languages.
| Status and code | When |
|---|---|
403 FORBIDDEN |
No permission to view the project, or a key used against another project |
404 PROJECT_NOT_FOUND |
Project does not exist |
POST /v1/projects
Section titled “POST /v1/projects”Create a project in an organization. A default namespace, a translation memory and a glossary are created with it.
Session cookie only, with project.create in the organization.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
organizationId |
body | integer |
Yes | Organization to create the project in |
name |
body | string |
Yes | 1 to 255 characters |
description |
body | string |
No | Up to 1000 characters |
sourceLocaleCode |
body | string |
Yes | Source language code, such as en |
curl -X POST -b cookies.txt -H "Content-Type: application/json" \ -d '{"organizationId": 1, "name": "my-web-app", "sourceLocaleCode": "en"}' \ https://api.comvi.io/v1/projectsReturns 201 Created with the project object, in the shape of GET /v1/projects/{id} without mtSettings and cdnSettings.
| Status and code | When |
|---|---|
400 LOCALE_NOT_FOUND |
sourceLocaleCode is not a valid locale |
403 FORBIDDEN |
No permission to create projects in the organization |
403 LIMIT_EXCEEDED |
Project limit reached for the plan |
PATCH /v1/projects/{id}
Section titled “PATCH /v1/projects/{id}”Update name, description, AI context, source locale, machine translation settings or CDN settings. Send only the fields to change.
Session cookie or API key with translations:write. Sending mtSettings or cdnSettings also needs project.manage_settings; without it the whole request fails with 403.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
id |
path | integer |
Yes | Project ID |
name |
body | string |
No | 1 to 255 characters |
description |
body | string |
No | Up to 1000 characters |
aiContext |
body | string | null |
No | Project-level context for AI translation, up to 8000 characters. null clears it |
sourceLocaleCode |
body | string |
No | New source language code |
mtSettings |
body | object |
No | Machine-translation settings; fields in the mtSettings table |
cdnSettings |
body | object |
No | Content Deploy settings; fields in the cdnSettings table |
mtSettings field |
Type | Meaning |
|---|---|---|
enabledProviders |
string[] |
Any of google, deepl, aws, azure, openai, anthropic |
primaryProvider |
string | null |
Default provider |
autoApply |
boolean |
Apply MT suggestions automatically |
aiTranslationInstructions |
string | null |
Custom instructions for AI providers |
aiModels |
object | null |
Model per provider, such as {"openai": "gpt-4o"} |
cdnSettings field |
Type | Meaning |
|---|---|---|
enabled |
boolean |
Enable CDN publishing |
locales |
string[] |
Locale codes to publish |
namespaces |
string[] |
Namespaces to publish |
statuses |
string[] |
Statuses to publish: translated, not_reviewed, not_translated |
format |
string |
json or i18next-v4 |
curl -X PATCH -H "Authorization: Bearer $COMVI_API_KEY" -H "Content-Type: application/json" \ -d '{"name": "my-web-app-v2", "aiContext": "A project management SaaS for small engineering teams."}' \ https://api.comvi.io/v1/projects/1Returns the full updated project, in the shape of GET /v1/projects/{id}.
| Status and code | When |
|---|---|
403 FORBIDDEN |
No permission to edit the project, or to manage its settings |
404 PROJECT_NOT_FOUND |
Project does not exist |
404 LOCALE_NOT_FOUND |
sourceLocaleCode is invalid |
DELETE /v1/projects/{id}
Section titled “DELETE /v1/projects/{id}”Soft-delete a project. Its data is retained but no longer accessible.
Session cookie only.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
id |
path | integer |
Yes | Project ID |
curl -X DELETE -b cookies.txt https://api.comvi.io/v1/projects/1Returns 204 No Content.
| Status and code | When |
|---|---|
403 FORBIDDEN |
No permission to delete the project |
404 PROJECT_NOT_FOUND |
Project does not exist |
GET /v1/projects/stats
Section titled “GET /v1/projects/stats”Translation statistics for the projects the caller can see in an organization.
Session cookie or API key with translations:read. A key gets its own project only.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
organizationId |
query | integer |
Yes | Organization ID |
curl -H "Authorization: Bearer $COMVI_API_KEY" "https://api.comvi.io/v1/projects/stats?organizationId=1"[{ "projectId": 1, "keyCount": 250, "translatedPct": 85.5, "notReviewedPct": 10.2, "notTranslatedPct": 4.3 }]| Status and code | When |
|---|---|
403 ORGANIZATION_NOT_FOUND |
The caller, or the key’s project, is not in the organization |
403 FORBIDDEN |
The key lacks translations:read, or its creator lost translation.view |
POST /v1/projects/{projectId}/ai-context/generate
Section titled “POST /v1/projects/{projectId}/ai-context/generate”Sample the project’s key names and source texts and ask an LLM for a draft project description covering domain, audience, tone and terminology. The draft is not saved; store it by sending it as aiContext to PATCH /v1/projects/{id}.
Session cookie only, with project.edit. Rate limit: 5 requests per hour per project. No request body.
| Parameter | In | Type | Required | Meaning |
|---|---|---|---|---|
projectId |
path | integer |
Yes | Project ID |
curl -X POST -b cookies.txt https://api.comvi.io/v1/projects/1/ai-context/generate{ "draft": "A project management SaaS for small engineering teams. The tone is direct and informal.", "keyCount": 250, "sampledCount": 120 }| Field | Type | Meaning |
|---|---|---|
draft |
string |
The generated description, not stored |
keyCount |
integer |
Translation keys in the project |
sampledCount |
integer |
Keys sampled and sent to the model |
| Status and code | When |
|---|---|
403 FORBIDDEN |
No permission to edit the project |
404 PROJECT_NOT_FOUND |
Project does not exist |
422 NOT_ENOUGH_KEYS |
Fewer than 30 keys. meta carries keyCount and required |
429 TOO_MANY_REQUESTS |
More than 5 requests in the last hour for the project |
502 INTERNAL_ERROR |
The model call failed |
504 INTERNAL_ERROR |
The model call timed out. meta.timeout is true |
Next steps
Section titled “Next steps”- Translations for keys and values in the project
- Languages to add and remove locales
- Namespaces to group keys