v2.2.0

AjaxResult

Specialised Result returned by every REST helper. Provides isMore() / getNext() / getTotal() / getStatus() for paged responses, and immutable data.

AjaxResult<T> extends Result<Payload<T>> and is the type every actions.v{2,3}.call.make() resolves to. Compared to the generic Result, it:

  • accepts the raw REST response (answer), the original request (query), and the HTTP status, and freezes them — setData() throws.
  • decodes Bitrix24 error payloads into AjaxError instances stored under the key 'base-error'.
  • exposes restApi:v2-only paging members: the envelope readers (isMore, hasMore, getTotal) and the manual-paging pair (getNext, fetchNext).
  • exposes the HTTP status (getStatus) and the original request (getQuery).

Reading Data

getData(): undefined | SuccessPayload<T>

Returns undefined when the result is not successful. On success, returns a frozen { result, time } — and only those two. The restApi:v2-only envelope fields next and total are not carried through; read them with isMore() and getTotal(), or let callList / fetchList page for you.

time is optional: a response does not always carry one, and the SDK does not invent it — see PayloadTime.

Use T to type the underlying result:

const response = await $b24.actions.v2.call.make<{ id: number, title: string }[]>({
  method: 'crm.item.list',
  params: { entityTypeId: 4, select: ['id', 'title'] },
  requestId: 'list-companies'
})

if (!response.isSuccess) {
  throw new Error(response.getErrorMessages().join('; '))
}

const data = response.getData()!     // { result: { id, title }[], time?: PayloadTime }
A body that is not an envelope is wrapped. If the response carries no result key at all, the whole body becomes result rather than being dropped. rest.documentation.openapi answers that way — the OpenAPI document at the top level — so getData()!.result is the document, with timeundefined. See Discovering v3 methods.

Pagination

Everything in this section reads the restApi:v2 envelope fields next / total, which restApi:v3 does not send.None of them is deprecated. An earlier plan removed all five in 3.0.0; it was withdrawn — see the migration notes. They behave differently under v3, though:
  • getNext / fetchNext throwSdkError({ code: 'JSSDK_CORE_METHOD_NOT_SUPPORT_IN_API_V3' }). Deliberately: returning false would be indistinguishable from "last page". Use actions.v3.fetchList.make under v3.
  • isMore / hasMore / getTotal do not throw — they return false / 0, because the field is absent. That is not the same statement as "no more rows" or "no rows matched", so do not branch on them under v3.
For new code the list helpers remain the recommendation for paging: they hide the offset bookkeeping and work under both protocol versions.

isMore / hasMore

isMore(): boolean
hasMore(): boolean   // alias

true when the success payload contains a numeric nextnext: 0 is a real offset and counts, a string does not. Always false for unsuccessful results, and always false under restApi:v3, which sends no next.

Its natural counterpart is getNext below, which is also restApi:v2-only. Under restApi:v3 neither is usable, so there isMore() is not a paging primitive at all — drive iteration with callList / fetchList.

getNext

getNext(http: TypeHttp): Promise<AjaxResult<T> | false>

Re-runs the original method with params.start = next and returns a new AjaxResult<T>. Returns false when there is no next page or the current result is unsuccessful.

fetchNext

fetchNext(http: TypeHttp): Promise<AjaxResult<T> | null>

Same as getNext, but returns null instead of false.

getTotal / getStatus / getQuery

getTotal(): number
getStatus(): number
getQuery(): Readonly<AjaxQuery>

getTotal reports the total the restApi:v2 envelope carries, and returns 0 on unsuccessful results — and on any restApi:v3 response, which sends no total. It is the only way to obtain a row count under restApi:v2: the list helpers iterate without exposing it, SuccessPayload omits it by design, and actions.v3.aggregate.make (count / countDistinct) is restApi:v3-only and @experimental — no shipped module publishes an *.aggregate action on any portal yet measured. AjaxQuery captures { method, params, requestId }; the returned object and its params are stable — calling getNext() does not mutate them.

Error Handling

When the raw response carries a { error: ... } field, AjaxResult converts it to an AjaxError (subclass of SdkError) keyed by 'base-error' in the inherited errors map. Both v2 and v3 error shapes are handled. A v3 validation[] array is folded into the message and kept intact on AjaxError.validation, which is where the failing field name is — the message alone does not carry it (#423).

import { AjaxError } from '@bitrix24/b24jssdk'

const response = await $b24.actions.v2.call.make({ method: 'profile', requestId: 'p' })
if (!response.isSuccess) {
  for (const error of response.getErrors()) {
    if (error instanceof AjaxError) {
      console.error(error.code, error.requestInfo?.method)
    }
  }
}

setData Is Disabled

setData(): never

Always throws ReferenceError('AjaxResult does not allow data modification'). Use higher-level helpers (callList, fetchList, batch) when you need to aggregate.