Base endpoint
https://win9-5.com
All REST endpoints return JSON.
BrowserBox exposes two integration layers: REST endpoints for session lifecycle and the <browserbox-webview> element for in-session control. This page documents both using current method and event names from the canonical implementation.
https://win9-5.com
All REST endpoints return JSON.
Send Authorization: Bearer <api_key> on protected endpoints.
Set login-link on <browserbox-webview> (not src).
POST /api/v1/sessions and store loginUrl.<browserbox-webview login-link="..."> in your application UI.whenReady(), then use tab/navigation/automation methods.const session = await fetch('https://win9-5.com/api/v1/sessions', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ minutes: 15 })
}).then((r) => r.json());
const bbx = document.querySelector('browserbox-webview');
bbx.setAttribute('login-link', session.loginUrl);
await bbx.whenReady();
Include your API key with each protected request:
curl -H "Authorization: Bearer bbx_your_api_key_here" \
https://win9-5.com/api/v1/balance
bbx_.Create an isolated browser session and deduct allocated minutes.
| Field | Type | Required | Description |
|---|---|---|---|
minutes | number | No | Defaults to 15, max 120. |
curl -X POST https://win9-5.com/api/v1/sessions \
-H "Authorization: Bearer bbx_abc123..." \
-H "Content-Type: application/json" \
-d '{"minutes":15}'
{
"sessionId": "cc57975684b942fc...",
"loginUrl": "https://bbx-instance.run.app/login?token=...",
"region": "us-central1",
"serviceName": "bbx-abc123",
"minutes_allocated": 15,
"balance_minutes": 285,
"expires_at": 1770612214916
}
Retrieve active-session state, remaining time, and account-scoped metadata.
curl https://win9-5.com/api/v1/sessions/cc57975684b942fc... \
-H "Authorization: Bearer bbx_abc123..."
{
"sessionId": "cc57975684b942fc...",
"loginUrl": "https://bbx-instance.run.app/login?token=...",
"region": "us-central1",
"serviceName": "bbx-abc123",
"created_at": 1770611914916,
"expires_at": 1770612214916,
"remaining_ms": 297663,
"minutes_allocated": 15,
"minutes_elapsed": 2,
"deleted": false
}
End a session and return unused minutes to your account balance.
curl -X DELETE https://win9-5.com/api/v1/sessions/cc57975684b942fc... \
-H "Authorization: Bearer bbx_abc123..."
{
"ok": true,
"minutes_used": 3,
"minutes_refunded": 27,
"balance_minutes": 297
}
Return current minute balance and account metadata.
curl https://win9-5.com/api/v1/balance \
-H "Authorization: Bearer bbx_abc123..."
List minute packs and defaults. No authentication required.
curl https://win9-5.com/api/v1/pricing
Create a Stripe Checkout URL for minute-pack purchases. No API key required.
| Field | Type | Required | Description |
|---|---|---|---|
product | string | Yes | minutes_60, minutes_300, minutes_1000, subscription |
email | string | No | Prefill customer email in checkout. |
curl -X POST https://win9-5.com/api/v1/checkout \
-H "Content-Type: application/json" \
-d '{"product":"minutes_300","email":"[email protected]"}'
Cookie-authenticated endpoints for the hosted demo. No API key required — sessions are tracked via a bbx_session cookie.
Create a demo browser session. If an active session already exists for the cookie, it is returned instead. Sessions last up to 15 minutes.
curl -X POST https://win9-5.com/api/session \
-H "Content-Type: application/json" \
--cookie "bbx_session=..."
{
"sessionId": "cc57975684b942fc...",
"loginUrl": "https://bbx-instance.fly.dev/login?token=...",
"region": "iad",
"minutes_allocated": 15,
"expires_at": 1770612214916
}
Lightweight session liveness check. Returns whether the cookie holder has an active session. Useful for resuming UI state after a page reload or browser reopen.
curl https://win9-5.com/api/session/status \
--cookie "bbx_session=..."
{
"active": true,
"sessionId": "cc57975684b942fc...",
"loginUrl": "https://bbx-instance.fly.dev/login?token=...",
"region": "iad",
"minutes_allocated": 15,
"expires_at": 1770612214916
}
{ "active": false }
Signal that the client is leaving. Supports defer (mark disconnected, allow grace-period reconnect) or hard (immediate teardown).
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | No | defer (default) or hard. |
sessionId | string | No | Target a specific session. Omit to affect all sessions for this cookie. |
curl -X POST https://win9-5.com/api/session/disconnect \
-H "Content-Type: application/json" \
--cookie "bbx_session=..." \
-d '{"mode":"defer"}'
{ "ok": true, "mode": "defer", "ended": 0, "marked": 1 }
Errors return JSON with an error field and may include extra context keys.
{ "error": "Insufficient minutes", "balance_minutes": 0, "requested_minutes": 15 }
| Status | Meaning |
|---|---|
400 | Missing or invalid parameters. |
401 | Missing or malformed auth header. |
402 | Insufficient minutes. |
403 | Invalid API key. |
404 | Session not found for that key. |
503 | Billing subsystem unavailable. |
<browserbox-webview>Load the canonical component script and set login-link to the loginUrl returned by POST /api/v1/sessions.
<script src="proxy.php?url=https://win9-5.com/browserbox-webview.js" type="module"></script>
<browserbox-webview
login-link="https://bbx-instance.run.app/login?token=..."
width="100%"
height="600"
request-timeout-ms="30000"
></browserbox-webview>
<script>
const bbx = document.querySelector('browserbox-webview');
await bbx.whenReady();
await bbx.navigateTo('https://example.com');
</script>
| Attribute | Type | Default | Description |
|---|---|---|---|
login-link | string | none | Required login URL with session token. |
width | string/number | 100% | Component width. Bare numbers are interpreted as px. |
height | string/number | 100% | Component height. Bare numbers are interpreted as px. |
parent-origin | string | * | Origin check for postMessage input validation. |
request-timeout-ms | number | 30000 | Per-call timeout floor is 100ms. |
ui-visible | boolean | true | Show or hide BrowserBox chrome UI. |
allow-user-toggle-ui | boolean | true | Allow end user to toggle UI visibility. |
chrome | string | default | Chrome presentation hint: none, minimal, default, custom. |
augment-root | string | open | Augment inspectability hint: open or closed. |
capture | string | snapshot | Capture policy hint: off, snapshot, sampled. |
| Property | Maps to | Notes |
|---|---|---|
loginLink | login-link | Set/remove source URL. |
routingMid | derived | Read-only resolved routing machine id. |
width | width | String values preserved. |
height | height | String values preserved. |
parentOrigin | parent-origin | Defaults to wildcard. |
requestTimeoutMs | request-timeout-ms | Parsed as integer. |
| Event | Detail payload | Description |
|---|---|---|
ready | { type } | Legacy handshake completed. |
api-ready | { methods: string[], policy?: PolicySnapshot } | Modern API handshake completed and may include the current server policy snapshot. |
ready-timeout | { timeoutMs, error } | Soft timeout while awaiting readiness. |
disconnected | {} | Session disconnected or source changed. |
iframe-retry | { attempt, maxAttempts, delayMs } | Automatic iframe reload retry in progress. |
mid-synced | { mid, attempts } | Routing-mid synchronization succeeded. |
mid-sync-timeout | { attempts, mid } | Routing-mid synchronization timed out. |
usability-changed | { usable, reason } | Browser usability state changed. |
| Event | Detail payload (typical) | Description |
|---|---|---|
tab-created | { index, id, url } | Tab creation observed. |
tab-closed | { index, id } | Tab close observed. |
tab-updated | { id, url, title, faviconDataURI } | Tab metadata changed. |
active-tab-changed | { index, id } | Active tab changed. |
did-start-loading | { tabId, url } | Navigation started loading. |
did-stop-loading | { tabId, url } | Navigation stopped loading. |
did-navigate | { tabId, url } | Navigation committed. |
policy-denied | { url, reason } | Policy blocked requested action. |
policy.changed | { reason, policy, capabilities } | Effective policy and capability set changed. |
favicon-changed | { ... } | Favicon metadata updated. |
sos | { reasonCode, message, retryUrl } | Fatal unusable signal from embedded BrowserBox. |
| Method | Description |
|---|---|
whenReady({ timeoutMs }) | Wait for handshake readiness. |
listApiMethods(options?) | Return available remote methods. |
callApi(method, ...args) | Generic method dispatcher. |
refresh() | Hard reload iframe and reset transport state. |
updateIframe() | Recompute routing MID, apply login-link, and re-apply dimensions. |
stopReconnectAttempts(reason?) | Stop retry loop and reject pending calls. |
| Method | Description |
|---|---|
getTabs(), getTabCount(), getActiveTabIndex() | Tab inspection helpers. |
createTab(url?), createTabs(count, opts?) | Create one or many tabs. |
closeTab(index?), closeTabById(targetId), closeAllTabs(opts?) | Close tab(s) by index or target id. |
switchToTab(index), switchToTabById(targetId) | Switch active tab. |
navigateTo(url, opts?), navigateTab(index, url, opts?) | Navigate active or selected tab. |
submitOmnibox(query, opts?) | Submit URL or search query. |
reload(), goBack(), goForward(), stop() | Standard browser navigation controls. |
| Method | Description |
|---|---|
waitForTabCount(count, opts?), waitForTabUrl(index, opts?) | Polling helpers for tab convergence and URL matching. |
getFavicons(), waitForNonDefaultFavicon(index, opts?) | Favicon metadata helpers. |
getScreenMetrics(), getTransportDiagnostics() | Viewport/transport diagnostics. |
health({ timeoutMs }?) | Return a structured health report with readiness, transport, latency, and last-error diagnostics. |
| Method | Description |
|---|---|
click(selector, opts?) | Click an element by CSS selector. Waits for the selector first by default. |
type(selector, text, opts?) | Type text into a matched element. Waits for the selector first. |
evaluate(expression, opts?) | Evaluate a JavaScript expression in the active tab and return the result. |
waitForSelector(selector, opts?) | Wait for a CSS selector to appear in the DOM (polls with exponential backoff). |
waitForNavigation(opts?) | Wait for the current navigation to complete. |
| Method | Description |
|---|---|
act({ navigate: url }) | Navigate the active tab. |
act({ click: { selector, ...opts } }) | Click an element by CSS selector. |
act({ type: { selector, text, ...opts } }) | Type text into a matched element. |
act({ evaluate: expression }) | Evaluate a JavaScript expression in the page. |
act({ waitForSelector: { selector, ...opts } }) | Wait for a CSS selector to appear. |
act({ waitForNavigation: opts }) | Wait for navigation to complete. Returns { ok, action, value }. |
| Method | Description |
|---|---|
uiVisible(visible?) | Show or hide the BrowserBox chrome UI. Returns current visibility state. |
allowUserToggleUI(allow?) | Allow or deny the user from toggling UI visibility. |
The element exposes a namespaced session-host API alongside the classic flat methods. Access via bbx.session, bbx.tabs, etc.
| Property / Method | Description |
|---|---|
session.id | Read-only routing machine id. |
session.usable | Read-only browser usability flag. |
session.transport | Read-only transport mode (modern, legacy, unknown). |
session.ready | Read-only readiness flag. |
session.health() | Return { ok, usable, ready, transport, sessionId, timestamp, latencyMs, diagnostics }. |
session.refresh() | Hard reload and reset transport. |
session.disconnect() | Explicit session teardown. |
session.capabilities() | Return current effective capabilities map. |
| Method | Description |
|---|---|
tabs.list() | Return all tabs with normalized metadata. |
tabs.getActive() | Return the active tab info. |
tabs.create({ url, active }) | Create a tab, optionally without activating it. |
tabs.activate(tabId) | Switch to tab by id. |
tabs.close(tabId) | Close tab by id. |
tabs.closeAll() | Close all tabs. |
| Method | Description |
|---|---|
page.navigate(url) | Navigate the active tab. |
page.reload(), page.back(), page.forward(), page.stop() | Standard navigation controls. |
page.url(), page.title(), page.favicon() | Active-tab metadata. |
page.metrics() | Normalized viewport/document metrics. |
page.text({ mainContentOnly }) | Extract visible page text. |
| Method | Description |
|---|---|
capture.frame({ format, quality }) | Capture the current rendered frame as a data URL. |
capture.viewport({ format, quality }) | Capture the viewport as a data URL. |
| Method | Description |
|---|---|
augment(spec) | Create an overlay (sidebar, toolbar, toast, highlight, custom). Typed content is preferred: { type: 'text'|'html'|'json', ... }. Returns a handle with update() and remove(). |
augment.update(id, patch) | Update an existing augment. |
augment.remove(id) | Remove an augment. |
augment.list() | List all active augments. |
| Method | Description |
|---|---|
select({ prompt, intent }) | Enter interactive pick mode. getRaw() returns { selector, selectors, text, href, htmlSnippet }; generalized previews/extracts return normalized selector results. |
| Method | Description |
|---|---|
policy.get() | Return the merged effective policy snapshot. Server policy is authoritative; embedder attributes can only further restrict it. |
| Method | Description |
|---|---|
on(eventName, handler) | Subscribe to events. Returns an unsubscribe function. |
off(eventName, handler) | Unsubscribe from events. |
observe(config) | Create a structured observer with filter config. Returns { id, config, on, off, unsubscribe }. |
events(config) | Async iterator yielding { id, type, timestamp, sessionId, tabId?, detail }. |
Legacy event names continue to work. New canonical dot-notation names are also emitted:
| Legacy name | Canonical alias |
|---|---|
api-ready | api.ready |
tab-created | tab.created |
tab-closed | tab.closed |
tab-updated | tab.updated |
active-tab-changed | tab.activated |
did-navigate | page.navigated |
did-start-loading | page.load.started |
did-stop-loading | page.load.stopped |
policy-denied | policy.denied |
policy.changed | policy.changed |
usability-changed | session.usability.changed |
disconnected | session.disconnected |
The component probes modern RPC first (bbx-api-call). If unavailable, it falls back to legacy message types and emulates compatibility for core tab/navigation operations. Use session.capabilities() or listApiMethods() for capability-based branching.
Advanced surfaces (augment, capture, select) are capability-gated and disabled by default. Enable them by setting the corresponding policy attributes or using interaction-mode presets.
Server policy is pushed over the existing BrowserBox runtime/meta path into the iframe, included in the initial bbx-api-ready handshake, and forwarded mid-session as bbx-policy-sync. The webview merges that authoritative snapshot with local attribute policy and emits policy.changed when capabilities change.
Public API failures use stable BrowserBoxError codes: ERR_NOT_READY, ERR_POLICY_DENIED, ERR_TIMEOUT, ERR_TRANSPORT, ERR_UNSUPPORTED, ERR_INVALID_ARGUMENT, ERR_NOT_FOUND, ERR_CONFLICT, and ERR_INTERNAL. Errors may also include status and retriable.
55/55 tests passing (2026-03-09) across session, tabs, page, navigation, automation (click, waitForSelector, evaluate, act), capture, diagnostics, policy, augment, events, and observer APIs.