Skip to content

Glossaries

View .md

Each organization has one glossary; its terms are the editable resource. Project-scoped glossary routes under /v1/projects/{projectId}/glossary/... accept an API key and are covered in the platform glossary guide.

Every endpoint needs a signed-in session, and an API key is turned away in one of two places. The term list, the single-term read and the three exports accept either method, so a key authenticates and is then refused with 403 FORBIDDEN and the message API keys cannot access organization-scoped routes, before scopes are looked at. Every other endpoint is session-only and answers a key with 401 AUTHENTICATION_REQUIRED.

Permissions: glossary.view to read and export, glossary.create to create and import, glossary.edit to update, glossary.delete to delete. glossary.delete has no entry in the API-key scope map, so no scope grants it anywhere, including the project-scoped routes. The other three map to translations:read and translations:write.

Read the organization glossary, creating the default record when necessary. Session only, glossary.view.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
Terminal window
curl -b cookies.txt https://api.comvi.io/v1/organizations/1/glossary

GET /v1/organizations/{orgId}/glossary/terms

Section titled “GET /v1/organizations/{orgId}/glossary/terms”

List terms with cursor pagination. glossary.view.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
cursor query string No nextCursor from the previous page
limit query integer No 1 to 100
search query string No Up to 255 characters
termType query preferred | forbidden No Filter by term type
Terminal window
curl -b cookies.txt "https://api.comvi.io/v1/organizations/1/glossary/terms?search=dashboard&limit=10"
{ "terms": [], "nextCursor": null, "hasMore": false }

POST /v1/organizations/{orgId}/glossary/terms

Section titled “POST /v1/organizations/{orgId}/glossary/terms”

Create a term. Session only, glossary.create.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
term body string Yes The term
definition, termType, partOfSpeech, gender body string No Metadata
isCaseSensitive, isExactMatch, isTranslatable body boolean No Matching flags
Terminal window
curl -X POST -b cookies.txt -H "Content-Type: application/json" \
-d '{"term":"dashboard","definition":"Main analytics screen","termType":"preferred"}' \
https://api.comvi.io/v1/organizations/1/glossary/terms

Returns 201 Created with the complete term, including its translations.

GET /v1/organizations/{orgId}/glossary/terms/{termId}

Section titled “GET /v1/organizations/{orgId}/glossary/terms/{termId}”

Read one term. glossary.view.

PATCH /v1/organizations/{orgId}/glossary/terms/{termId}

Section titled “PATCH /v1/organizations/{orgId}/glossary/terms/{termId}”

Update any subset of the fields accepted on create. Session only, glossary.edit.

DELETE /v1/organizations/{orgId}/glossary/terms/{termId}

Section titled “DELETE /v1/organizations/{orgId}/glossary/terms/{termId}”

Delete a term. Session only, glossary.delete. Returns 204 No Content.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
termId path integer Yes Term ID
Terminal window
curl -X DELETE -b cookies.txt https://api.comvi.io/v1/organizations/1/glossary/terms/7

POST /v1/organizations/{orgId}/glossary/terms/{termId}/translations

Section titled “POST /v1/organizations/{orgId}/glossary/terms/{termId}/translations”

Add a translation to a term. Session only, glossary.edit.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
termId path integer Yes Term ID
localeId body integer Yes Target locale ID
text body string Yes Translated term
termType body string No preferred or forbidden
Terminal window
curl -X POST -b cookies.txt -H "Content-Type: application/json" \
-d '{"localeId": 2, "text": "панель керування", "termType": "preferred"}' \
https://api.comvi.io/v1/organizations/1/glossary/terms/7/translations

PATCH /v1/organizations/{orgId}/glossary/terms/{termId}/translations/{translationId}

Section titled “PATCH /v1/organizations/{orgId}/glossary/terms/{termId}/translations/{translationId}”

Update a translation by its ID. Session only, glossary.edit.

DELETE /v1/organizations/{orgId}/glossary/terms/{termId}/translations/{translationId}

Section titled “DELETE /v1/organizations/{orgId}/glossary/terms/{termId}/translations/{translationId}”

Remove a translation by its ID. Session only, glossary.delete.

POST /v1/organizations/{orgId}/glossary/import

Section titled “POST /v1/organizations/{orgId}/glossary/import”

Import terms from CSV. Session only, glossary.create. The body is JSON with the CSV Base64-encoded in content. The schema caps the encoded string at 10 MiB, but the route sets no body limit of its own, so Fastify’s default of 1 MiB caps the request, roughly 780 KB of decoded CSV. A larger body is refused with 413 and code: "UNKNOWN".

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
content body string Yes Base64-encoded CSV
conflictStrategy body skip | overwrite | merge Yes What to do with an existing term
columnMapping body object No Maps your headers to Comvi’s column names, such as {"language": "locale_code", "word": "term"}

CSV columns, as the export writes them so an exported file re-imports without a mapping: concept_id, definition, subject, locale_code, term, term_type, part_of_speech, is_case_sensitive, is_exact_match, is_translatable, is_forbidden, description, gender. locale_code and term are required. A header named locale instead of locale_code is not recognised: the import answers 200 with {"imported": 0, "skipped": 0, "updated": 0, "errors": [{"row": 0, "message": "Missing locale_code column"}]} and writes nothing, and a missing term column behaves the same way. Read errors, not the status. When a row omits concept_id, each translation row must follow the source-locale row it belongs to; rows are grouped by order.

Terminal window
curl -X POST -b cookies.txt -H "Content-Type: application/json" \
-d '{"content":"Y29uY2VwdF9pZCxsb2NhbGVfY29kZSx0ZXJtLGRlZmluaXRpb24KMSxlbixkYXNoYm9hcmQsTWFpbiBhbmFseXRpY3Mgc2NyZWVuCjEsdWss0L/QsNC90LXQu9GMINC60LXRgNGD0LLQsNC90L3RjywK","conflictStrategy":"merge"}' \
https://api.comvi.io/v1/organizations/1/glossary/import

That content decodes to:

concept_id,locale_code,term,definition
1,en,dashboard,Main analytics screen
1,uk,панель керування,

POST /v1/organizations/{orgId}/glossary/import/json

Section titled “POST /v1/organizations/{orgId}/glossary/import/json”

Import terms from JSON. Session only, glossary.create. The body mirrors the JSON export, so a glossary round-trips between organizations. Up to 100,000 concepts; the body is capped at 10 MB.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
version body string Yes "1.0"
concepts body object[] Yes Up to 100,000
concepts[].terms body object[] Yes Each with localeCode and text; optional termType, description, partOfSpeech, gender, isCaseSensitive, isExactMatch
concepts[].definition body string No Up to 2000 characters
concepts[].subject body string No Up to 255 characters
concepts[].isTranslatable body boolean No false for names never translated
conflictStrategy body skip | overwrite | merge Yes What to do with an existing term
sourceLocaleCode body string No Source locale of the concepts
Terminal window
curl -X POST -b cookies.txt -H "Content-Type: application/json" \
-d '{"version":"1.0","sourceLocaleCode":"en","conflictStrategy":"merge","concepts":[{"definition":"Main analytics screen","isTranslatable":true,"terms":[{"localeCode":"en","text":"dashboard","termType":"preferred"},{"localeCode":"uk","text":"панель керування"}]}]}' \
https://api.comvi.io/v1/organizations/1/glossary/import/json

Both imports answer with the same result. A row you cannot write because of a language restriction is reported in errors as Access denied to locale: <code> and is not counted in skipped. Unknown locale codes and rows missing locale_code or term land there too, with their row number.

{ "imported": 120, "skipped": 4, "updated": 11, "errors": [{ "row": 45, "message": "Unknown locale: xx" }] }

GET /v1/organizations/{orgId}/glossary/export/csv

Section titled “GET /v1/organizations/{orgId}/glossary/export/csv”

GET /v1/organizations/{orgId}/glossary/export/json

Section titled “GET /v1/organizations/{orgId}/glossary/export/json”

GET /v1/organizations/{orgId}/glossary/export/tbx

Section titled “GET /v1/organizations/{orgId}/glossary/export/tbx”

Export the glossary as a file with a Content-Disposition: attachment header. glossary.view. Use curl -o.

Parameter In Type Required Meaning
orgId path integer Yes Organization ID
localeIds query string No Comma-separated locale IDs
Format Content-Type Use it for
csv text/csv; charset=utf-8 Spreadsheets and quick edits
json application/json Round-tripping through the JSON import. Body: { "version": "1.0", "sourceLocaleCode": "...", "concepts": [...] }
tbx application/xml; charset=utf-8 TBX-speaking CAT tools
Terminal window
curl -b cookies.txt -o glossary.tbx "https://api.comvi.io/v1/organizations/1/glossary/export/tbx?localeIds=1,2"

Standard envelope, except 422 validation failures, which carry code and meta and no message.

Status When
400 Invalid cursor, body, locale, or term shape
401 AUTHENTICATION_REQUIRED No session cookie, the session is no longer valid, or an API key on a session-only endpoint
403 FORBIDDEN Missing glossary permission or locale access, or an API key on an endpoint that accepts either method
403 READ_ONLY_MODE The organization is over its plan limits and can only read
404 Organization, term, or translation not found
422 FIELD_REQUIRED, FIELD_TOO_LONG, FIELD_TOO_SHORT, VALIDATION_ERROR A field is missing, over its length, empty, or has the wrong type, format, pattern, range or enum. meta.field names it