These routes act on a member’s Moon AI account, beyond their membership. The strongest ones (email address, two-factor authentication, password, disabling) only apply to a managed account: an account whose email address belongs to a domain verified by the organization, or that was created through its single sign-on or its directory. On an account that belongs to the person, they return 409 .
All routes live under https://. Actions on an account follow the same rules as for members: never the key’s creator, the owner, an admin, or a member with more rights than the key (403 ). The person concerned receives an email for each action, when email sending is set up.
Read a member’s accountLink to the Read a member’s account section
GET / · members:read
{
"managed": true,
"managed_reason": "domain",
"member_status": "active",
"account": {
"name": "Camille Martin",
"email": "camille.martin@ecole.fr",
"status": "active",
"disabled_by_org": false,
"sign_in": ["password", "google"],
"two_factor": { "enabled": true, "method": "totp", "backup_codes_remaining": 8 },
"last_active_at": 1762332000,
"created_at": 1756684800,
"sessions_revoked_at": null,
"two_factor_required": true
},
"devices": [
{ "kind": "cli", "label": "Moon CLI", "created_at": 1762300000, "last_active_at": 1762330000, "expires_at": 1764892000, "ip": "203.0.113.x" },
{ "kind": "web", "label": "Chrome · Windows", "created_at": 1762331000, "last_active_at": 1762331000, "expires_at": null, "ip": "2001:0db8:0001::" }
],
"verified_domains": ["ecole.fr"],
"blocked": null,
"can": { "sign_out_org": true, "sign_out_account": true, "edit": true, "reset_2fa": true, "password_reset": true, "disable": true, "enable": false, "offboard": true, "transfer_private": true }
}| Field | Description |
|---|---|
managed_reason | domain, sso, scim or null (the person’s own account). |
account.status | Status of the account on the platform; disabled_by_org says whether this organization disabled it. |
account.sign_in | Sign-in methods: password, the linked providers, sso. |
devices | Moon CLI sessions open on the organization and, for a managed account, signed-in browsers, with a masked IP address. null when the key cannot sign this member out. |
can | What the key can do to this account. |
Sign a member outLink to the Sign a member out section
POST / · members:write
| Field | Type | Required | Description |
|---|---|---|---|
scope | string | no | organization (default): the sessions can no longer act in the organization; other workspaces stay signed in. account: every session of the account, everywhere (managed account; also requires security:read or security:write). |
Response: {"scope": (Moon CLI sessions closed), or {"scope": .
Reset two-factor authenticationLink to the Reset two-factor authentication section
POST / · security:write · managed account
Removes the authenticator app, the email code and the backup codes; the person sets it up again the next time they sign in. All their sessions are closed. Response: {"reset": .
Send a password reset codeLink to the Send a password reset code section
POST / · security:write · managed account
Sends the person a 6-digit code valid for 15 minutes; it is never shown to the organization. Response: {"sent": .
| Status | code | Cause |
|---|---|---|
| 409 | sso_required | Single sign-on is required for this account: it has no password. |
| 429 | rate_limited | A code was already requested for this person in the last 10 minutes, even if sending it failed. |
| 502 | error | The email could not be sent. |
| 503 | smtp_unavailable | Email sending is not set up. |
Change the name or email addressLink to the Change the name or email address section
PATCH / · security:write · managed account
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | 1 to 128 characters. |
email | string | no | An email address on a domain verified by the organization. |
Response: {"changed": . A new email address closes every session and must be confirmed at the next sign-in; both the old and the new address are notified.
| Status | code | Cause |
|---|---|---|
| 400 | invalid_request | Nothing to change, empty or too long name, invalid email address. |
| 400 | email_domain_not_verified | The email address is not on a domain verified by the organization. |
| 409 | email_taken | The email address is already used by another account. |
Disable and reactivate an accountLink to the Disable and reactivate an account section
POST / · security:write · managed account
The person can no longer sign in anywhere; they remain a member. All their sessions are closed. Response: {"disabled": .
POST / · security:write · managed account
Reverses a disabling done by this organization, and only by this one. Response: {"disabled": .
| Status | code | Cause |
|---|---|---|
| 409 | not_active | The account is not active (when disabling). |
| 409 | owns_workspace | The account owns another team workspace with members: transfer it first. |
| 409 | not_disabled_by_org | The account was not disabled by this organization (when reactivating). |
| 409 | invalid_request | The organization would be left without an active admin. |
Offboarding a memberLink to the Offboarding a member section
List what they ownLink to the List what they own section
GET / · members:read
{
"resources": {
"agents": { "total": 2, "shared": 2 },
"knowledge": { "total": 5, "shared": 3 },
"notes": { "total": 12, "shared": 1 },
"prompts": { "total": 4, "shared": 4 },
"tools": { "total": 0, "shared": 0 }
},
"managed": true,
"kinds": ["agents", "knowledge", "notes", "prompts", "tools"]
}Transfer, remove, disableLink to the Transfer, remove, disable section
POST / · members:write
Runs these steps in order: transfer of resources, removal from the organization, disabling of the account. Everything is checked before the first change.
| Field | Type | Required | Description |
|---|---|---|---|
transfer_to | string | with kinds | An active member who receives the resources. |
kinds | list | no | agents, knowledge, notes, prompts, tools. |
include_private | boolean | no | Also transfer resources that are not shared (managed account; requires security:read or security:write). Otherwise, only shared resources are transferred. |
remove | boolean | no | true by default: remove the member from the organization. |
disable_account | boolean | no | Disable the account (managed account; requires security:read or security:write). |
curl https://chat.realmoon.ai/api/v1/orgs/$ORG_ID/members/$USER_ID/offboard \
-H "Authorization: Bearer $MOONAI_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"transfer_to": "<successor id>", "kinds": ["knowledge", "prompts"], "remove": true}'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}/members/{os.environ['USER_ID']}/offboard",
headers=HEADERS,
json={"transfer_to": os.environ["SUCCESSOR_ID"], "kinds": ["knowledge", "prompts"], "remove": True},
timeout=60,
)
r.raise_for_status()
print(r.json())const BASE = `https://chat.realmoon.ai/api/v1/orgs/${process.env.ORG_ID}`;
const r = await fetch(`${BASE}/members/${process.env.USER_ID}/offboard`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.MOONAI_ADMIN_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ transfer_to: process.env.SUCCESSOR_ID, kinds: ['knowledge', 'prompts'], remove: true }),
});
if (!r.ok) throw new Error(await r.text());
console.log(await r.json());Response: {"transferred": (with disabled_at when the account was disabled). Transferred resources keep their shares. The removal sends the member.removed event.
| Status | code | Cause |
|---|---|---|
| 400 | invalid_request | Nothing to do, kinds without transfer_to, no known type, transfer to the person themselves. |
| 409 | invalid_target | transfer_to is not an active member. |
| 409 | not_managed_account | include_private or disable_account on an account that belongs to the person. |
| 409 | invalid_request | The organization would be left without an active admin. |
Account requirementsLink to the Account requirements section
Read the requirementsLink to the Read the requirements section
GET / · security:read
{
"settings": { "require_2fa": true, "grace_until": 1763000000, "max_session_hours": 168, "sessions_valid_after": null, "updated_at": 1762339200, "updated_by": "3f2b9c1d-7e4a-4b8c-9d0e-1f2a3b4c5d6e" },
"limits": { "grace_days_max": 90, "session_hours_min": 1, "session_hours_max": 2160 },
"sso": { "configured": true, "active": true, "enforced": false },
"verified_domains": ["ecole.fr"],
"members": { "active": 120, "compliant": 97, "missing": 23 }
}A member meets the requirements when they have turned on two-factor authentication, or when they sign in through the organization’s required single sign-on.
Change the requirementsLink to the Change the requirements section
PUT / · security:write
| Field | Type | Required | Description |
|---|---|---|---|
require_2fa | boolean | no | Require two-factor authentication. false removes the requirement and the grace period. |
grace_days | integer | no | Grace period from 0 to 90 days, counted from now. 0 or missing when turning it on: required immediately. |
max_session_hours | integer | no | Maximum session length, from 1 to 2,160 hours; null removes the limit. |
Send at least one field; a missing field does not change. The response has the same shape as the read, without members. Requiring two-factor authentication right away returns 409 when the key’s creator has not turned it on themselves. A member without two-factor authentication once the grace period is over can no longer work in the organization (403 ).
List members who do not meet the requirementsLink to the List members who do not meet the requirements section
GET / · security:read
Parameters: filter (missing, the default, or all), page, limit. Each item: user_id, name, email, last_active_at, two_factor. The response also includes settings, active_members, compliant and missing.
Sign everyone outLink to the Sign everyone out section
POST / · security:write
No session opened before now can act in the organization any longer: everyone signs in again, including the key’s creator. The key itself keeps working. Response: {"signed_out": .
What the organization requires of the key’s creatorLink to the What the organization requires of the key’s creator section
GET / · no scope
Returns require_2fa, two_factor_enabled, two_factor_missing, grace_until, blocked, can_switch_out and max_session_hours for the person who created the key.