OptixLog Docs
Concepts

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_at

There 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 — the TeamCollection.
  • project.workflow_nodes — the WorkflowNodeCollection.
  • project.audit_events — the AuditEventCollection.
  • 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    # TeamMembershipCollection

Team filters

FilterTypeMeaning
namestrPartial or exact name match.
categorystrExact 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.

On this page