BrowserBox Platform Reference

REST API and embed reference

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.

Base endpoint

https://win9-5.com

All REST endpoints return JSON.

Authentication

Send Authorization: Bearer <api_key> on protected endpoints.

Embed contract

Set login-link on <browserbox-webview> (not src).

Quickstart

  1. Create a session with POST /api/v1/sessions and store loginUrl.
  2. Render <browserbox-webview login-link="..."> in your application UI.
  3. Await 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();

Authentication

Include your API key with each protected request:

curl -H "Authorization: Bearer bbx_your_api_key_here" \ https://win9-5.com/api/v1/balance

REST Endpoints

POST /api/v1/sessions

Create an isolated browser session and deduct allocated minutes.

Request body

FieldTypeRequiredDescription
minutesnumberNoDefaults to 15, max 120.

Example

curl -X POST https://win9-5.com/api/v1/sessions \ -H "Authorization: Bearer bbx_abc123..." \ -H "Content-Type: application/json" \ -d '{"minutes":15}'

Response (201)

{ "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 }
GET /api/v1/sessions/:id

Retrieve active-session state, remaining time, and account-scoped metadata.

Example

curl https://win9-5.com/api/v1/sessions/cc57975684b942fc... \ -H "Authorization: Bearer bbx_abc123..."

Response (200)

{ "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 }
DELETE /api/v1/sessions/:id

End a session and return unused minutes to your account balance.

Example

curl -X DELETE https://win9-5.com/api/v1/sessions/cc57975684b942fc... \ -H "Authorization: Bearer bbx_abc123..."

Response (200)

{ "ok": true, "minutes_used": 3, "minutes_refunded": 27, "balance_minutes": 297 }
GET /api/v1/balance

Return current minute balance and account metadata.

Example

curl https://win9-5.com/api/v1/balance \ -H "Authorization: Bearer bbx_abc123..."
GET /api/v1/pricing

List minute packs and defaults. No authentication required.

Example

curl https://win9-5.com/api/v1/pricing
POST /api/v1/checkout

Create a Stripe Checkout URL for minute-pack purchases. No API key required.

Request body

FieldTypeRequiredDescription
productstringYesminutes_60, minutes_300, minutes_1000, subscription
emailstringNoPrefill customer email in checkout.

Example

curl -X POST https://win9-5.com/api/v1/checkout \ -H "Content-Type: application/json" \ -d '{"product":"minutes_300","email":"[email protected]"}'

Demo Session Endpoints

Cookie-authenticated endpoints for the hosted demo. No API key required — sessions are tracked via a bbx_session cookie.

POST /api/session

Create a demo browser session. If an active session already exists for the cookie, it is returned instead. Sessions last up to 15 minutes.

Example

curl -X POST https://win9-5.com/api/session \ -H "Content-Type: application/json" \ --cookie "bbx_session=..."

Response (201 created / 200 existing)

{ "sessionId": "cc57975684b942fc...", "loginUrl": "https://bbx-instance.fly.dev/login?token=...", "region": "iad", "minutes_allocated": 15, "expires_at": 1770612214916 }
GET /api/session/status

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.

Example

curl https://win9-5.com/api/session/status \ --cookie "bbx_session=..."

Response (200) — active session

{ "active": true, "sessionId": "cc57975684b942fc...", "loginUrl": "https://bbx-instance.fly.dev/login?token=...", "region": "iad", "minutes_allocated": 15, "expires_at": 1770612214916 }

Response (200) — no active session

{ "active": false }
POST /api/session/disconnect

Signal that the client is leaving. Supports defer (mark disconnected, allow grace-period reconnect) or hard (immediate teardown).

Request body

FieldTypeRequiredDescription
modestringNodefer (default) or hard.
sessionIdstringNoTarget a specific session. Omit to affect all sessions for this cookie.

Example

curl -X POST https://win9-5.com/api/session/disconnect \ -H "Content-Type: application/json" \ --cookie "bbx_session=..." \ -d '{"mode":"defer"}'

Response (200)

{ "ok": true, "mode": "defer", "ended": 0, "marked": 1 }

Error Model

Errors return JSON with an error field and may include extra context keys.

{ "error": "Insufficient minutes", "balance_minutes": 0, "requested_minutes": 15 }
StatusMeaning
400Missing or invalid parameters.
401Missing or malformed auth header.
402Insufficient minutes.
403Invalid API key.
404Session not found for that key.
503Billing subsystem unavailable.

Embedding with <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>
Attributes
AttributeTypeDefaultDescription
login-linkstringnoneRequired login URL with session token.
widthstring/number100%Component width. Bare numbers are interpreted as px.
heightstring/number100%Component height. Bare numbers are interpreted as px.
parent-originstring*Origin check for postMessage input validation.
request-timeout-msnumber30000Per-call timeout floor is 100ms.
ui-visiblebooleantrueShow or hide BrowserBox chrome UI.
allow-user-toggle-uibooleantrueAllow end user to toggle UI visibility.
chromestringdefaultChrome presentation hint: none, minimal, default, custom.
augment-rootstringopenAugment inspectability hint: open or closed.
capturestringsnapshotCapture policy hint: off, snapshot, sampled.
Properties
PropertyMaps toNotes
loginLinklogin-linkSet/remove source URL.
routingMidderivedRead-only resolved routing machine id.
widthwidthString values preserved.
heightheightString values preserved.
parentOriginparent-originDefaults to wildcard.
requestTimeoutMsrequest-timeout-msParsed as integer.
Events

Lifecycle and transport events

EventDetail payloadDescription
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.

Runtime forwarded events

EventDetail 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.
Methods

Lifecycle and generic dispatch

MethodDescription
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.

Tabs and navigation

MethodDescription
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.

Waiting and diagnostics

MethodDescription
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.

Automation

MethodDescription
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.

Unified action dispatch

MethodDescription
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 }.

UI controls

MethodDescription
uiVisible(visible?)Show or hide the BrowserBox chrome UI. Returns current visibility state.
allowUserToggleUI(allow?)Allow or deny the user from toggling UI visibility.
Namespaced API (Session Host)

The element exposes a namespaced session-host API alongside the classic flat methods. Access via bbx.session, bbx.tabs, etc.

session

Property / MethodDescription
session.idRead-only routing machine id.
session.usableRead-only browser usability flag.
session.transportRead-only transport mode (modern, legacy, unknown).
session.readyRead-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.

tabs

MethodDescription
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.

page

MethodDescription
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.

capture

MethodDescription
capture.frame({ format, quality })Capture the current rendered frame as a data URL.
capture.viewport({ format, quality })Capture the viewport as a data URL.

augment (capability-gated)

MethodDescription
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.

select (capability-gated)

MethodDescription
select({ prompt, intent })Enter interactive pick mode. getRaw() returns { selector, selectors, text, href, htmlSnippet }; generalized previews/extracts return normalized selector results.

policy

MethodDescription
policy.get()Return the merged effective policy snapshot. Server policy is authoritative; embedder attributes can only further restrict it.

Event helpers

MethodDescription
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 }.

Canonical event aliases

Legacy event names continue to work. New canonical dot-notation names are also emitted:

Legacy nameCanonical alias
api-readyapi.ready
tab-createdtab.created
tab-closedtab.closed
tab-updatedtab.updated
active-tab-changedtab.activated
did-navigatepage.navigated
did-start-loadingpage.load.started
did-stop-loadingpage.load.stopped
policy-deniedpolicy.denied
policy.changedpolicy.changed
usability-changedsession.usability.changed
disconnectedsession.disconnected

Transport behavior

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.

Error model

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.

Test coverage

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.