Documentation
OMNISIM Synthetic Users runs persona-driven journeys against your staging API, web app, or both. Register a product once, start runs from Python or REST, and receive friction clusters plus per-agent UX narratives and an observer report.
omnisim v0.2 (pip install omnisim). TypeScript @omnisim/sdk mirrors the same /api/v1 surface. All routes require X-API-Key.New here? Quickstart → Products → Web & hybrid → Runs.
Quickstart
Install the SDK, set your key, register a product, and start a run.
pip install omnisim
export OMNISIM_API_KEY="omni_sk_your_key"
export OMNISIM_BASE_URL="https://api.omnisim.io" # optional; defaults to http://localhost:8000import os
from omnisim import Omnisim
client = Omnisim(api_key=os.environ["OMNISIM_API_KEY"], base_url=os.environ.get("OMNISIM_BASE_URL", "https://api.omnisim.io"))
product = client.products.register(
name="Acme Staging API",
base_url="https://staging.api.acme.dev",
openapi=open_api_dict,
auth={"type": "bearer", "token": os.environ["STAGING_TOKEN"]},
)
run = client.synthetic_users.run(
product_id=product["id"],
personas=50,
rounds=3,
scenarios=["signup"],
mode="behavioral_only",
)
result = run.wait_for_complete()
print(result.get("friction_points"), result.get("recommendations"))API keys: dashboard. Web apps: see Web & hybrid.
Authentication
Every v1 request must include your API key:
X-API-Key: omni_sk_xxxxxxxxKeys are tied to a tier (Free, Pro, Pro+). Limits apply to personas per run, daily API calls, registered products, and webhooks. Invalid or missing keys return 401.
Your tier also selects the agent capability level and browser screen reads (see Credits & tiers). Final observer reports are generated by a hosted report model on all tiers.
Products (API)
A product is your staging surface: base_url, optional OpenAPI spec, and encrypted credentials for the proxy.
POST/api/v1/products
{
"name": "Acme Staging API",
"base_url": "https://staging.api.acme.dev",
"interaction_mode": "api",
"openapi": { },
"auth": { "type": "bearer", "token": "staging-token" },
"redact_fields": ["password", "ssn"]
}auth.type: none, bearer, api_key, basic. Staging URLs only — production hostnames are rejected.
GET /api/v1/products
GET /api/v1/products/{product_id}
DELETE /api/v1/products/{product_id}
Web & hybrid products
Register a staging web app with interaction_mode: "web" — no OpenAPI required. Use "hybrid" for Playwright UI plus real HTTP from OpenAPI.
product = client.products.register(
name="My SaaS staging",
base_url="http://127.0.0.1:3000",
app_url="http://127.0.0.1:3000",
interaction_mode="web",
user_flows={
"signup": [
{"action": "goto", "path": "/"},
{"action": "read_screen", "scope": "page"},
{"action": "click", "selector": "#signup", "label": "Sign up"},
],
"_config": {
"journey_mode": "exploratory",
"repo_path": "/path/to/my-app",
"staging_command": "npm run dev",
"browser_harness_url": "http://127.0.0.1:9333",
},
},
)
# Hybrid: API + browser
product = client.products.register_hybrid(
name="Acme full stack",
base_url="https://staging.api.acme.dev",
app_url="https://staging.app.acme.dev",
openapi=open_api_dict,
user_flows={"...": []},
auth={"type": "bearer", "token": "..."},
)Flow actions: goto, click, fill, wait_for, read_screen (accessibility tree — not screenshot OCR), read_text, screenshot (visual proof).
Pro / Pro+ add enhanced DOM on read_screen (bounding boxes + key computed styles). Free uses ARIA snapshots only.
Localhost products can auto-start via user_flows._config (staging_command, repo_path, health_path). Server needs playwright install chromium and browser requirements installed.
POST /api/v1/products/{product_id}/browser-session
Attach Playwright storage_state (cookies) for authenticated UI runs — client.products.attach_browser_session(product_id, storage_state).
Synthetic runs
Starts an async run: LLM agents exercise your product, then friction analysis and an observer report are generated. Poll or use webhooks (Pro+).
POST /api/v1/products/{product_id}/runs
{
"personas": 50,
"agents": 50,
"rounds": 3,
"focus": "general",
"scenarios": ["signup", "checkout"],
"mode": "behavioral_only"
}agents is an alias for personas. mode must be behavioral_only (behavioral accepted as legacy alias). Response 202 with run_id, poll_url, and often watch_url for live HTML.
GET /api/v1/runs/{run_id}
GET /api/v1/runs/{run_id}/traces
GET /api/v1/runs/{run_id}/report.html
GET /api/v1/runs/{run_id}/watch
Usage
Rate/limit usage for your key — not dollar credit balance (see dashboard wallet).
GET /api/v1/usage
summary = client.usage.get()
# daily_calls, daily_limit, tier, total_tokens, ...Webhooks
Pro and Pro+ can register HTTPS endpoints for run completion.
POST /api/v1/webhooks
GET /api/v1/webhooks
DELETE /api/v1/webhooks/{webhook_id}
HMAC-SHA256 (v0.2+):
X-OMNISIM-Timestamp: 1716566400
X-OMNISIM-Signature: v1=<base64_hmac>Signed payload: {timestamp}.{raw_json_body}
from omnisim import verify_webhook
body = await request.body()
if not verify_webhook(body, request.headers, webhook_secret):
raise HTTPException(401, "invalid signature")Full guide: docs/synthetic-users-sdk.md
Environment variables
| Variable | Required | Description |
|---|---|---|
OMNISIM_API_KEY | Yes | Dashboard API key (omni_sk_...) |
OMNISIM_BASE_URL | No | API base (default http://localhost:8000) |
OMNISIM_TIMEOUT | No | HTTP timeout seconds (default 120) |
OMNISIM_REQUIRE_HTTPS | No | Set 1 to reject non-HTTPS remote URLs |
Server-side (self-hosted API): GROQ_API_KEY for Free agent calls; MOONSHOT_API_KEY for Pro/Pro+ agents; ANTHROPIC_API_KEY for observer reports and UX narratives.
Python SDK
Package omnisim v0.2 — Omnisim.from_env() or explicit api_key / base_url. Namespaces: products, synthetic_users, usage, webhooks.
from omnisim import Omnisim, RunMode
client = Omnisim.from_env()
run = client.synthetic_users.run(
product_id=product_id,
agents=100,
scenarios=["explore"],
mode=RunMode.BEHAVIORAL_ONLY,
)
result = run.wait_for_complete(timeout=600, interval_ms=5000)
traces = run.get_traces()wait_for_complete() uses exponential backoff (min interval_ms, cap 15s). Retries 429, 502, 503, 504 up to 3 times.
Typed errors: OmnisimValidationError, OmnisimAuthError, OmnisimNotFoundError, OmnisimRateLimitError.
TypeScript SDK
npm install @omnisim/sdkimport { Omnisim, verifyWebhook } from "@omnisim/sdk";
const client = Omnisim.fromEnv();
const usage = await client.usage.get();Python is canonical for production; TypeScript mirrors REST + webhook verify.
Reports & CLI
After completion, each agent can include a first-person UX narrative in the result.
result = run.wait_for_complete()
run.print_report(verbose=True)
run.open_visual_report() # GET .../report.html
# Fields on result / observer_report:
# agent_ux_reports[], journey_results, friction_pointsTerminal watch while running:
def on_agent(agent: dict) -> None:
print(agent["agent_id"], agent.get("task_label"))
run = client.synthetic_users.run(product_id=pid, agents=10, scenarios=["signup"])
result = run.wait_for_complete(on_agent=on_agent, interval_ms=2000)CLI (from OMNISIM repo):
pip install -e "packages/sdk-python[cli]"
omnisim-run run --agents 10 --scenarios explore --verboseAgent evals (internal QA)
Evaluate synthetic agent behavior quality and narrative trustworthiness via the --evals flag. Intended for internal testing of the simulation engine, not your product.
# Install DeepEval in backend venv first
pip install -r backend/requirements-eval.txt
# Run with evals (adds ~2-5s per agent)
omnisim-run run --product-id prod_xxx --agents 5 --evals
# Or with test-product
omnisim-run test-product --product-id prod_xxx --scenarios explore --evals
# JSON output for automation
omnisim-run run --product-id prod_xxx --agents 5 --evals --json | jq '.agent_evals'Requires ANTHROPIC_API_KEY in backend env for LLM-judge metrics. Without it, only deterministic metrics run.
See docs/agent-evals.md for full documentation.
Credits & tiers
| Tier | Price | Credits / mo | Max personas | Products | Agent tier | Screen reads |
|---|---|---|---|---|---|---|
| Free | $0 | $20 | 5 | 1 | Standard | ARIA |
| Pro | $30 | $30 | 40 | 5 | Advanced | Enhanced DOM |
| Pro+ | $60 | $60 | 80 | 20 | Advanced | Enhanced DOM |
1 credit = $1. Synthetic runs use behavioral billing: ~$0.05/persona per run (min $1). Max rounds per run: Free 1, Pro 3, Pro+ 4. Daily API call caps vary by tier — see pricing and GET /api/v1/usage.
Errors & limits
400— validation or tier limits (personas, products, staging URL rules)401— invalid API key404— product or run not found429— rate limit (SDK retries with backoff)
OpenAPI explorer: https://api.omnisim.io/docs