Global Admin Service
Manage developer accounts, API keys, and users across the entire system. All operations require global admin privileges.
Global Admin Only
This service requires global admin privileges. Regular developers cannot access these endpoints.
Initialize the Service
from vclient import global_admin_service
admins = global_admin_service()
Available Methods
Developer CRUD Operations
| Method | Returns | Description |
|---|---|---|
get_developer(developer_id) |
Developer |
Retrieve a developer by ID |
create_developer(request=None, **kwargs) |
Developer |
Create a new developer account |
update_developer(developer_id, request=None, **kwargs) |
Developer |
Update developer properties |
delete_developer(developer_id) |
None |
Delete a developer account |
Developer Pagination Methods
| Method | Returns | Description |
|---|---|---|
get_developer_page(limit=10, offset=0, is_global_admin=None) |
PaginatedResponse[Developer] |
Retrieve a paginated page |
list_all_developers(is_global_admin=None) |
list[Developer] |
Retrieve all developers |
iter_all_developers(limit=100, is_global_admin=None) |
AsyncIterator[Developer] |
Iterate through all developers |
API Key Management
| Method | Returns | Description |
|---|---|---|
create_api_key(developer_id) |
DeveloperWithApiKey |
Generate a new API key for a developer |
Server Logs
Inspect the API server's on-disk logs without shelling into the host. Both methods require global admin privileges and that file logging is enabled on the server.
| Method | Returns | Description |
|---|---|---|
tail_logs(level=None, limit=100) |
list[ServerLogEntry] |
Return the most recent log entries, newest first |
download_logs() |
ServerLogArchive |
Download a zip archive of all log files |
tail_logs parameters
level: minimum log level to include. One of"TRACE","DEBUG","INFO","WARNING","ERROR","CRITICAL"(theLogLeveltype). When omitted, the server uses its configured level.limit: maximum number of entries to return. Clamped client-side to 1-500, defaulting to 100.
File logging required
Both methods raise ConflictError (HTTP 409) when file logging is not enabled on the server. download_logs also raises ConflictError when no log files exist. Without global admin privileges, both raise AuthorizationError (HTTP 403).
Cross-Company User Methods
Global Admin Key Required
These methods require a global-admin API key. They do not accept an On-Behalf-Of header. The company-scoped role hierarchy is bypassed, and archived (soft-deleted) users are returned and restorable.
Manage users across all companies from a single service. Archived users appear in results and can be restored by passing is_archived=False to update_user.
User CRUD Operations
| Method | Returns | Description |
|---|---|---|
get_user(user_id) |
AdminUser |
Retrieve a user by ID |
create_user(request=None, **kwargs) |
AdminUser |
Create a new user in a company |
update_user(user_id, request=None, **kwargs) |
AdminUser |
Update user properties or restore user |
delete_user(user_id) |
None |
Soft-delete a user (reversible) |
User Pagination Methods
| Method | Returns | Description |
|---|---|---|
get_user_page(*, company_id=None, role=None, email=None, is_archived=None, limit=10, offset=0) |
PaginatedResponse[AdminUser] |
Retrieve a paginated page |
list_all_users(*, company_id=None, role=None, email=None, is_archived=None) |
list[AdminUser] |
Retrieve all users |
iter_all_users(*, limit=100, company_id=None, role=None, email=None, is_archived=None) |
AsyncIterator[AdminUser] |
Iterate through all users |
Filter parameters for user pagination
company_id: narrow results to a specific company.role: filter byUserRolevalue (ADMIN,STORYTELLER,PLAYER,UNAPPROVED).email: filter by email address.is_archived: whenTrue, return only archived users; whenFalse, return only active users; when omitted, return both.
Examples
Create a Developer Account
Add a new developer to the system.
from vclient.models import DeveloperCreate
# Option 1: Use a model object (preferred)
request = DeveloperCreate(
username="newdev",
email="dev@example.com",
is_global_admin=False
)
dev = await admins.create_developer(request)
# Option 2: Pass fields as keyword arguments
dev = await admins.create_developer(
username="newdev",
email="dev@example.com"
)
Update Developer Settings
Modify a developer account's properties.
from vclient.models import DeveloperUpdate
update = DeveloperUpdate(
email="newemail@example.com",
is_global_admin=True
)
updated = await admins.update_developer(dev.id, update)
# Register per-developer OIDC audiences so the developer's own apps
# can issue tokens that the identity endpoint will accept.
updated = await admins.update_developer(
dev.id,
provider_audiences={
"apple": ["com.example.iosapp"],
"google": ["1234-abc.apps.googleusercontent.com"],
},
)
Generate API Key
Create a new API key for an existing developer.
dev_with_key = await admins.create_api_key(dev.id)
print(f"New API Key: {dev_with_key.api_key}")
Save API Keys Immediately
API keys are only displayed once during creation. Save the key from the response - it cannot be retrieved later.
Audit Logs
View audit trail entries for a specific developer across all companies. Requires global admin privileges.
# Get a page of audit logs for a developer
page = await admins.get_audit_log_page(dev.id)
# Filter to a specific company
page = await admins.get_audit_log_page(
dev.id,
company_id="company123",
operation="CREATE",
)
# Include request forensic details
page = await admins.get_audit_log_page(
dev.id,
include=["request_details"],
)
| Method | Returns | Description |
|---|---|---|
get_audit_log_page(developer_id, **filters) |
PaginatedResponse[AuditLog \| AuditLogDetail] |
Get a page of audit log entries |
list_all_audit_logs(developer_id, **filters) |
list[AuditLog \| AuditLogDetail] |
Get all audit log entries |
iter_all_audit_logs(developer_id, **filters) |
AsyncIterator[AuditLog \| AuditLogDetail] |
Iterate through all audit log entries |
The admin endpoint accepts all the same filter parameters as the company audit log (see Companies Service), plus company_id to narrow results to a specific company.
Tail Server Logs
Read the most recent server log entries, newest first.
# Get the latest 100 entries at the server's configured level
entries = await admins.tail_logs()
for entry in entries:
print(f"{entry.timestamp} [{entry.level}] {entry.message}")
# Filter to warnings and above, limited to 50 entries
warnings = await admins.tail_logs(level="WARNING", limit=50)
Each ServerLogEntry field is nullable. When a log line is not valid JSON, the original line is available on entry.raw.
Download Server Logs
Download a zip archive containing the active log file and any rotated backups.
from pathlib import Path
archive = await admins.download_logs()
Path(archive.filename).write_bytes(archive.content)
The filename comes from the server's Content-Disposition header (for example, vapi-logs-20260525T120000Z.zip), and content holds the raw zip bytes.
List Developers
Retrieve all developer accounts with optional filtering.
# Get all developers
all_devs = await admins.list_all_developers()
# Filter by global admin status
admin_devs = await admins.list_all_developers(is_global_admin=True)
# Paginated access
page = await admins.get_developer_page(limit=25, offset=0)
print(f"Total developers: {page.total}")
Iterate Through Developers
Use memory-efficient iteration for large developer lists.
async for developer in admins.iter_all_developers():
print(f"{developer.username} - {developer.email}")
Create a User in a Company
Create a user account inside a specific company using the global-admin service.
from vclient.models import AdminUserCreate
# Option 1: Use a model object (preferred)
request = AdminUserCreate(
company_id="company-456",
username="newplayer",
email="player@example.com",
role="PLAYER",
name_first="Jane",
name_last="Doe",
)
user = await admins.create_user(request)
# Option 2: Pass fields as keyword arguments
user = await admins.create_user(
company_id="company-456",
username="newplayer",
email="player@example.com",
role="PLAYER",
)
Update a User
Modify a user account's properties. Only include fields that need to change.
from vclient.models import AdminUserUpdate
update = AdminUserUpdate(email="new@example.com", role="STORYTELLER")
updated = await admins.update_user(user.id, update)
Soft-Delete and Restore a User
Delete is reversible. Archived users are still returned by the user pagination methods when queried by a global-admin.
# Soft-delete a user
await admins.delete_user(user.id)
# Restore by clearing the archived flag
restored = await admins.update_user(user.id, is_archived=False)
List and Filter Users
Retrieve users across all companies with optional filters.
# Get all users across all companies
all_users = await admins.list_all_users()
# Filter to a single company
company_users = await admins.list_all_users(company_id="company-456")
# Find archived users only
archived = await admins.list_all_users(is_archived=True)
# Paginated access with role filter
page = await admins.get_user_page(role="ADMIN", limit=25)
print(f"Total admins: {page.total}")
Iterate Through Users
Use memory-efficient iteration for large user lists.
async for user in admins.iter_all_users(company_id="company-456"):
print(f"{user.username} - {user.email} (archived={user.is_archived})")
Related Documentation
- Response Models - View
Developer,DeveloperWithApiKey,ServerLogEntry, andServerLogArchivemodel schemas - User Models - View
AdminUser,AdminUserCreate, andAdminUserUpdatemodel schemas