Brainby arc-labs/docs
Sdk pythonrecall.org
Python SDK

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()

GET/v1/orgAPI key (admin)stable
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()

PATCH/v1/orgAPI key (admin)stable
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

ParameterTypeRequired
namestroptional

New 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()

GET/v1/org/membersAPI key (admin)stable
def members(
    self,
    *,
    limit: int = 20,
    cursor: Optional[str] = None,
) -> dict: ...

List org members with their roles and join timestamps.

Parameters

ParameterTypeRequired
limitintoptional

Members per page. Server clamps to [1, 100].

cursorstroptional

Opaque 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

RoleWhat it can do
ownerFounding user. Cannot be transferred or removed.
adminManage members, billing, all API keys, all agents.
memberRead/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()

POST/v1/org/members/inviteAPI key (admin)stable
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

ParameterTypeRequired
emailstrrequired

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

rolestroptional

Role 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()

DELETE/v1/org/members/:user_idAPI key (admin)stable
def remove_member(self, user_id: str) -> dict: ...

Remove a member from the org. The owner role cannot be removed — attempts return RecallValidationError.

Parameters

ParameterTypeRequired
user_idstrrequired

The 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()

GET/v1/org/planAPI key (admin)stable
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

CodeStatusRetry
RecallAuthError401/403fatal

API key missing, expired, or lacks admin scope.

RecallNotFoundError404fatal

Member user ID does not exist in the org.

RecallValidationError422fatal

Attempted to remove the owner, duplicate invite email, invalid role, etc.

RecallRateLimitError429fatal

Rate limit exceeded. Inspect .retry_after_ms.

RecallServerError5xxfatal

Server-side failure. Retried automatically up to max_retries.

Was this page helpful?

On this page