v3.0.0

B24Frame Initialization

Function is designed to initialize a B24Frame
initializeB24Frame(options?: {
  version?: ApiVersion
  restrictionParams?: Partial<RestrictionParams>
  httpOptions?: TypeHttpOptions
  keepAuthFresh?: boolean | KeepAuthFreshParams
}): Promise<B24Frame>

The initializeB24Frame function is designed to initialize a B24Frame object, which is used for working with Bitrix24 applications.

It manages the initialization process and handles potential connection errors.

Supports repeated calls until initialization is complete: every caller shares a single in-flight promise, so concurrent calls await one handshake and a resolved value is returned instantly. The first call wins: a later caller's options are ignored and the already-built frame is returned, so pass restrictionParams / httpOptions at the app's first init rather than at a call site that may run second.
If the app is opened outside the Bitrix24 iframe (a direct URL, a dev server, the install screen), window.name carries no DOMAIN/APP_SID. The promise then rejects promptly with an SdkError (code: JSSDK_CLIENT_SIDE_WARNING, status: 500) instead of hanging — including every concurrent caller sharing that promise — and a later call may retry once the app runs inside Bitrix24. Always await inside try/catch.Every call returns the same frame until that frame is destroyed. After $b24.destroy(), the next call builds a new one. Before #486 it returned the destroyed frame, which no longer hears the portal, so every call on it hung.

Parameters

  • options? — optional configuration:
    • restrictionParams?: Partial<RestrictionParams> — rate-limit / retry tuning forwarded to the frame's HTTP transports (the same knobs as setRestrictionManagerParams). Omit to use the defaults. Example: initializeB24Frame({ restrictionParams: { retryOnNetworkError: false } }).
    • httpOptions?: TypeHttpOptions — axios settings merged over the SDK's own defaults for both transports, forwarded to the constructor unchanged. The key it exists for is adapter: in a browser the SDK asks for fetch, because axios would otherwise walk ['xhr', 'http', 'fetch'] and take XHR by list order. Example: initializeB24Frame({ httpOptions: { adapter: 'xhr' } }). See Configuring the axios instance.
    • keepAuthFresh?: boolean | KeepAuthFreshParams — keep the access token alive while the tab is open. Off by default. Pass true for the defaults, or an object to tune the schedule. See Keeping the token alive.
    • version?: ApiVersion — reserved; accepted by the type but not yet consumed by the frame, so it currently has no effect.

Return Value

  • Promise<B24Frame>: Returns a promise that resolves to a B24Frame object upon successful initialization.

Usage

import { initializeB24Frame } from '@bitrix24/b24jssdk'

Keeping the token alive

The SDK refreshes the access token on the request path only: before a call, if the token has already expired, and again if the portal answers 401. (A valid token is used as it is — an ordinary call does not cost a refresh.) That covers an app that talks to Bitrix24 through $b24, and nothing else.

It does not cover the app that reads the token itself:

const $b24 = await initializeB24Frame()

// The token goes to your own backend — no `$b24` request is ever made,
// so nothing in the SDK ever refreshes it.
const auth = $b24.auth.getAuthData()
await fetch('/api/orders', {
    headers: { 'X-B24-Auth': auth === false ? '' : auth.access_token }
})

Leave that page open and untouched. After AUTH_EXPIRES seconds getAuthData() starts returning false, and every call to your own backend answers 401 or 403. Nothing changed and nothing failed — the token simply reached the end of its life with nobody there to renew it.

keepAuthFresh runs the timer for you:

const $b24 = await initializeB24Frame({ keepAuthFresh: true })

With it on:

  • the token is refreshed before it expires — on a margin, not on the fact of getAuthData() === false;
  • the check runs again whenever the tab becomes visible, because a background tab's timers are throttled and a frozen tab's are not run at all, so a timer alone would come back to a dead token;
  • a refresh that a call is already waiting for is not repeated — the keep-alive shares the in-flight one;
  • a failed refresh is never thrown at your app. It is a state, not an exception: the pulse logs through the SDK logger (silent unless you wired one) and tries again, backing off — 30 s, 1 min, 2 min, 4 min, 8 min, then every 10 min. A parent window that is navigated away or refusing is not worth a message every 30 seconds for the life of the tab.

Refreshing the frame token costs no REST call — it is a postMessage to the parent Bitrix24 window. Stopping is automatic: $b24.destroy() stops the pulse along with everything else.

Pass it at the app's firstinitializeB24Frame(). Every caller shares one in-flight promise and the first caller's options win, so a second call adding keepAuthFresh: true silently gets the first caller's frame with the pulse off — and the failure mode is the quiet one this option exists to prevent. If you enable it from a composable or plugin, make sure that is the code path that initialises the frame.

Why it is not on by default

It changes when your app talks to the parent window, and Bitrix warns that an application that refreshes too often risks being blocked automatically. An app whose requests all go through $b24 already gets a fresh token on every call and gains nothing from the timer. Turn it on when the token leaves the SDK, or when the app is expected to sit open and idle.

Tuning the schedule

type KeepAuthFreshParams = {
  marginMs?: number  // default 300000 — 5 minutes
  minDelayMs?: number // default 30000  — 30 seconds
  maxDelayMs?: number // default 600000 — 10 minutes
}
  • marginMs — how long before expiry a refresh becomes due. The pulse aims at expiry minus this, so it sleeps through the part of the token's life where there is nothing to do.
  • minDelayMs / maxDelayMs — the floor and ceiling on that sleep. From 15 minutes out, the ceiling binds: with the defaults the pulse sleeps the full 10 minutes and re-checks.
    • The floor cannot be lowered. minDelayMs can only raise it above 30 seconds — a slip of one order of magnitude would otherwise be thousands of messages a second, and refreshing too often is what risks the auto-block.
    • A maxDelayMs below the effective floor is raised to it, so { maxDelayMs: 10_000 } on its own means a 30-second ceiling, not a 10-second one.
// A portal handing out short-lived tokens: refresh 2 minutes ahead and never
// sleep longer than 2 minutes.
const $b24 = await initializeB24Frame({
    keepAuthFresh: { marginMs: 120_000, maxDelayMs: 120_000 }
})

An expiry the SDK cannot read (missing, zero, not a finite number) counts as due: one extra postMessage costs nothing next to missing the only chance to refresh.

A refresh that succeeds but buys no headroom — a token whose whole life is shorter than marginMs, so it is due again the moment it arrives — is treated like a failure and backs off the same way. Otherwise it would be one message every 30 seconds for as long as the tab is open, which is the thing the option is careful not to do.