actions.v2.* / actions.v3.* and never touch TypeHttp directly. Reach for it when you need raw call / batch, custom limiter tuning, or runtime stats.TypeHttp is the contract implemented by HttpV2 and HttpV3. Each B24Frame / B24Hook / B24OAuth owns one instance per REST API version. Reach them through:
import { ApiVersion } from '@bitrix24/b24jssdk'
const v2 = $b24.getHttpClient(ApiVersion.v2)
const v3 = $b24.getHttpClient(ApiVersion.v3)
Properties
Logger
setLogger(logger: LoggerInterface): void
getLogger(): LoggerInterface
Lets you swap a debug logger into a single client without affecting the rest of the SDK. See Logger.
Calling REST
call
call<T = unknown>(
method: string,
params: TypeCallParams,
requestId?: string
): Promise<AjaxResult<T>>
Low-level single-method call. Higher-level helpers (actions.v2.call.make, callList, fetchList) build on top.
batch
batch<T = unknown>(
calls: BatchCommandsArrayUniversal | BatchCommandsObjectUniversal | BatchNamedCommandsUniversal,
options?: ICallBatchOptions
): Promise<Result<ICallBatchResult<T>>>
Low-level batch call. Three input shapes are accepted:
- Array of tuples:
[ [method, params], [method, params] ] - Array of objects:
[ { method, params, as?, parallel? }, ... ] - Named map:
{ key1: { method, params }, key2: [method, params] }
params is the only key read for a command's arguments — writing them under
query, the portal's own wire name, loses them silently. See the warning on the
BatchV3 and
BatchV2 pages — the two
transports lose them by different routes.
For most use cases call actions.v2.batch.make / actions.v3.batch.make, which handle the response unwrapping and returnAjaxResult.
BatchRequestEnvelopeV2 is exported alongside these types but is not something you construct. It names what the restApi:v2 transport puts on the wire for a batch — { halt, cmd } — which reaches call through a parameter typed TypeCallParams and type-checks only because of that type's permissive index signature. It is documented here so an exported symbol is not a mystery, not because a caller needs it. restApi:v3 has no envelope: the commands are the request body, a bare top-level JSON array. That leaves nowhere in the body for a credential — the portal reads every top-level entry as a command — so a webhook keeps its secret in the URL and a server-side B24OAuth sends the token in an Authorization: Bearer header. A browser cannot send that header (the portal's CORS preflight does not allow it), which is why a v3 batch does not work from B24Frame; see BatchV3 Limitations.Configuring the axios instance
ajaxClient is the live axios instance the transport uses. There are two ways
in. httpOptions at construction is merged over the SDK's own defaults, which is
where adapter belongs; anything else you can change after the client exists,
through defaults:
import { B24Hook } from '@bitrix24/b24jssdk'
const b24 = B24Hook.fromWebhookUrl(
'https://your-portal.bitrix24.com/rest/1/SECRET',
{ httpOptions: { adapter: 'xhr' } }
)
A frame app passes the same option to initializeB24Frame(), which forwards it to the B24Frame constructor unchanged — and a browser is where adapter earns its keep, since that is the runtime whose adapter changed. The first call wins: a later initializeB24Frame() returns the frame already built and ignores its options.
import { initializeB24Frame } from '@bitrix24/b24jssdk'
const $b24 = await initializeB24Frame({ httpOptions: { adapter: 'xhr' } })
httpOptions is a deliberately narrow slice of AxiosRequestConfig — TypeHttpOptions: adapter, timeout, timeoutErrorMessage, proxy, httpAgent, httpsAgent, maxRedirects, maxContentLength, maxBodyLength, decompress, withCredentials. baseURL, transformRequest, paramsSerializer and validateStatus are how the SDK talks to the portal, and overriding them breaks it quietly — a transformRequest here replaces the request body wholesale, with no error on either side and a portal-side failure only — so they are not offered, and a key outside the list is dropped at construction, with the dropped names logged (never their values). The type alone would not do it: excess-property checking does not fire on a variable, and plain JavaScript has no compiler at all. They remain reachable through defaults below, where it reads as the deliberate act it is.
adapter replaces the transport wholesale, which is strictly more than the excluded transformRequest could do, and proxy / httpAgent route token-bearing traffic wherever you point them. Both are on the list, because adapter is the reason it exists. The filter also reaches the two REST transports only: the OAuth token-refresh client builds its own axios instance, so adapter, timeout and proxy do not apply to the request that posts client_secret to the OAuth server.
:: headers is the one exception, and not an offered one: TypeHttpOptions does not accept it, so httpOptions: { headers: … } is a compile error. The merge itself survives for the path that predates the type — a direct new HttpV2(...), or a call from untyped JavaScript — as it has since #144.import { ApiVersion } from '@bitrix24/b24jssdk'
const http = $b24.getHttpClient(ApiVersion.v3)
http.ajaxClient.defaults.timeout = 120_000
http.ajaxClient.defaults.proxy = { host: '10.0.0.1', port: 3128 }
timeout: 30_000and a matchingtimeoutErrorMessage. Raise it for a long-running report method rather than raising the retry count. The message is read by the XHR and Node adapters only; onfetchaxios composes its own (timeout of 30000ms exceeded, codeETIMEDOUTrather thanECONNABORTED). The SDK classifies both as a timeout either way.User-Agent, on server-side runtimes only — a browser and a worker forbid the header, so it is not set in either.Content-Type: application/json, per request rather than on the instance. The portal reads afilterboolean only from a JSON body, and axios was supplying that content type by default rather than by intent — see Filtering. Because it is set per request,ajaxClient.defaults.headersno longer reaches SDK traffic; your own requests through this instance are unaffected, including aFormDatabody, whose multipart boundary axios still computes. A request interceptor you install on this instance still outranks it — that runs after the config is assembled — so an interceptor that setsContent-Typechanges the encoding of SDK traffic too, and with it the boolean-filter behaviour above.adapter: 'fetch', in a browser or a worker only. Left alone, axios walks['xhr', 'http', 'fetch']and takes the first supported entry, which is XHR whereverXMLHttpRequestexists. Outside a browser nothing is asked for.
jsdom counts as a browser here, so a double that
stubs XMLHttpRequest stops intercepting SDK traffic — pass
httpOptions: { adapter: 'xhr' } in that suite. And axios gates
onUploadProgress on request streaming, which only Chromium over HTTP/2
supports: your own uploads through ajaxClient get no progress events in
Firefox or Safari, where XHR always delivered them. Same opt-out.maxRedirects is forced to 0 on one request, and only one. A
restApi:v3 batch on a non-hook transport outside a browser carries the access
token in an Authorization: Bearer header, and a redirect would take it along:
follow-redirects strips the header when the host changes, but keeps it for the
same host and for a subdomain. A credential in the body was safe here by
accident — a 301/302 turns POST into GET and drops the body, so the token that
used to sit in auth never travelled.By default the constraint is per-request, not on the instance: nothing else the
SDK sends is affected, and a redirect elsewhere in your traffic still works. A portal that
does redirect this one request gets a legible 301 instead of a silent hop with a
bearer token attached.In a browser the sibling branch behaves differently, and since the fetch
adapter arrived it is no longer inert. There the token rides in the query string
rather than a header, maxRedirects: 0 is set for the same reason, and fetch
reads it as redirect: 'manual' where XHR ignored it outright. What comes back
is an opaque response — status: 0, empty body, no headers —
and axios resolves that: settle returns early on any falsy status, before
validateStatus is consulted, and the fetch adapter has no status-0 guard of its
own (XHR did). Left at that, the refused request would answer as a silently empty
success, so the SDK raises JSSDK_HTTP_REDIRECT_BLOCKED itself — only on the
request that asked for maxRedirects: 0, so an ordinary status-0 network failure
is unaffected. Same narrow scope: a restApi:v3 batch on a non-hook transport.If you know your redirect target and want the hop anyway, a transport subclass
can return maxRedirects from _prepareRequestConfig and it wins — the value
is a default, applied before the per-request config is spread over it, not a
lock. Setting ajaxClient.defaults.maxRedirects does not reach it: a
per-request config outranks the instance default in axios.Limiter Configuration
setRestrictionManagerParams(params: RestrictionParams): Promise<void>
getRestrictionManagerParams(): RestrictionParams
Update or read the restriction policy on this client. The setter replaces the parameters you name and leaves the rest alone, with the nested limiter blocks replaced whole — see Updating the parameters. The getter returns a copy. To change both v2 and v3 at once, use b24.setRestrictionManagerParams(...).
See Limiters for the params shape and presets (ParamsFactory.getDefault(), getBatchProcessing(), getRealtime(), fromTariffPlan()).
Statistics
getStats(): RestrictionManagerStats & {
adaptiveDelayAvg: number
errorCounts: Record<string, number>
totalRequests: number
successfulRequests: number
failedRequests: number
totalDuration: number
byMethod: Map<string, { count: number, totalDuration: number }>
lastErrors: { method: string, error: string, timestamp: number }[]
}
Snapshot of the limiter + per-method counters. Useful for dashboards. See Limiters → Monitoring for the full breakdown.
Reset
reset(): Promise<void>
Clears the limiter state and statistics. Typical use: after a destructive incident response or in long-running daemons that want a clean window.
Client-Side Warning
setClientSideWarning(value: boolean, message: string): void
B24Hook and B24OAuth enable a runtime warning when used in a browser-like runtime — the main thread or any worker (their secrets must never reach the client, and a worker's bundle is as public as the page's). Toggle it from the parent class via b24.offClientSideWarning(); this method is the underlying primitive.