OptixLog Docs
Concepts

Pagination, Filtering, and Includes

How Page[T] works, how iter() walks all pages, AND filter semantics, include= for related data, and ordering with order_by and cursor.

Every collection in the Management API follows the same pagination, filtering, and includes contract. Learning it once applies to teams, memberships, workflow nodes, node labels, and audit events.

Page[T] — the paginated result

All list(...) methods return a Page[T]:

@dataclass(frozen=True)
class Page(Generic[T]):
    items: list[T]          # the items in this page
    next_cursor: str | None # cursor to fetch the next page; None if no more pages
    total: int | None       # total count, if available; may be None

Example:

page = project.teams.list(limit=50)

for team in page.items:
    print(team.id)

if page.next_cursor:
    next_page = project.teams.list(limit=50, cursor=page.next_cursor)

iter() — walk all pages automatically

Use iter(...) to transparently walk all pages without managing cursors:

for team in project.teams.iter(category="engineering"):
    print(team.id, team.name)

iter() accepts the same filter kwargs as list() but not limit or cursor. It fetches pages lazily as you consume the iterator.

Filters — AND semantics

Filters are conjunctive: all supplied filter kwargs must match. An item is returned only if it satisfies every condition.

# Matches teams where name contains "Photonics" AND category == "engineering":
page = project.teams.list(name="Photonics", category="engineering")

# Matches workflow nodes where label == "SimulationRun" AND solver property == "fdtd":
page = project.workflow_nodes.list(
    label="SimulationRun",
    has_property={"solver": "fdtd"},
)

Omitting a filter means "no constraint on that field".

Filter kwargs per collection

Teams:

FilterTypeMeaning
namestrTeam name match.
categorystrTeam category match.

Team memberships:

FilterTypeMeaning
user_idstrFilter by user.
rolestrFilter by role.

Workflow nodes:

FilterTypeMeaning
labelstrNode label name.
created_bystrUser ID of creator.
has_propertydict[str, str]One or more property key=value pairs (AND).

Audit events:

FilterTypeMeaning
actionstrEvent action string.
categorystrEvent category.
levelstrSeverity level: debug, info, warn, error.
actor_idstrUser ID of the actor.
target_typestrTarget entity type: organization, project, team, user, workflow_node, file, invitation, permission_group.
request_idstrRequest correlation ID.
sincedatetimeEvents at or after this timestamp.
untildatetimeEvents at or before this timestamp.

By default, related objects are not fetched — their fields are None. Pass include= to request them:

# Fetch workflow node with all related data:
node = project.workflow_nodes.get(
    "node-id",
    include=["label", "properties", "attachments", "parents", "children"],
)

# Fetch team membership with user and team populated:
membership = team.memberships.get(
    user_id="user-id",
    include=["user", "team"],
)

# Fetch team with member count:
team = project.teams.get("team-id", include=["counts"])

Include options by collection:

CollectionAvailable includes
Teams"counts"
Team memberships"user", "team"
Workflow nodes"label", "properties", "attachments", "parents", "children"

Ordering

All list() and iter() calls accept order_by and order:

page = project.workflow_nodes.list(
    order_by="created_at",
    order="desc",   # "asc" | "desc"
)

order_by options per collection

Collectionorder_by optionsDefault
Teamsname, created_at, updated_at, category—
Team membershipsjoined_at, role, user_name—
Workflow nodescreated_at, updated_at, display_name, labelcreated_at desc
Node labelsname, id—
Audit eventstimestamp, action, leveltimestamp desc

Cursor-based pagination

Cursors are opaque strings. Pass next_cursor from one page as cursor= on the next:

cursor = None
while True:
    page = project.workflow_nodes.list(label="SimulationRun", cursor=cursor, limit=100)
    for node in page.items:
        process(node)
    if page.next_cursor is None:
        break
    cursor = page.next_cursor

Prefer iter() over manual cursor management for simple iteration.

On this page