Users & Organizations
Manage user accounts, organization membership, API keys, and authentication.
Overview
Three resources handle identity and access:
- Auth (
client.auth) -- Manage API keys and verify the current session. - Users (
client.users) -- List, create, and update user accounts; manage your own profile. - Organizations (
client.organizations) -- Manage organization settings, members, invitations, and credits.
Auth
Verify Your Session
from strongly import Strongly
client = Strongly()
me = client.auth.whoami()
print(f"User: {me.name} ({me.email})")
print(f"User ID: {me.user_id}")
print(f"Roles: {me.roles}")
print(f"Organization: {me.organization.id}")
print(f"API key prefix: {me.api_key.key_prefix}")
WhoamiResponse Fields
| Field | Type | Description |
|---|---|---|
user_id | str | Current user ID |
email | str | Current user email |
name | str | Current user name |
roles | list | Assigned roles |
organization | WhoamiOrganization | Organization details |
api_key | WhoamiApiKey | API key details |
Creating API Keys
from strongly import Strongly
client = Strongly()
key = client.auth.create_key(
name="ci-pipeline",
scopes=["workflows:read", "workflows:execute", "executions:read"],
expires_in_days=90,
)
print(f"Key ID: {key.id}")
print(f"Key: {key.key}") # Only shown once -- store it securely
print(f"Prefix: {key.key_prefix}")
print(f"Expires: {key.expires_at}")
ApiKeyCreateResponse Fields
| Field | Type | Description |
|---|---|---|
id | str | Key identifier |
key | str | The full API key (only returned at creation time) |
key_prefix | str | Key prefix for identification |
name | str | Key name |
scopes | list | Permitted scopes |
expires_at | str | Expiration timestamp |
Managing API Keys
from strongly import Strongly
client = Strongly()
# List all keys
for key in client.auth.list_keys():
print(f"{key.name} ({key.key_prefix}...) — {key.status}")
# Filter by status
for key in client.auth.list_keys(status="active"):
print(f"{key.name} — last used: {key.last_used_at}")
# Get a specific key
key = client.auth.get_key("key-abc123")
print(f"{key.name}: scopes={key.scopes}, status={key.status}")
# Rotate a key (generates a new secret, invalidates the old one)
rotated = client.auth.rotate_key("key-abc123")
print(f"New key: {rotated.key}") # Store this securely
print(f"Expires: {rotated.expires_at}")
# Revoke a key
client.auth.revoke_key("key-abc123")
print("Key revoked")
ApiKeyRotateResponse Fields
| Field | Type | Description |
|---|---|---|
id | str | Key identifier |
key | str | The new API key (only returned once) |
key_prefix | str | New key prefix |
expires_at | str | New expiration timestamp |
ApiKey Model
| Field | Type | Description |
|---|---|---|
id | str | Unique key identifier |
key_prefix | str | Key prefix for identification |
name | str | Key name |
user_id | str | Owner user ID |
organization_id | str | Organization ID |
scopes | list | Permitted scopes |
status | str | Key status (active, revoked, expired) |
expires_at | str | Expiration timestamp |
last_used_at | str | Last usage timestamp |
last_used_ip | str | Last usage IP address |
revoked_at | str | When the key was revoked |
revoked_by | str | Who revoked the key |
metadata | dict | Custom metadata |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Auth Method Reference
| Method | Description | Returns |
|---|---|---|
create_key(*, name, scopes, expires_in_days=None) | Create a new API key | ApiKeyCreateResponse |
list_keys(*, status=None, limit=50) | List API keys | SyncPaginator[ApiKey] |
get_key(key_id) | Get a key by ID | ApiKey |
revoke_key(key_id) | Revoke a key | dict |
rotate_key(key_id) | Rotate a key (new secret) | ApiKeyRotateResponse |
whoami() | Get current session info | WhoamiResponse |
Users
Your Profile
from strongly import Strongly
client = Strongly()
# Get your own profile
me = client.users.me()
print(f"Name: {me.name}")
print(f"Email: {me.email}")
print(f"Role: {me.role}")
print(f"Organization: {me.organization.name}")
# Update your profile
updated = client.users.update_me({
"name": "Jane Doe",
"profile": {
"title": "Senior ML Engineer",
"timezone": "America/New_York",
},
})
print(f"Updated: {updated['name']}")
Listing Users
from strongly import Strongly
client = Strongly()
# List all users
for user in client.users.list():
print(f"{user.name} ({user.email}) — {user.role}")
# Search by name or email
for user in client.users.list(search="jane"):
print(f"{user.name} — {user.email}")
# Filter by active status
for user in client.users.list(active=True):
print(f"{user.name} — last login: {user.last_login_at}")
# Exclude archived users
for user in client.users.list(archived=False):
print(user.name)
Creating a User
from strongly import Strongly
client = Strongly()
user = client.users.create({
"email": "new-hire@company.com",
"name": "New Hire",
"role": "user",
"password": "InitialPassword123!",
})
print(f"User ID: {user.id}")
print(f"Status: {user.status}")
Managing Users
from strongly import Strongly
client = Strongly()
user_id = "user-abc123"
# Get a specific user
user = client.users.retrieve(user_id)
print(f"{user.name} — {user.role}")
# Update a user
updated = client.users.update(user_id, {
"role": "admin",
})
print(f"Updated role: {updated.role}")
# Archive a user
client.users.archive(user_id)
print("User archived")
# Reset a user's password
client.users.reset_password(user_id)
print("Password reset email sent")
User API Keys
Manage API keys for your own account through the users resource:
from strongly import Strongly
client = Strongly()
# List your API keys
keys = client.users.api_keys()
for key in keys:
print(f"{key.name} — {key.status}")
# Create a new API key
result = client.users.create_api_key({
"name": "notebook-access",
"scopes": ["projects:read", "workspaces:read", "workspaces:write"],
})
print(f"New key: {result.get('key')}")
# Revoke a key
client.users.revoke_api_key("key-abc123")
User Model
| Field | Type | Description |
|---|---|---|
id | str | Unique user identifier |
email | str | Primary email address |
emails | list | All email addresses |
name | str | Display name |
username | str | Username |
profile | UserProfile | Profile details (title, timezone, etc.) |
role | str | Primary role |
roles | list | All assigned roles |
status | str | Account status |
organization_id | str | Organization ID |
organization | UserOrganization | Organization details |
avatar_url | str | Avatar image URL |
last_login | str | Last login timestamp |
last_login_at | str | Last login timestamp (ISO format) |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Users Method Reference
| Method | Description | Returns |
|---|---|---|
list(*, search=None, archived=None, active=None, limit=50) | List users with optional filters | SyncPaginator[User] |
me() | Get your own profile | User |
update_me(body) | Update your profile | dict |
retrieve(user_id) | Get a user by ID | User |
create(body) | Create a new user | User |
update(user_id, body) | Update a user | User |
archive(user_id) | Archive a user | dict |
reset_password(user_id) | Send a password reset | dict |
api_keys() | List your API keys | List[ApiKeyInfo] |
create_api_key(body) | Create an API key | dict |
revoke_api_key(key_id) | Revoke an API key | dict |
Organizations
Basic Usage
from strongly import Strongly
client = Strongly()
# List organizations you belong to
for org in client.organizations.list():
print(f"{org.name} ({org.plan}) — {org.member_count} members")
# Get a specific organization
org = client.organizations.retrieve("org-abc123")
print(f"{org.name}: {org.description}")
print(f"Plan: {org.plan}")
print(f"Namespace: {org.namespace}")
Updating an Organization
from strongly import Strongly
client = Strongly()
updated = client.organizations.update("org-abc123", {
"name": "Acme Corp AI",
"description": "Enterprise AI platform for Acme Corp",
"settings": {
"default_workspace_image": "strongly/pytorch:2.1-cuda",
"enforce_mfa": True,
},
})
print(f"Updated: {updated.name}")
Member Management
from strongly import Strongly
client = Strongly()
org_id = "org-abc123"
# List members
members = client.organizations.members(org_id)
for m in members:
owner_tag = " [owner]" if m.is_owner else ""
print(f" {m.name} ({m.email}) — {m.role}{owner_tag}")
# Add a member by user ID
client.organizations.add_member(org_id, user_id="user-xyz789", role="member")
# Change a member's role
client.organizations.update_member_role(org_id, "user-xyz789", role="admin")
# Remove a member
client.organizations.remove_member(org_id, "user-xyz789")
Member Fields
| Field | Type | Description |
|---|---|---|
user_id | str | User identifier |
role | str | Role within the organization |
email | str | User email |
name | str | User name |
joined_at | str | When the user joined |
is_owner | bool | Whether this user is the organization owner |
Invitations
Invite external users by email:
from strongly import Strongly
client = Strongly()
org_id = "org-abc123"
# Send an invitation
client.organizations.invite(org_id, email="new-user@company.com", role="member")
print("Invitation sent")
# List pending invitations
invitations = client.organizations.list_invitations(org_id)
for inv in invitations:
print(f" {inv.email} — {inv.role} ({inv.status}) — expires: {inv.expires_at}")
# Cancel an invitation
client.organizations.cancel_invitation(org_id, "inv-abc123")
print("Invitation cancelled")
Invitation Fields
| Field | Type | Description |
|---|---|---|
id | str | Invitation identifier |
email | str | Invited email address |
role | str | Assigned role |
status | str | Invitation status (pending, accepted, expired, cancelled) |
invited_by | str | Who sent the invitation |
expires_at | str | Expiration timestamp |
organization_id | str | Organization ID |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Credits and Billing
from strongly import Strongly
client = Strongly()
org_id = "org-abc123"
# Check credit balance
credits = client.organizations.credits(org_id)
print(f"Balance: {credits.balance} {credits.currency}")
print(f"Total used: {credits.total_used}")
print(f"Total purchased: {credits.total_purchased}")
# View transaction history
transactions = client.organizations.transactions(org_id, limit=20)
for tx in transactions:
print(f" {tx.get('created_at')} — {tx.get('type')}: {tx.get('amount')} {tx.get('currency')}")
OrganizationCredits Fields
| Field | Type | Description |
|---|---|---|
balance | float | Current credit balance |
total_used | float | Total credits consumed |
total_purchased | float | Total credits purchased |
currency | str | Currency code |
Organization Model
| Field | Type | Description |
|---|---|---|
id | str | Unique organization identifier |
name | str | Organization name |
description | str | Human-readable description |
status | str | Organization status |
plan | str | Subscription plan |
member_count | int | Number of members |
credits | float | Current credit balance |
owner_id | str | Owner user ID |
namespace | str | Kubernetes namespace |
settings | dict | Organization settings |
created_at | str | Creation timestamp |
updated_at | str | Last update timestamp |
Organizations Method Reference
| Method | Description | Returns |
|---|---|---|
list() | List organizations | SyncPaginator[Organization] |
retrieve(org_id) | Get an organization by ID | Organization |
update(org_id, body) | Update organization fields | Organization |
members(org_id) | List organization members | List[Member] |
add_member(org_id, *, user_id, role="member") | Add a member | dict |
remove_member(org_id, user_id) | Remove a member | dict |
update_member_role(org_id, user_id, *, role) | Change a member's role | dict |
invite(org_id, *, email, role="member") | Send an invitation | dict |
list_invitations(org_id) | List pending invitations | List[Invitation] |
cancel_invitation(org_id, invite_id) | Cancel an invitation | dict |
credits(org_id) | Get credit balance | OrganizationCredits |
transactions(org_id, *, limit=50) | Get transaction history | List[CreditTransaction] |
Complete Example
from strongly import Strongly
def main():
client = Strongly()
# --- Verify session ---
print("=== Current Session ===")
me = client.auth.whoami()
print(f"User: {me.name} ({me.email})")
print(f"Organization: {me.organization.id}")
print(f"Roles: {me.roles}")
# --- Create a scoped API key ---
print("\n=== Creating API Key ===")
key = client.auth.create_key(
name="data-pipeline-key",
scopes=["workflows:read", "workflows:execute", "executions:read"],
expires_in_days=30,
)
print(f"Key: {key.key_prefix}... (save the full key securely)")
print(f"Expires: {key.expires_at}")
# --- List team members ---
my_profile = client.users.me()
org_id = my_profile.organization_id
print(f"\n=== Organization Members ({org_id}) ===")
members = client.organizations.members(org_id)
for m in members:
owner_tag = " [owner]" if m.is_owner else ""
print(f" {m.name} ({m.email}) — {m.role}{owner_tag}")
# --- Invite a new team member ---
print("\n=== Sending Invitation ===")
client.organizations.invite(org_id, email="data-engineer@company.com", role="member")
print("Invitation sent to data-engineer@company.com")
invitations = client.organizations.list_invitations(org_id)
for inv in invitations:
print(f" {inv.email} — {inv.status}")
# --- Check credits ---
print("\n=== Credits ===")
credits = client.organizations.credits(org_id)
print(f"Balance: {credits.balance} {credits.currency}")
print(f"Used: {credits.total_used}")
# --- List users ---
print("\n=== Active Users ===")
for user in client.users.list(active=True):
print(f" {user.name} ({user.email}) — {user.role}")
# --- Create a service account user ---
print("\n=== Creating Service Account ===")
svc_user = client.users.create({
"email": "ci-bot@company.com",
"name": "CI Bot",
"role": "user",
"password": "SecurePassword456!",
})
print(f"User ID: {svc_user.id}")
# --- Manage API keys ---
print("\n=== API Key Management ===")
for key in client.auth.list_keys(status="active"):
print(f" {key.name} ({key.key_prefix}...) — last used: {key.last_used_at}")
# Rotate the key we created earlier
rotated = client.auth.rotate_key(key.id)
print(f"\nRotated key: {rotated.key_prefix}...")
# --- View transaction history ---
print("\n=== Recent Transactions ===")
transactions = client.organizations.transactions(org_id, limit=5)
for tx in transactions:
print(f" {tx.get('created_at')} — {tx.get('type')}: {tx.get('amount')}")
if __name__ == "__main__":
main()