DocsOpen Moon AI
Browse the docs

Domains

Add and verify your organization’s domains with a DNS TXT record, set up automatic joining, and invite existing accounts through the admin API.

On this page

A verified domain (for example ecole.fr) proves that the organization owns the addresses on that domain. It makes the accounts with those addresses “managed”, and enables automatic joining, required single sign-on and account creation by the SCIM directory. An organization can have up to 50 domains.

All routes are under https://chat.realmoon.ai/api/v1/orgs/{org_id}. Scopes: security:read to read, security:write to write.

The domain objectLink to the The domain object section

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" }
}
FieldDescription
statuspending, verified or failed.
last_errorrecord_not_found, dns_unavailable, domain_taken, or lost:<n> after failures of the weekly check.
txtThe record to publish: its name and value never change.
auto_joinAuto-join for accounts on this domain.
default_role_key, default_group_idsRole and groups given to accounts that join through this domain.

List domainsLink to the List domains section

GET /domains · security:read

Returns items, total, verified_count and paid_subscription (the workspace is paid by card, so automatic joining is not available).

Add a domainLink to the Add a domain section

POST /domains · security:write

FieldTypeRequiredDescription
domainstringyesThe domain name, without @ or https://. Internationalized names are accepted.

Returns the domain, pending verification.

StatuscodeCause
400domain_invalidInvalid domain name.
400domain_publicDomain of a public or disposable email service.
400invalid_requestMore than 50 domains.
409domain_existsThe domain is already in the list.

Verify a domainLink to the Verify a domain section

  1. Publish the TXT record given by txt in the domain’s DNS zone: name _moonai.<domain>, value moonai-verification=<token>.
  2. Call POST /domains/{domain_id}/verify (security:write).

The response is the domain with check: {"found": true, "error": null}, or found: false with error (record_not_found or dns_unavailable). It returns 200 even when the record is not visible yet: call it again once the record is published.

cURL
curl -X POST https://chat.realmoon.ai/api/v1/orgs/$ORG_ID/domains/$DOMAIN_ID/verify \
  -H "Authorization: Bearer $MOONAI_ADMIN_KEY"
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
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);
StatuscodeCause
409domain_takenThe domain is already verified by another organization.
429rate_limitedMore than 20 checks per organization within 10 minutes.

A verified domain is checked again every 7 days. After three failures in a row, it goes back to pending and automatic joining is turned off; the owner is notified. A DNS server that does not respond does not count as a failure.

Configure a domainLink to the Configure a domain section

PATCH /domains/{domain_id} · security:write

FieldTypeRequiredDescription
auto_joinbooleannoA person whose verified address is on this domain joins the organization when they sign in, as long as seats are left.
default_role_keystringnomanager, billing or custom:<id>; never admin. null clears it.
default_group_idslistnoUp to 50 static groups; not dynamic, not from the directory, and not granting the admin role.
StatuscodeCause
403role_escalationThe role or groups grant more than the key’s permissions.
404not_foundA group was not found (message Groupe introuvable.).
409domain_not_verifiedauto_join on a domain that is not verified.
409auto_join_paid_subscriptionauto_join on a workspace paid by card: each account that joins would add a billed seat. Invite the accounts instead.
409directory_group_adminA group that grants the admin role.

Remove a domainLink to the Remove a domain section

DELETE /domains/{domain_id} · security:write

Response: {"success": true}. Accounts on this domain are no longer managed by the organization on that basis.

Invite the domain’s existing accountsLink to the Invite the domain’s existing accounts section

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

Lists the existing Moon AI accounts whose address is on this verified domain, with status: active or suspended (already members), invited (invitation pending) or none. Parameters: page, limit.

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

FieldTypeRequiredDescription
user_idslistyes1 to 500 accounts on the domain.

Sends a member invitation to each one. Response:

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

Reasons in skipped: not_in_domain, already_member, seats_full, invite_limit (daily invitation limit), error. Both routes return 409 domain_not_verified on a domain that is not verified.

See alsoLink to the See also section

Moon AI

Moon AI in action

0:00

Explore

Screenshots of chat.realmoon.ai taken on October 29, 2026, with fictional data.

Moon AI

Your preferences

Visits counted without cookies.

Our server counts visits without cookies or trackers. Your theme and your answer about ad measurement are remembered on this device.

Ad measurement

With your consent, our ad networks’ trackers (Google) measure our ads, from the visit to the sign-up and then to the first subscription and its amount, and may show you our ads. Your answer is valid for 13 months; you can change it here at any time.

No answer saved on this device.

After you decline, no tag is loaded anymore and the site deletes the cookies they had set on realmoon.ai. Those on the ad networks’ own domains are managed with them or in your browser.

The Moon AI app has its own privacy settings.