Documentation Index
Fetch the complete documentation index at: https://docs.nusomi.com/llms.txt
Use this file to discover all available pages before exploring further.
Targets Python 3.10+. Sync and async clients ship in the same package.
Client
from nusomi import Nusomi
nusomi = Nusomi(
api_key=os.environ["NUSOMI_API_KEY"],
base_url="https://api.nusomi.com", # override for self-hosted
timeout=30.0,
max_retries=3,
)
For asyncio:
from nusomi import AsyncNusomi
async with AsyncNusomi(api_key=...) as nusomi:
session = await nusomi.sessions.create(workflow="...")
...
Resources
nusomi.sessions
nusomi.events
nusomi.frames
nusomi.replay
nusomi.recovery
nusomi.memory
nusomi.exports
nusomi.workflows
nusomi.webhooks
Sessions
nusomi.sessions.create(workflow, metadata=None, actor=None) -> Session
nusomi.sessions.get(id) -> Session
nusomi.sessions.list(**filters) -> Iterator[Session]
nusomi.sessions.start(id) -> Session
nusomi.sessions.stop(id) -> Session
nusomi.sessions.tag(id, name, **data) -> None
nusomi.sessions.delete(id) -> None
A Session is also a context manager:
with nusomi.sessions.create(workflow="...") as session:
# session.start() called on enter, session.stop() on exit
do_work()
Events
nusomi.events.query(session_id, **filters) -> list[Event]
nusomi.events.stream(session_id, **opts) -> Iterator[Event]
nusomi.events.emit(session_id, type, **payload) -> None
Frames
nusomi.frames.get(frame_id) -> Frame
nusomi.frames.image(frame_id) -> bytes
nusomi.frames.list(session_id, **filters) -> Iterator[Frame]
Replay
nusomi.replay.exact(session_id, **opts) -> Replay
nusomi.replay.guided(session_id, **opts) -> Replay
nusomi.replay.partial(session_id, from_frame=..., **opts) -> Replay
Recovery
nusomi.recovery.from_session(session_id, **opts) -> Replay
Memory
nusomi.memory.paths(**filters) -> list[Path]
nusomi.memory.outliers(**filters) -> list[Session]
nusomi.memory.similar(session_id, limit=10) -> list[Session]
nusomi.memory.recovery_points(**filters) -> list[Frame]
nusomi.memory.on_drift(workflow, handler) -> Subscription
Exports
nusomi.exports.create(workflow, filter=None, format="parquet", destination=None) -> Export
nusomi.exports.get(id) -> Export
nusomi.exports.list(**filters) -> Iterator[Export]
Webhooks
nusomi.webhooks.list() -> list[Webhook]
nusomi.webhooks.create(**input) -> Webhook
nusomi.webhooks.delete(id) -> None
list(...) returns an iterator that pages under the hood:
for s in nusomi.sessions.list(workflow="process_invoice", since="30d"):
print(s.id, s.duration_ms)
Default page size is 100. Override with page_size=....
Errors
from nusomi import NusomiError
try:
nusomi.sessions.create(workflow="...")
except NusomiError as e:
print(e.code, e.message, e.request_id)
if e.code == "rate_limited":
time.sleep(e.retry_after_ms / 1000)
See errors for the full code table.
Streaming
for ev in nusomi.events.stream(
session_id,
types=["click", "validation_error"],
):
print(ev.t_ms, ev.type, ev.payload)
The stream auto-reconnects on transient failure. Stop with stream.close() or by breaking out of the loop.
Async streaming
async with AsyncNusomi(api_key=...) as nusomi:
async for ev in nusomi.events.stream(session_id):
print(ev)
Type hints
All models are pydantic v2 dataclasses. Use them in your own type annotations:
from nusomi.types import Session, Event, Frame, ClickEvent
Event payloads are tagged unions:
match ev.type:
case "click":
print(ev.payload.x, ev.payload.y)
case "validation_error":
print(ev.payload.field, ev.payload.message)
Playwright integration
from playwright.sync_api import sync_playwright
from nusomi import Nusomi
nusomi = Nusomi(api_key=...)
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
with nusomi.sessions.create(workflow="login_test") as session:
session.attach_playwright(context)
page = context.new_page()
page.goto("https://app.example.com/login")
...
browser.close()
Logging
Bind to standard logging:
import logging
logging.getLogger("nusomi").setLevel(logging.DEBUG)