new B24Frame(...) directly — use initializeB24Frame(), which deduplicates concurrent inits, parses the window.name payload from Bitrix24, and awaits init() for you.B24Frame extends AbstractB24 and implements TypeB24. On top of the shared REST surface (actions.v2.*, actions.v3.*, tools.*) it exposes managers that talk to the parent window through postMessage: auth, parent, slider, dialog, placement, options.
Constructor
constructor(
queryParams: B24FrameQueryParams,
options?: { restrictionParams?: Partial<RestrictionParams> }
)
B24FrameQueryParams describes the Bitrix24-supplied identifiers parsed from window.name:
Unlike B24Hook and B24OAuth, B24Frame requires await b24.init() before any REST call — init() performs the getInitData handshake with the parent window. initializeB24Frame() does this for you.
Getters
isInit
get isInit(): boolean
true once the parent-window handshake completes. Until then, accessing auth, actions, tools, or any frame manager throws 'B24 not initialized'.
isFirstRun
get isFirstRun(): boolean
true on the very first launch of the application (Bitrix24 sets FIRST_RUN). On isFirstRun = true, the SDK automatically sends setInstall: true to the parent.
isInstallMode
get isInstallMode(): boolean
true while the application is in installation flow (INSTALL flag from the parent). Required by installFinish.
auth
get auth(): AuthManager
Authorization manager. Exposes getAuthData, refreshAuth, getUniq, isAdmin, plus auto-refresh on 401 responses.
parent
get parent(): ParentManager
Parent window manager. Posting messages to and reading metadata from the surrounding Bitrix24 page.
slider
get slider(): SliderManager
Slider manager. Open / close Bitrix24 sliders.
placement
get placement(): PlacementManager
Placement manager. Inspect and update the placement context.
options
get options(): OptionsManager
Options manager. Read application / user options synced from the parent window.
dialog
get dialog(): DialogManager
Dialog manager. Ask Bitrix24 to render its native confirm / message / file pickers.
Methods
init
init(): Promise<void>
Performs the parent-window handshake (getInitData), wires the manager state, and creates both REST API HTTP clients. Idempotent in practice — initializeB24Frame() deduplicates concurrent calls.
destroy
destroy(): void
Tears the frame down: unsubscribes from postMessage events, clears the pending-command timers, and drops the placement callbacks. Always call before unmounting the host component to avoid leaks.
Any command still waiting on the parent window is rejected with JSSDK_FRAME_DISPOSED rather than left pending — nothing can answer it once the listener is gone, and silence is the one outcome a caller cannot act on. Mirrors how a disposed PullClient rejects start() with PULL_DISPOSED.
This matters for a command whose promise you discarded. parent.closeApplication() and slider.closeSliderAppPage() are the usual pair, since they run precisely while the app is closing: if you call one without awaiting it and destroy the frame in the same breath, attach .catch(() => {}) so the rejection does not surface as an unhandled one.
installFinish
installFinish(): Promise<any>
Sends setInstallFinish to the parent. The returned promise rejects with an SdkError whose code is JSSDK_FRAME_INSTALL_ALREADY_FINISHED (message: Application was previously installed. You cannot call installFinish) when called outside install mode — guard with isInstallMode.
event.bind never fire, placements bound with placement.bind never appear, and other outgoing calls never reach your endpoints — even though each of those registration calls returned success.This is Bitrix24's documented behaviour: What doesn't work until installation is complete lists exactly placement.bind and event.bind as inert until the install is finished. (That page is the authority here; the SDK cannot reproduce portal-side behaviour, so if what you see differs — for instance on a self-hosted portal — trust the app.info check below over this prose.)Nothing fails loudly. Registration succeeds, imbot.register returns a botId, querying the handlers lists them — and no traffic ever arrives. Every visible signal says the setup is correct, which is why this is usually debugged at the wrong layer: nginx, tunnels, TLS, routing.Call it once, from the install page, as the last step of your install flow.This applies only to an app that has an installation interface. An API-only app with no interface must not call installFinish() — its installation completes automatically, and the method works only inside a browser interface frame (an install callback runs server-side and cannot call it). So if an app with no UI is missing events, installFinish() is not the cause; look elsewhere.Finishing the installation is a lifecycle step, not a security one. An app that also runs an OAuth install/uninstall endpoint still has to verify application_token on ONAPPINSTALL / ONAPPUNINSTALL — see Security patterns. The two are unrelated, and doing this one does not cover the other.To check an application after the fact, ask the portal:const response = await $b24.actions.v2.call.make<{ INSTALLED: boolean }>({
method: 'app.info',
requestId: 'app-info-1'
})
console.log(response.getData()!.result.INSTALLED) // false ⇒ installFinish() never landed
init handlers.That is stronger than "the next line might not run". This command is sent without the SDK's isSafely timer, so its promise settles only when the parent window answers — and if the reload happens first, the promise never settles at all. The await does not return, and a finally block attached to it does not execute. Treat installFinish() as the last statement of the install flow, and do not build state that depends on it resolving.getAppSid
getAppSid(): string
Application session id relative to the parent window (mirrors APP_SID).
getLang
getLang(): B24LangList
Bitrix24 interface language enum. See LangList.
getTargetOrigin / getTargetOriginWithPath
getTargetOrigin(): string
getTargetOriginWithPath(): Map<ApiVersion, string>
Portal origin and per-version REST endpoints (parent-supplied).
Inherited from AbstractB24
getHttpClient, setHttpClient, setRestrictionManagerParams, getLogger, setLogger, actions, tools. See:
Usage
import {
initializeB24Frame,
LoggerFactory,
EnumCrmEntityTypeId,
Text,
type B24Frame,
type ISODate
} from '@bitrix24/b24jssdk'
const $logger = LoggerFactory.createForBrowser('MyApp', import.meta.env?.DEV === true)
let $b24: undefined | B24Frame
async function loadCompanies() {
if (!$b24) return
const response = await $b24.actions.v2.callList.make<{ id: number, title: string, createdTime: ISODate }>({
method: 'crm.item.list',
params: {
entityTypeId: EnumCrmEntityTypeId.company,
select: ['id', 'title', 'createdTime']
},
idKey: 'id',
requestId: 'companies-list'
})
if (!response.isSuccess) {
$logger.error('REST error', { messages: response.getErrorMessages() })
return
}
return response.getData()!.map((item) => ({
id: Number(item.id),
title: item.title,
createdTime: Text.toDateTime(item.createdTime)
}))
}
async function bootstrap() {
try {
$b24 = await initializeB24Frame()
const companies = await loadCompanies()
$logger.notice('companies', { companies })
} catch (error) {
$logger.error('init failed', { error })
}
}
bootstrap()