DocsOpen Moon AI
Browse the docs

Member accounts through the API

Read a member’s account, sign them out, reset their two-factor authentication, disable it, offboard them and manage account requirements through the API.

On this page

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 not_managed_account.

All routes live under https://chat.realmoon.ai/api/v1/orgs/{org_id}. 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 forbidden). 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/{user_id}/account · members:read

JSON
{
  "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 }
}
FieldDescription
managed_reasondomain, sso, scim or null (the person’s own account).
account.statusStatus of the account on the platform; disabled_by_org says whether this organization disabled it.
account.sign_inSign-in methods: password, the linked providers, sso.
devicesMoon 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.
canWhat the key can do to this account.

Sign a member outLink to the Sign a member out section

POST /members/{user_id}/account/sign-out · members:write

FieldTypeRequiredDescription
scopestringnoorganization (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": "organization", "signed_out": true, "cli_revoked": 2} (Moon CLI sessions closed), or {"scope": "account", "signed_out": true}.

Reset two-factor authenticationLink to the Reset two-factor authentication section

POST /members/{user_id}/account/reset-2fa · 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": true, "had_two_factor": true}.

Send a password reset codeLink to the Send a password reset code section

POST /members/{user_id}/account/password-reset · security:write · managed account

Sends the person a 6-digit code valid for 15 minutes; it is never shown to the organization. Response: {"sent": true, "email_hint": "c***@ecole.fr"}.

StatuscodeCause
409sso_requiredSingle sign-on is required for this account: it has no password.
429rate_limitedA code was already requested for this person in the last 10 minutes, even if sending it failed.
502errorThe email could not be sent.
503smtp_unavailableEmail sending is not set up.

Change the name or email addressLink to the Change the name or email address section

PATCH /members/{user_id}/account · security:write · managed account

FieldTypeRequiredDescription
namestringno1 to 128 characters.
emailstringnoAn email address on a domain verified by the organization.

Response: {"changed": ["email", "name"], "name": "…", "email": "…"}. 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.

StatuscodeCause
400invalid_requestNothing to change, empty or too long name, invalid email address.
400email_domain_not_verifiedThe email address is not on a domain verified by the organization.
409email_takenThe email address is already used by another account.

Disable and reactivate an accountLink to the Disable and reactivate an account section

POST /members/{user_id}/account/disable · security:write · managed account

The person can no longer sign in anywhere; they remain a member. All their sessions are closed. Response: {"disabled": true, "disabled_at": 1762339200}.

POST /members/{user_id}/account/enable · security:write · managed account

Reverses a disabling done by this organization, and only by this one. Response: {"disabled": false}.

StatuscodeCause
409not_activeThe account is not active (when disabling).
409owns_workspaceThe account owns another team workspace with members: transfer it first.
409not_disabled_by_orgThe account was not disabled by this organization (when reactivating).
409invalid_requestThe 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/{user_id}/resources · members:read

JSON
{
  "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/{user_id}/offboard · 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.

FieldTypeRequiredDescription
transfer_tostringwith kindsAn active member who receives the resources.
kindslistnoagents, knowledge, notes, prompts, tools.
include_privatebooleannoAlso transfer resources that are not shared (managed account; requires security:read or security:write). Otherwise, only shared resources are transferred.
removebooleannotrue by default: remove the member from the organization.
disable_accountbooleannoDisable the account (managed account; requires security:read or security:write).
cURL
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}'
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}/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())
JavaScript
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": {"knowledge": 3, "prompts": 4}, "removed": true, "account_disabled": false} (with disabled_at when the account was disabled). Transferred resources keep their shares. The removal sends the member.removed event.

StatuscodeCause
400invalid_requestNothing to do, kinds without transfer_to, no known type, transfer to the person themselves.
409invalid_targettransfer_to is not an active member.
409not_managed_accountinclude_private or disable_account on an account that belongs to the person.
409invalid_requestThe 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/requirements · security:read

JSON
{
  "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/requirements · security:write

FieldTypeRequiredDescription
require_2fabooleannoRequire two-factor authentication. false removes the requirement and the grace period.
grace_daysintegernoGrace period from 0 to 90 days, counted from now. 0 or missing when turning it on: required immediately.
max_session_hoursintegernoMaximum 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 actor_without_2fa 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 org_2fa_required).

List members who do not meet the requirementsLink to the List members who do not meet the requirements section

GET /security/requirements/members · 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/sign-out-all · 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": true, "valid_after": 1762339200}.

What the organization requires of the key’s creatorLink to the What the organization requires of the key’s creator section

GET /me/requirements · 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.

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.