Projects, Organizations, and Teams
The entity hierarchy — organization → project → teams and members — and how you access each through the Management API.
Entity hierarchy
Organization
└── Project (one or more)
├── Team (one or more)
│ └── TeamMembership (user + role)
└── ProjectMember (deduped view across all teams)Every API key is scoped to one organization. All projects, teams, and members belong to that organization.
Organization
You access the organization through a project:
org = project.organization.get()
org.id
org.name
org.description
org.logo_url
org.company_size
org.industry
org.website
org.contact_name
org.contact_email
org.contact_phone
org.created_at
org.updated_atThere is one organization per key. project.organization.get() always returns the same organization regardless of which project you call it on.
Projects
Projects are the unit of schema ownership and team structure. You access a project through Management:
from optixlog.management import Management
management = Management(client)
# By id:
project = management.project("proj_grating_7f3a")
# From a ProjectRef (e.g. from client.project(...)):
project = management.project_from(project_ref)ManagementProject exposes:
project.config— project name, description, category, status, and timestamps.project.organization— the parent organization.project.teams— theTeamCollection.project.workflow_nodes— theWorkflowNodeCollection.project.audit_events— theAuditEventCollection.project.get_all_members(...)— deduplicated member list across all teams.project.snapshot(...)— fetch multiple resources in one call.
Teams
Teams group members within a project. You list, filter, and look up teams through project.teams:
# List with filters (AND logic):
page = project.teams.list(
name="Photonics",
category="engineering",
include=["counts"],
limit=50,
order_by="name",
order="asc",
)
# Strict lookup — raises NotFoundError if missing:
team = project.teams.get("team-id", include=["counts"])
# Nullable lookup:
team = project.teams.get_or_none("team-id")
# Iterate all pages:
for team in project.teams.iter(category="engineering"):
print(team.id, team.name)Team fields:
team.id
team.name
team.icon
team.description
team.category
team.notes
team.created_at
team.updated_at
team.member_count # int | None — populated when include=["counts"]
team.memberships # TeamMembershipCollectionTeam filters
| Filter | Type | Meaning |
|---|---|---|
name | str | Partial or exact name match. |
category | str | Exact category match. |
Team includes
Pass include=["counts"] to populate team.member_count.
Team memberships
A TeamMembership is the edge between a User and a Team within a project, with a role and a join timestamp.
# From a team:
memberships_page = team.memberships.list(
role="Engineer",
include=["user", "team"],
order_by="joined_at",
order="desc",
)
# By user id (note: get takes user_id= as a keyword):
membership = team.memberships.get(user_id="user-id", include=["user"])
membership.user_ref # EntityRef(type, id, name)
membership.team_ref # EntityRef(type, id, name)
membership.role
membership.joined_at
membership.user # User | None — populated when include=["user"]
membership.team # Team | None — populated when include=["team"]Project members
project.get_all_members(...) returns a deduplicated list of every user who belongs to any team in the project:
page = project.get_all_members(
include_memberships=True,
limit=100,
order_by="name",
order="asc",
)
for member in page.items:
print(member.user_ref.id, member.user_ref.name)
if member.memberships:
for m in member.memberships:
print(" team:", m.team_ref.name, "role:", m.role)Set include_memberships=False for a lighter response when you only need user IDs or names.