SuperAPI AI Directory

b24jssdk-helpers

Data & analytics

View repository

Updated 10-15 20:06

About this skill

b24jssdk helpers and Pull

The useB24Helper() composable wraps B24HelperManager and the Pull client lifecycle. It's the recommended way to load portal-wide context (currencies, your app's install info, the current user) once per app boot.

Initial setup

import {
  initializeB24Frame,
  useB24Helper,
  LoadDataType,
  type TypePullMessage
} from '@bitrix24/b24jssdk'

const { initB24Helper, isInitB24Helper, destroyB24Helper, getB24Helper, usePullClient, useSubscribePullClient, startPullClient } = useB24Helper()

const $b24 = await initializeB24Frame()

await initB24Helper( $b24, [ LoadDataType.Profile, LoadDataType.App, LoadDataType.Currency, LoadDataType.AppOptions, LoadDataType.UserOptions ], /* requestId */ 'app-boot' )

const helper = getB24Helper()


Pass only the `LoadDataType` flags you actually need — `initB24Helper` issues a single batched REST call (`$b24.actions.v2.batch.make` internally) and each flag adds work to it. `Profile` and `App` (the defaults) are usually the minimum.

`isInitB24Helper()` returns `true` once `initB24Helper` resolved — useful for guards.

## Reading helper data

```ts
const me = helper.profileInfo.data
// { id, name, lastName, isAdmin, … }

const app = helper.appInfo.data
const status = helper.appInfo.statusCode  // EnumAppStatus

const license = helper.licenseInfo  // for enterprise checks
const payment = helper.paymentInfo

const baseCurrency = helper.currency.baseCurrency

Accessing helper.profileInfo before initB24Helper resolves throws B24HelperManager.profileInfo not initialized. Use isInitB24Helper() as a guard if the load is asynchronous w.r.t. your UI.

Currency formatting

const symbol  = helper.currency.getCurrencyLiteral('USD', 'en')   // '$'
const full    = helper.currency.getCurrencyFullName('USD', 'en')  // 'US Dollar'
const pretty  = helper.currency.format(1234.56, 'USD', 'en')      // '$1,234.56'

format honours per-currency rules (decimal places, separators) loaded from the portal.

Bulk options with notification

The helper-level OptionsManager can save many keys in one batch and broadcast a Pull event:

await helper.appOptions.save(
  {
    featureFlags: helper.appOptions.encode({ exportCsv: true, beta: false }),
    lastSyncAt: new Date().toISOString()
  },
  {
    moduleId: 'application',
    command: 'FEATURES_UPDATED',
    params: { source: 'app' }
  }
)

// `getJsonObject` returns `object` — it takes no type argument. Cast at the
// callsite if you want a shape.
const flags = helper.appOptions.getJsonObject(
  'featureFlags',
  { exportCsv: false, beta: false }
)

encode JSON-stringifies into a Bitrix24-compatible string; getJsonObject reverses it with a typed default.

Pull client (push events)

import type { TypePullMessage } from '@bitrix24/b24jssdk'
usePullClient()

useSubscribePullClient((m: TypePullMessage) => {
  if (m.command === 'FEATURES_UPDATED') {
    // re-read options, update UI
  }
}, /* moduleId */ 'application')

startPullClient()

Subscribe before startPullClient() — the client connects after start. useSubscribePullClient and startPullClient throw if usePullClient was not called first.

Publish from the back end, not from the Pull client

To put a message into the channel, call pull.application.event.add over REST — MODULE_ID is what your subscribers filter on:

import type { B24Frame } from '@bitrix24/b24jssdk'
declare const $b24: B24Frame

await $b24.actions.v2.call.make({
  method: 'pull.application.event.add',
  params: {
    COMMAND: 'FEATURES_UPDATED',
    PARAMS: { source: 'app' },
    MODULE_ID: 'application'
  }
})

PullClient does expose sendMessage(), but it needs pull.channel.public.list to resolve the recipients' channels and that method is not in the application REST surface — it usually rejects with JSSDK_PULL_PUBLIC_IDS_UNAVAILABLE. Do not generate code that calls it from an app.

"Usually" because the lookup is skipped when every recipient already has an unexpired cached channel, which the startup config call prefills from publicChannels — so a send to the current user can go out without rejecting. That is not a reason to use it: the send is still not a delivery receipt, and what comes back arrives on a SubscriptionType.Client subscription rather than the Server one subscribe() defaults to.

Nothing in the SDK gates publishing on being an application, either — isPublishingEnabled() reads only serverVersion > 3 && publish_enabled. And sendMessageToChannels() takes channel ids from the caller, so it never makes the lookup and never raises that code at all. The guidance above is about which path is SUPPORTED, not about which one the code permits.

Multiple subscriptions on different moduleIds are supported — call useSubscribePullClient once per channel:

useSubscribePullClient(handleAppEvent, 'application')
useSubscribePullClient(handleImEvent, 'im')
useSubscribePullClient(handleCrmEvent, 'crm')

To shut down (also tears the Pull client down):

import { useB24Helper } from '@bitrix24/b24jssdk'

const { destroyB24Helper } = useB24Helper()
destroyB24Helper()

Using helpers with B24Hook / B24OAuth

B24HelperManager itself works with any TypeB24. The composable is designed around the in-frame lifecycle, but for backend code you can construct the manager directly:

import { B24HelperManager, LoadDataType } from '@bitrix24/b24jssdk'

const helper = new B24HelperManager($b24)
await helper.loadData([LoadDataType.Profile, LoadDataType.Currency])
const baseCurrency = helper.currency.baseCurrency

Pull is only meaningful in an interactive context. Don't startPullClient() from a CLI script.

Anti-patterns

  • ❌ Calling initB24Helper twice without destroyB24Helper in between — the second call is a no-op (early-return on $isInitB24Helper), the data does NOT refresh.
  • ❌ usePullClient without useSubscribePullClient — connection runs but nothing handles messages.
  • ❌ Loading every LoadDataType "just in case" — every extra flag costs REST work in the batch.
  • ❌ Reading helper.profileInfo.data before initB24Helper resolves.