recall.org
Manage org profile, membership, and plan usage with recall.org (SyncOrg / AsyncOrg).
All methods exist on both SyncOrg (via Recall) and AsyncOrg (via
AsyncRecall) with identical signatures. Every example shows both variants.
profile()
def profile(self) -> dict: ...Fetch the org's public profile fields.
Returns
{
"id": "org_01HEX…",
"name": "Acme Corp",
"slug": "acme-corp", # immutable after creation
"createdAt": "2025-11-01T08:00:00Z",
}Examples
org = recall.org.profile()
print(org["name"], "/", org["slug"])org = await recall.org.profile()
print(org["name"], "/", org["slug"])patch_profile()
def patch_profile(
self,
*,
name: Optional[str] = None,
) -> dict: ...Update mutable org profile fields. name is the only mutable field — slug
is set at org creation and cannot be changed.
Parameters
namestroptionalNew display name for the org. Does not affect the slug or any URLs.
Returns
Returns the updated org profile with the same shape as profile().
Examples
updated = recall.org.patch_profile(name="Acme AI Platform")
print("New name:", updated["name"])updated = await recall.org.patch_profile(name="Acme AI Platform")
print("New name:", updated["name"])members()
def members(
self,
*,
limit: int = 20,
cursor: Optional[str] = None,
) -> dict: ...List org members with their roles and join timestamps.
Parameters
limitintoptionalMembers per page. Server clamps to [1, 100].
cursorstroptionalOpaque cursor from the previous page's meta.nextCursor.
Returns
Each item in items is an OrgMember:
{
"items": [
{
"userId": "usr_01HEX…",
"email": "alice@acme.com",
"role": "admin",
"joinedAt": "2025-11-01T08:00:00Z",
},
# …
],
"meta": { "count": 4, "limit": 20, "nextCursor": None },
}Roles
| Role | What it can do |
|---|---|
owner | Founding user. Cannot be transferred or removed. |
admin | Manage members, billing, all API keys, all agents. |
member | Read/write memories within assigned agent scope. Cannot manage members. |
Examples
page = recall.org.members()
for m in page["items"]:
print(m["email"], "—", m["role"])page = await recall.org.members()
for m in page["items"]:
print(m["email"], "—", m["role"])invite_member()
def invite_member(
self,
email: str,
role: str = "member", # 'admin' or 'member'
) -> dict: ...Send an invitation email to a new org member. The invitee receives a sign-up link and is added to the org's member list on first login.
Parameters
emailstrrequiredEmail address of the person to invite. Must be a valid email. If the
address already belongs to an org member, the server returns a
RecallValidationError.
rolestroptionalRole to assign. One of 'admin' or 'member'. 'owner' cannot be
assigned via this endpoint — it is reserved for the founding user.
Returns
Returns the OrgMember record created by the invitation:
{
"userId": "usr_pending_01HEX…",
"email": "alice@acme.com",
"role": "admin",
"joinedAt": None, # null until the invitee accepts
}Examples
member = recall.org.invite_member("alice@acme.com", role="admin")
print(f"Invited {member['email']} as {member['role']}")member = await recall.org.invite_member("alice@acme.com", role="admin")
print(f"Invited {member['email']} as {member['role']}")remove_member()
def remove_member(self, user_id: str) -> dict: ...Remove a member from the org. The owner role cannot be removed — attempts
return RecallValidationError.
Parameters
user_idstrrequiredThe userId of the member to remove, as returned by members().
Returns
{
"userId": "usr_01HEX…",
"deletedAt": "2026-05-10T10:00:00Z",
}The removed user's API keys are NOT automatically revoked. Their keys
remain valid until explicitly deleted. After removing a member, enumerate
their keys with recall.keys.list(agent_id=…) and call
recall.keys.delete() on each to close the access gap.
Examples
result = recall.org.remove_member("usr_01HEX…")
print("Removed at:", result["deletedAt"])result = await recall.org.remove_member("usr_01HEX…")
print("Removed at:", result["deletedAt"])plan()
def plan(self) -> dict: ...Fetch the org's current plan tier and live usage counters. Use this before bulk operations to check headroom before hitting a plan limit mid-loop.
Returns
{
"tier": "pro",
"memoriesUsed": 45_230,
"memoriesLimit": 100_000,
"agentsUsed": 3,
"agentsLimit": 10,
"namespacesUsed": 2,
"namespacesLimit": 5,
}Limits reset on the billing-cycle anniversary — not on the calendar month boundary.
Examples
# Pre-flight guard before a bulk memory import
plan = recall.org.plan()
headroom = plan["memoriesLimit"] - plan["memoriesUsed"]
if headroom < batch_size:
raise RuntimeError(
f"Only {headroom:,} memory slots remain. "
"Upgrade plan or call recall.memories.forget() to free space."
)
# Safe to proceed
for batch in batches:
recall.memories.write(messages=batch)plan = await recall.org.plan()
headroom = plan["memoriesLimit"] - plan["memoriesUsed"]
if headroom < batch_size:
raise RuntimeError(
f"Only {headroom:,} memory slots remain. "
"Upgrade plan or call recall.memories.forget() to free space."
)
for batch in batches:
await recall.memories.write(messages=batch)Errors
RecallAuthError401/403fatalAPI key missing, expired, or lacks admin scope.
RecallNotFoundError404fatalMember user ID does not exist in the org.
RecallValidationError422fatalAttempted to remove the owner, duplicate invite email, invalid role, etc.
RecallRateLimitError429fatalRate limit exceeded. Inspect .retry_after_ms.
RecallServerError5xxfatalServer-side failure. Retried automatically up to max_retries.
Was this page helpful?