# Domaines

> Ajouter et vérifier les domaines de l’organisation par un enregistrement DNS TXT, régler le rattachement automatique et inviter les comptes existants par l’API.

Un domaine vérifié (par exemple `ecole.fr`) prouve que l’organisation possède les adresses de ce domaine. Il rend « gérés » les comptes de ces adresses, permet le rattachement automatique, la [connexion unique](https://realmoon.ai/documentation/api-organisations/sso/) obligatoire et la création de comptes par l’[annuaire SCIM](https://realmoon.ai/documentation/api-organisations/scim/). Une organisation a 50 domaines au plus.

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

## L’objet domaine

```json
{
  "id": "3c1f6a2e-5b8d-4e7a-9f10-2b6c8d4e0a11",
  "domain": "ecole.fr",
  "status": "pending",
  "verified_at": null,
  "last_checked_at": null,
  "last_error": null,
  "auto_join": false,
  "default_role_key": null,
  "default_group_ids": [],
  "created_at": 1762339200,
  "updated_at": 1762339200,
  "txt": { "type": "TXT", "name": "_moonai.ecole.fr", "value": "moonai-verification=4f9c2a7b1e6d3c8a0b5f2e9d7c1a4b6e" }
}
```

| Champ | Description |
| --- | --- |
| `status` | `pending`, `verified` ou `failed`. |
| `last_error` | `record_not_found`, `dns_unavailable`, `domain_taken`, ou `lost:<n>` après des échecs de la vérification hebdomadaire. |
| `txt` | L’enregistrement à publier : son nom et sa valeur ne changent pas. |
| `auto_join` | Rattachement automatique des comptes de ce domaine. |
| `default_role_key`, `default_group_ids` | Rôle et groupes donnés aux comptes rattachés par ce domaine. |

## Lister les domaines

`GET /domains` · `security:read`

Rend `items`, `total`, `verified_count` et `paid_subscription` (le workspace est payé par carte : le rattachement automatique n’est alors pas proposé).

## Ajouter un domaine

`POST /domains` · `security:write`

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `domain` | chaîne | oui | Le nom de domaine, sans `@` ni `https://`. Un nom international est accepté. |

Rend le domaine, en attente de vérification.

| Statut | `code` | Cause |
| --- | --- | --- |
| 400 | `domain_invalid` | Nom de domaine invalide. |
| 400 | `domain_public` | Domaine d’une messagerie publique ou jetable. |
| 400 | `invalid_request` | Plus de 50 domaines. |
| 409 | `domain_exists` | Le domaine est déjà dans la liste. |

## Vérifier un domaine

1. Publiez dans la zone DNS du domaine l’enregistrement `TXT` donné par `txt` : nom `_moonai.<domaine>`, valeur `moonai-verification=<jeton>`.
2. Appelez `POST /domains/{domain_id}/verify` (`security:write`).

La réponse est le domaine avec `check` : `{"found": true, "error": null}`, ou `found: false` avec `error` (`record_not_found` ou `dns_unavailable`). Elle répond `200` même quand l’enregistrement n’est pas encore visible : relancez quand il est publié.

```bash title="cURL"
curl -X POST https://chat.realmoon.ai/api/v1/orgs/$ORG_ID/domains/$DOMAIN_ID/verify \
  -H "Authorization: Bearer $MOONAI_ADMIN_KEY"
```

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

BASE = f"https://chat.realmoon.ai/api/v1/orgs/{os.environ['ORG_ID']}"
HEADERS = {"Authorization": f"Bearer {os.environ['MOONAI_ADMIN_KEY']}"}

r = requests.post(f"{BASE}/domains/{os.environ['DOMAIN_ID']}/verify", headers=HEADERS, timeout=30)
r.raise_for_status()
domain = r.json()
print(domain["status"], domain["check"])
```

```javascript title="JavaScript"
const BASE = `https://chat.realmoon.ai/api/v1/orgs/${process.env.ORG_ID}`;
const r = await fetch(`${BASE}/domains/${process.env.DOMAIN_ID}/verify`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.MOONAI_ADMIN_KEY}` },
});
if (!r.ok) throw new Error(await r.text());
const domain = await r.json();
console.log(domain.status, domain.check);
```

| Statut | `code` | Cause |
| --- | --- | --- |
| 409 | `domain_taken` | Le domaine est déjà vérifié par une autre organisation. |
| 429 | `rate_limited` | Plus de 20 vérifications par organisation en 10 minutes. |

Un domaine vérifié est revérifié tous les 7 jours. Après trois échecs de suite, il repasse en attente et le rattachement automatique est coupé ; le propriétaire en est prévenu. Un serveur DNS qui ne répond pas ne compte pas comme un échec.

## Régler un domaine

`PATCH /domains/{domain_id}` · `security:write`

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `auto_join` | booléen | non | Une personne dont l’adresse vérifiée est de ce domaine rejoint l’organisation à sa connexion, tant qu’il reste des sièges. |
| `default_role_key` | chaîne | non | `manager`, `billing` ou `custom:<id>` ; jamais `admin`. `null` l’efface. |
| `default_group_ids` | liste | non | 50 groupes statiques au plus ; ni dynamiques, ni venus de l’annuaire, ni donnant le rôle d’administrateur. |

| Statut | `code` | Cause |
| --- | --- | --- |
| 403 | `role_escalation` | Le rôle ou les groupes donnent plus que les permissions de la clé. |
| 404 | `not_found` | Groupe introuvable. |
| 409 | `domain_not_verified` | `auto_join` sur un domaine non vérifié. |
| 409 | `auto_join_paid_subscription` | `auto_join` sur un workspace payé par carte : chaque compte rattaché ajouterait un siège facturé. Invitez plutôt les comptes. |
| 409 | `directory_group_admin` | Un groupe qui donne le rôle d’administrateur. |

## Retirer un domaine

`DELETE /domains/{domain_id}` · `security:write`

Réponse : `{"success": true}`. Les comptes de ce domaine cessent d’être gérés par l’organisation à ce titre.

## Inviter les comptes existants du domaine

`GET /domains/{domain_id}/accounts` · `security:read`

Liste les comptes Moon AI existants dont l’adresse est de ce domaine vérifié, avec `status` : `active` ou `suspended` (déjà membres), `invited` (invitation en cours) ou `none`. Paramètres : `page`, `limit`.

`POST /domains/{domain_id}/claim` · `security:write`

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `user_ids` | liste | oui | 1 à 500 comptes du domaine. |

Envoie une invitation de membre à chacun. Réponse :

```json
{
  "invited": ["41ab2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"],
  "skipped": [{ "user_id": "77cd8e9f-0a1b-4c2d-9e3f-4a5b6c7d8e9f", "reason": "already_member" }],
  "domain": "ecole.fr"
}
```

Raisons de `skipped` : `not_in_domain`, `already_member`, `seats_full`, `invite_limit` (limite d’invitations du jour), `error`. Les deux routes répondent `409 domain_not_verified` sur un domaine non vérifié.

## Voir aussi

- [Connexion unique](https://realmoon.ai/documentation/api-organisations/sso/)
- [SCIM 2.0](https://realmoon.ai/documentation/api-organisations/scim/)
- [Comptes des membres](https://realmoon.ai/documentation/api-organisations/comptes/)

---

Documentation Moon AI › API des organisations › Domaines. Page : https://realmoon.ai/documentation/api-organisations/domaines/. 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.
