Runtime API
The platform injects one frozen global, window.BRT, before your entry module runs. It contains the approved bridge between the isolated extension frame and the storefront.
Use brt-extension.d.ts for TypeScript and editor completion. The exact machine-readable operations are in contract.json.
Initialization
Wait for BRT.ready before reading settings or calling an API.
const {capabilities, settings} = await window.BRT.ready;
Initialization fails after 10 seconds when the host cannot establish a valid channel. Calls also time out after 10 seconds.
BRT.capabilities() returns the currently granted capability keys. BRT.settings() returns the public values configured in the builder. Both snapshots are deeply frozen.
A store user can decline or revoke a capability. Check availability, handle rejected promises, and leave the section useful when optional access is missing.
Theme
Capability: site.theme.read
const theme = await BRT.theme.read();
Returns strings for primary, secondary, background, surface, text, mutedText, link, button, headingFont, bodyFont, sectionGap, and buttonRadius.
Treat values as CSS values, not HTML. Set known style properties or custom properties directly.
Catalog
Capability: catalog.products.read
const result = await BRT.catalog.products({
search: 'optic',
page: 1,
limit: 12,
includeOutOfStock: false,
});
Use a limit of 12 or 24. The result has this shape:
{
products: [{
id: 123,
name: 'Product name',
url: '/product/example?pid=123',
image: '/storage/example.webp',
price: '$99.00',
inStock: true,
}],
total: 1,
page: 1,
lastPage: 1,
}
Product values are public storefront data. Still render strings with textContent or equivalent safe DOM APIs.
The url identifies the product's storefront route, but protocol version 1 does not provide a product-navigation action. Do not navigate the isolated frame or try to reach its parent. If product-detail navigation is required, report that platform gap during review.
Cart
Capability: cart.manage
await BRT.cart.manage('add', {productId: 123, quantity: 1});
await BRT.cart.manage('update', {productId: 123, quantity: 2});
await BRT.cart.manage('remove', {productId: 123});
Returns {ok, itemCount, total}. The host also dispatches its normal cart-updated event so the surrounding storefront can refresh.
Booking
Capabilities: booking.availability.read and booking.create
const availability = await BRT.booking.availability({
laneId: 4,
date: '2026-09-15',
durationMinutes: 60,
});
await BRT.booking.start({
laneId: 4,
startsAt: '2026-09-15T16:00:00-06:00',
endsAt: '2026-09-15T17:00:00-06:00',
});
Availability returns the public response from the site's range-availability endpoint. booking.start opens the BRT booking flow and returns {opened, url}.
Waivers
Capability: waivers.start
await BRT.waivers.start('range');
The accepted values are range, rental, and class. A missing value defaults to range. The call opens the BRT waiver flow and returns {opened, url}.
Approved forms
Capability: forms.submit
Newsletter:
await BRT.forms.submit('newsletter', {email: 'visitor@example.com'});
Contact:
await BRT.forms.submit('contact', {
questionType: 9,
name: 'Visitor name',
email: 'visitor@example.com',
phone: '555-555-0100',
subject: 'Store question',
message: 'Question text',
});
Both return {ok}. BRT supplies its own anti-abuse state. Extensions never receive CSRF tokens or application sessions.
Text messaging
Capability: communications.sms.open
await BRT.communications.text('I have a question about this item.');
The call opens the visitor's messaging app with the store's configured number. It returns {opened: true}. It fails with ADAPTER_UNAVAILABLE when the site has no valid text-message link.
Analytics
Capability: analytics.events.write
await BRT.analytics.track('Select product', {
label: 'Featured products',
value: 99,
});
Returns {tracked}. BRT honors the site's tracking configuration and consent state. Do not encode customer information in event names, labels, or values.
Raw requests
BRT.request(capability, action, payload) is available for forward-compatible low-level use. Prefer the named methods above. The host rejects unknown capabilities and actions even when a raw request is syntactically valid.
Messages must contain plain JSON-compatible data. Functions, DOM nodes, class instances, non-finite numbers, prototype keys, excessive nesting, and payloads above 65,536 bytes are rejected.
Errors
Rejected calls use an Error with a stable code property. Handle at least:
| Code | Meaning |
|---|---|
CAPABILITY_NOT_GRANTED |
The store user did not grant or later revoked access. |
ADAPTER_UNAVAILABLE |
The site cannot provide the requested operation. |
INVALID_REQUEST |
The action or payload failed validation. |
INVALID_PAYLOAD |
The request contains a value that cannot cross the isolated bridge. |
INITIALIZATION_TIMEOUT |
The host did not initialize the extension within 10 seconds. |
REQUEST_TIMEOUT |
No response arrived within 10 seconds. |
TOO_MANY_REQUESTS |
The frame already has 64 pending calls. |
PAYLOAD_TOO_LARGE |
Serialized request data exceeds 65,536 bytes. |
PAYLOAD_TOO_COMPLEX |
Data exceeds depth, node, or collection limits. |
REQUEST_FAILED |
The host rejected the operation without a more specific public code. |
Show a useful local fallback. Do not display raw exception details to storefront visitors.