# Core concepts

The Comvi data model: organizations, projects, languages, namespaces, keys, statuses and API keys, and where Comvi differs from other TMS.

Canonical: https://comvi.io/docs/platform/concepts

An **organization** owns **projects**. Each project has its own languages, namespaces, keys,
translations, API keys and CDN endpoint. Translation memories and glossaries belong to the
organization and are assigned to projects.

## Projects

A project is one translatable surface, typically one application or website. Languages,
namespaces, keys, API keys and the CDN endpoint are all project-scoped. Two surfaces that
share almost all copy fit one project with several namespaces. Separate release cycles or
owners call for separate projects. See [Projects](/docs/platform/projects).

## Languages

```text
en   de   pt-BR   zh-Hant   zh-Hant-TW
```

Locale codes are canonical BCP-47: subtags separated by a hyphen, the language lowercase,
a script subtag Titlecase, a region subtag UPPERCASE. Underscore input such as `pt_BR` is
accepted everywhere and canonicalized on entry, so the dashboard, API, CLI, import/export
and CDN all return and display `pt-BR`. A project's codes are valid BCP-47 by construction
and go straight into app config, URLs and `Intl`. See
[Locale codes](/docs/platform/languages#which-spelling-your-app-needs).

You pick the source language when you create the project. It cannot be changed afterwards,
and machine translation quality and translation memory matches both depend on it, so choose
the language your team writes in.

## Namespaces

```text
https://cdn.comvi.io/<project-token>/<language>.json                # default namespace
https://cdn.comvi.io/<project-token>/<namespace>/<language>.json    # any other namespace
```

A namespace is a group of keys that ships together. Every `(language, namespace)` pair
becomes one JSON file on the CDN, so namespaces are the unit you code-split translations by.
Every project starts with a `default` namespace; add more to load only what a screen needs,
to keep a large project navigable, or to give teams their own area. See
[Namespaces](/docs/platform/namespaces).

## Keys and values

```text
greeting
nav.home
errors.not_found
```

Keys are opaque strings. Dot notation is a readability convention, not nesting. A key belongs
to exactly one namespace and carries a value per language, plus an optional description that
gives translators context. Values are [ICU MessageFormat](https://unicode-org.github.io/icu/userguide/format_parse/messages/):

```text
You have {count, plural, one {# message} other {# messages}}.
```

## Statuses and deploys

Every value has a status: `not_translated`, `not_reviewed` or `translated`. Status tracks
review, not delivery. Saving a value from the editor sets it to `not_reviewed`, whoever saved
it. Moving a value to `translated` is a separate click on the status badge and needs review
permission. Imported values land as `translated`.

Deploying is a separate action. Once Content Deploy is on, every write schedules a deploy
about 5 seconds later, and the bundle holds whatever matches the **Filter by Status**
setting. An empty filter ships drafts too. See
[Translation lifecycle](/docs/platform/translation-lifecycle).

## API keys and webhooks

An API key authenticates the CLI, CI and any automation against the [REST API](/docs/api).
A key is scoped to one project and carries its own scopes, but on every request Comvi
intersects those scopes with the permissions its creator holds right now. Demote the creator
and the key loses the same access. Human users authenticate with sessions; see
[Roles & permissions](/docs/platform/roles-permissions).

Webhooks go the other direction, Comvi calling your server, and are verified with an HMAC
signature rather than an API key. See [Webhooks](/docs/platform/integrations/webhooks).

## Next steps

- [Your first project](/docs/platform/your-first-project): Create a project end to end.
- [Consume translations](/docs/platform/consume-translations): Load deployed bundles into any app or runtime.
