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
AjaxErrorinstances 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 }
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
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/fetchNextthrow —SdkError({ code: 'JSSDK_CORE_METHOD_NOT_SUPPORT_IN_API_V3' }). Deliberately: returningfalsewould be indistinguishable from "last page". Useactions.v3.fetchList.makeunder v3.isMore/hasMore/getTotaldo not throw — they returnfalse/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.
isMore / hasMore
isMore(): boolean
hasMore(): boolean // alias
true when the success payload contains a numeric next — next: 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.