# Règles

> Le format des règles de l’organisation, des rôles, des groupes et des exceptions, la façon dont elles se combinent, et les routes qui les lisent et écrivent.

Les règles d’une [organisation gérée](https://realmoon.ai/documentation/organisations/organisations-gerees/) décident des modèles, des fonctions, des connecteurs, des fichiers et des limites d’utilisation de ses membres. Elles s’écrivent à quatre niveaux : l’organisation, les rôles, les groupes et l’exception d’un membre. Les règles enregistrées ne s’appliquent qu’une fois l’organisation gérée (`managed`, voir [Organisation et réglages](https://realmoon.ai/documentation/api-organisations/organisation/#general)).

Toutes les routes sont sous `https://chat.realmoon.ai/api/v1/orgs/{org_id}`. Portées : `rules:read` pour lire, `rules:write` pour écrire.

## Règles de l’organisation

Une clé absente prend la valeur de la plateforme : tout est permis, 100 % des limites, pas de taille de fichier imposée.

```json
{
  "models": { "mode": "allow", "ids": ["anthropic/claude-haiku-4.5", "mistralai/mistral-large-2512"], "eu_only": false },
  "modes": { "agent": false },
  "features": { "web_search": true, "image_generation": false, "public_share": false },
  "connectors": { "mode": "allow", "ids": ["gmail", "notion"], "personal_mcp": false },
  "files": { "max_mb": 50, "types": ["pdf", "docx", "xlsx"] },
  "usage": { "session_pct": 50, "week_pct": 80 },
  "learn_mode_default": false,
  "outside_access": true,
  "retention_days": 365
}
```

| Clé | Valeurs |
| --- | --- |
| `models.mode` | `all` (tous les modèles proposés) ou `allow` (seulement `ids`, 1 000 au plus). |
| `models.eu_only` | `true` : seulement les modèles hébergés dans l’Union européenne ; coupe aussi `image_generation`, `video_generation`, `music_generation`, `web_search`, `deep_research` et `voice`. |
| `modes` | `auto`, `agent`, `compare` : `true` ou `false`. |
| `features` | `true` ou `false` pour chaque fonction (liste ci-dessous). |
| `connectors.mode` | `all`, `none` ou `allow` (seulement `ids`, 1 000 au plus). |
| `connectors.personal_mcp` | Les membres peuvent ajouter leurs propres serveurs MCP. |
| `files.max_mb` | Taille maximale d’un fichier, de 1 à 500 Mo. |
| `files.types` | Extensions permises, sans le point (200 au plus). |
| `usage.session_pct`, `usage.week_pct`, `usage.month_pct` | Part de la limite d’utilisation de 5 heures, de la semaine et du mois que chaque membre peut utiliser, de 1 à 100. |
| `learn_mode_default` | Le mode apprentissage est activé par défaut. |
| `outside_access` | `false` : les membres ne peuvent plus utiliser Moon AI hors de l’organisation (contrat actif exigé). |
| `retention_days` | Durée de conservation des conversations, de 30 à 3 650 jours ; `null` : rien n’est supprimé. |

Fonctions de `features` : `web_search`, `url_fetch`, `deep_research`, `image_generation`, `video_generation`, `music_generation`, `voice`, `sandbox`, `code_interpreter`, `memory`, `projects`, `routines`, `agents`, `skills`, `artifacts`, `import`, `public_share`, `temporary_chats`, `file_upload`, `personal_instructions`, `cli`, `api_keys`, `economy_fallback`, `messaging`.

Quand `music_generation` n’est réglée nulle part, la musique suit `video_generation` si celle-ci est coupée.

## Règles d’un rôle, d’un groupe ou d’un membre

À ces niveaux, une clé absente est héritée. `outside_access` et `retention_days` n’existent qu’au niveau de l’organisation.

```json
{
  "features": { "web_search": "deny", "image_generation": "allow" },
  "modes": { "agent": "deny" },
  "models": { "mode": "only", "ids": ["mistralai/mistral-large-2512"], "eu_only": "deny" },
  "connectors": { "remove": ["slack"], "personal_mcp": "allow" },
  "files": { "max_mb": 20, "types": { "mode": "only", "ids": ["pdf"] } },
  "usage": { "month_pct": 40 },
  "learn_mode_default": "on"
}
```

| Forme | Valeurs |
| --- | --- |
| Fonctions, modes, `models.eu_only`, `connectors.personal_mcp` | `allow`, `deny`, ou `inherit` / `null` (hérité) ; `true` et `false` valent `allow` et `deny`. Pour `models.eu_only`, `deny` exige les modèles hébergés dans l’Union européenne. |
| `learn_mode_default` | `on`, `off`, ou `inherit`. |
| `models`, `connectors`, `files.types` | `{"mode": "only", "ids": [...]}`, `{"mode": "all"}`, `{"mode": "none"}` (connecteurs seulement), et `add` / `remove` pour ajouter ou retirer des éléments. Une liste seule vaut `only`. |
| `files.max_mb`, `usage.*` | Un nombre ; `null` est hérité. |

## Consignes

Chaque niveau peut porter des consignes : un texte de 4 000 caractères au plus, ajouté aux conversations des membres concernés. Une chaîne vide ou `null` les efface. Elles s’ajoutent dans cet ordre : organisation, rôles, groupes, exception du membre.

## Comment les règles se combinent

Pour chaque membre comptent : son rôle de base, ses autres rôles (donnés à lui, à un de ses groupes ou à une de ses étiquettes), les groupes dont il est membre (pas ceux qu’il gère seulement) et son exception.

- **Fonctions et modes** : l’exception décide si elle est posée ; sinon un `deny` d’un rôle ou d’un groupe l’emporte, puis un `allow`, puis la règle de l’organisation.
- **Nombres** (`files.max_mb`, `usage.*`) : l’exception décide ; sinon la plus petite des restrictions, sinon le plus grand des assouplissements, sinon la valeur de l’organisation.
- **Listes** (`models`, `connectors`, `files.types`) : la liste de l’organisation, à laquelle les niveaux ajoutent puis retirent ; un retrait l’emporte toujours. L’exception passe en dernier.

`GET /policies/effective/{user_id}` donne le résultat pour un membre et la source de chaque valeur.

## Lire et écrire les règles de l’organisation

`GET /policies/org` · `rules:read`

```json
{
  "id": "5b1e0c3a-7d2f-4a8e-9c11-2f6d8e4b7a90",
  "org_id": "8c1f2a4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
  "scope_type": "org",
  "scope_id": null,
  "rules": { "features": { "image_generation": false }, "retention_days": 365 },
  "instructions": "Répondez en français et citez vos sources.",
  "rules_format": null,
  "updated_by": "0d9a2f44-1c3b-4e7a-8b6f-55e2c1d0a9b8",
  "updated_at": 1762339200,
  "policy_version": 42,
  "limits": { "files_max_mb": { "min": 1, "max": 500 }, "retention_days": { "min": 30, "max": 3650 }, "usage_pct": { "min": 1, "max": 100 }, "instructions_max": 4000, "model_ids_max": 1000, "connector_ids_max": 1000, "file_types_max": 200 },
  "counts": { "active_members": 380, "outside_access_retained": 379, "without_group": 4 }
}
```

`policy_version` augmente à chaque écriture de règles, de rôles, de groupes, d’étiquettes ou de réglages. `limits` donne aussi les longueurs des noms de groupes, de rôles et d’étiquettes.

`PUT /policies/org` · `rules:write`

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `rules` | objet | non | Remplace toutes les règles. Si `outside_access` ou `retention_days` sont absents, leurs valeurs enregistrées sont gardées. |
| `instructions` | chaîne | non | Les consignes de l’organisation. |

Un champ absent n’est pas touché ; envoyez au moins l’un des deux.

```bash title="cURL"
curl -X PUT https://chat.realmoon.ai/api/v1/orgs/$ORG_ID/policies/org \
  -H "Authorization: Bearer $MOONAI_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"rules": {"features": {"image_generation": false}, "usage": {"session_pct": 50}}}'
```

```python title="Python"
import os
import requests

r = requests.put(
    f"https://chat.realmoon.ai/api/v1/orgs/{os.environ['ORG_ID']}/policies/org",
    headers={"Authorization": f"Bearer {os.environ['MOONAI_ADMIN_KEY']}"},
    json={"rules": {"features": {"image_generation": False}, "usage": {"session_pct": 50}}},
    timeout=30,
)
if r.status_code == 400:
    print(r.json()["detail"].get("errors"))
r.raise_for_status()
print(r.json()["policy_version"])
```

```javascript title="JavaScript"
const r = await fetch(`https://chat.realmoon.ai/api/v1/orgs/${process.env.ORG_ID}/policies/org`, {
  method: 'PUT',
  headers: { Authorization: `Bearer ${process.env.MOONAI_ADMIN_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ rules: { features: { image_generation: false }, usage: { session_pct: 50 } } }),
});
const body = await r.json();
if (!r.ok) throw new Error(JSON.stringify(body.detail));
console.log(body.policy_version);
```

Des règles invalides répondent `400 invalid_request` (« Règles invalides. ») avec `errors` : au plus 20 objets `{"path": "models.ids", "message": "Indiquez au moins un modèle."}`. Fermer `outside_access` sans contrat actif répond `403 managed_needs_contract`.

`PUT /policies/org/models` · `rules:write`

Modifie seulement la règle des modèles : `{"models": {"mode": "allow", "ids": ["mistralai/mistral-large-2512"]}}`. `{"models": {}}` revient à tous les modèles. La liste des modèles qu’une règle peut autoriser se lit avec [`GET /models/catalog`](https://realmoon.ai/documentation/api-organisations/modeles/#catalogue).

Chaque écriture de règles envoie l’événement [webhook](https://realmoon.ai/documentation/api-organisations/webhooks/) `policy.updated` avec `scope_type` et `scope_id`.

## Règles d’un groupe

`GET /policies/groups/{group_id}` · `rules:read`

`PUT /policies/groups/{group_id}` · `rules:write`

Même corps que pour l’organisation, au [format des niveaux](https://realmoon.ai/documentation/api-organisations/regles/#format-couche). La réponse ajoute `group_name` et `rules_format: 2`. Les consignes d’un groupe demandent aussi `groups:write`. Une clé qui ne peut pas agir sur ce groupe reçoit `404`.

## Règles d’un rôle

`GET /policies/roles` · `rules:read`

```json
{
  "items": [
    { "role_key": "owner", "name": "Propriétaire", "kind": "provided", "has_rules": false, "has_instructions": false },
    { "role_key": "member", "name": "Élève", "kind": "provided", "has_rules": true, "has_instructions": false },
    { "role_key": "custom:9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d", "name": "Surveillant", "kind": "created", "has_rules": true, "has_instructions": true }
  ],
  "total": 6,
  "policy_version": 42
}
```

Les rôles fournis viennent d’abord (`owner`, `admin`, `manager`, `member`, `billing`), puis les [rôles créés](https://realmoon.ai/documentation/api-organisations/roles/). Le nom des rôles `manager` et `member` dépend du type d’organisation.

`GET /policies/roles/{role_key}` · `rules:read`

`PUT /policies/roles/{role_key}` · `rules:write`

Même corps qu’un groupe ; la réponse ajoute `role`. Un rôle inconnu répond `404`.

## Exceptions d’un membre

Une exception passe avant toutes les autres règles du membre.

| Méthode et chemin | Portée | Rôle |
| --- | --- | --- |
| `GET /policies/members` | `rules:read` | Les membres qui ont une exception, les plus récentes d’abord. |
| `GET /policies/members/{user_id}` | `rules:read` | L’exception d’un membre (`rules: {}` s’il n’en a pas). |
| `PUT /policies/members/{user_id}` | `rules:write` | Poser ou modifier l’exception ; si rien ne reste, elle est supprimée. |
| `DELETE /policies/members/{user_id}` | `rules:write` | Supprimer l’exception ; répond `{"removed": true, "policy_version": 43}`. |

Une clé ne pose pas d’exception sur le créateur de la clé, le propriétaire, un administrateur, ni sur un membre qui a plus de droits qu’elle (`403 forbidden`).

## Règles effectives d’un membre

`GET /policies/effective/{user_id}` · `members:read`

```json
{
  "managed": true,
  "user_id": "41ab2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "policy_version": 42,
  "rules": { "features": { "web_search": false, "image_generation": false }, "models": { "eu_only": true, "mode": "all" }, "retention_days": 365 },
  "sources": {
    "features.web_search": [{ "scope_type": "group", "scope_id": "<id de groupe>", "name": "Classe 3e B" }],
    "models.eu_only": [{ "scope_type": "org", "scope_id": null, "name": null }]
  },
  "derived": { "features.image_generation": "models.eu_only" },
  "instructions": "<organization_instructions source=\"organization\">\nRépondez en français.\n</organization_instructions>",
  "instruction_blocks": [{ "scope_type": "org", "scope_id": null, "name": null, "text": "Répondez en français." }],
  "group_ids": ["<id de groupe>"],
  "base_role": "member",
  "role_keys": ["member"],
  "managed_group_ids": [],
  "member_exception": false,
  "layers": [{ "scope_type": "group", "scope_id": "<id de groupe>", "name": "Classe 3e B", "has_rules": true }],
  "settings": {
    "features.web_search": { "value": false, "source": "group:<id de groupe>", "sources": [], "derived": null },
    "usage.session_pct": { "value": 100, "source": "default", "sources": [], "derived": null }
  },
  "can_edit_exception": true
}
```

| Champ | Description |
| --- | --- |
| `rules` | Les règles qui s’appliquent au membre. |
| `sources` | Pour chaque réglage, le niveau qui l’a décidé. |
| `derived` | Réglages forcés par une autre règle, par exemple une fonction coupée par `models.eu_only`. |
| `settings` | Chaque réglage avec sa valeur et sa source : `member`, `group:<id>`, `role:<clé>`, `org` ou `default`. |
| `instruction_blocks` | Consignes par niveau. Sans le droit de lire les règles, les consignes des rôles, de l’exception et des groupes que la clé ne gère pas sont masquées (`hidden: true`). |

Le calcul se fait même quand l’organisation n’est pas encore gérée.

## Aperçu de la conservation

`GET /policies/retention/preview?days=365` · `rules:read`

Rend `{"days": 365, "count": 1284, "cutoff": 1730803200, "managed": true}` : les conversations du workspace non modifiées depuis `cutoff` qu’une conservation de `days` jours supprimerait à la prochaine suppression de nuit. `days` va de 30 à 3 650.

## Voir aussi

- [Règles](https://realmoon.ai/documentation/organisations/regles/), dans l’administration
- [Modèles de l’organisation](https://realmoon.ai/documentation/api-organisations/modeles/)
- [Groupes](https://realmoon.ai/documentation/api-organisations/groupes/)

---

Documentation Moon AI › API des organisations › Règles. Page : https://realmoon.ai/documentation/api-organisations/regles/. Modifiée le 5 novembre 2026.

© 2026 Stellarr Studio SAS. Tous droits réservés. Moon AI, Moon Blur et Stellarr Studio sont des marques déposées à l’INPI.
