v2.2.0

Discovering entity fields (*.field.list)

Ask the portal which fields an entity has, what type each one is, and whether it can be filtered, sorted or written — instead of guessing them or downloading the whole OpenAPI document. Also states the v3 camelCase field-name rule.

Overview

Most restApi:v3 entities publish a pair of metadata methods:

  • <entity>.field.list — every field the entity has, as a list of descriptors;
  • <entity>.field.get — one field, by name.

This is a large part of the v3 surface: 91 of the 245 methods a measured cloud portal publishes belong to this family — 37%. Every module has it: rest 22, main 18, note 10, bizprocdesigner 9, humanresources 8, tasks 8, mail 6, vibecodeconnector 6, call 2, timeman 2.

Discovering v3 methods answers which methods exist on a portal, with one document you fetch once and cache. This page answers which fields this one entity has — a small, cheap call you can make per entity, which also carries per-field flags the OpenAPI document does not.

Calling it through the SDK

An ordinary v3 call — no special helper:

const response = await $b24.actions.v3.call.make<{
  items: Array<{ name: string, type: string, sortable: boolean, filterable: boolean }>
}>({ method: 'tasks.task.field.list' })

const fields = response.getData()?.result?.items ?? []
const sortable = fields.filter(field => field.sortable).map(field => field.name)

The rows arrive under result.items. <entity>.field.get answers with a single descriptor under result.item instead:

const response = await $b24.actions.v3.call.make<{
  item: { name: string, type: string, sortable: boolean }
}>({ method: 'tasks.task.field.get', params: { name: 'title' } })

Both accept an optional select, which narrows the descriptor keys — pass select: ['name', 'sortable'] and each row comes back with those two keys only.

What a descriptor holds

KeyWhat it means
nameThe field name to use in select, filter and order.
typestring, integer, datetime, …
title / descriptionHuman-readable labels. description is often null.
filterableWhether the field may appear in filterand in an aggregate select; see below.
sortableWhether it may appear in order.
editableWhether it may be written.
requiredGroupsThe operations the field is mandatory for, e.g. ['add'].
multiple / elementTypeWhether the value is a list, and of what.
validationRulesPortal-side constraints, when the field declares any.

Three of these have no other source. filterable, editable and requiredGroups appear nowhere in the OpenAPI document's request schema, so "can I filter on this?" and "what must I pass to add?" are answerable here and nowhere else.

sortable and filterable are independent — do not infer one from the other. They happen to name the same five fields on main.eventlog (id, timestampX, auditTypeId, userId, guestId of thirteen), which makes the coincidence look like a rule. It is not: on tasks.task, title is sortable: true and filterable: false, and exactly one field of ninety-five — id — is filterable at all, against nineteen that are sortable. A rich order alongside a bare filter is a normal state for a v3 entity, not a portal fault. Under restApi:v2 the same entity filters on RESPONSIBLE_ID, STATUS and GROUP_ID happily; that is a difference between the two APIs, not something to work around.
filterable also gates aggregation, which the flag's name does not suggest. A field that is selectable and comes back from list quite normally is still refused by an aggregate select unless it is filterable — the portal checks the same attribute for both. Measured: the refusal is a soft failure (isSuccessfalse, not a throw — a 4xx in the restApi:v3 envelope), carrying BITRIX_REST_V3_EXCEPTION_VALIDATION_REQUESTVALIDATIONEXCEPTION and naming the field in validation[].field. Match on the code and the field: the message is localised. Given the ratio above, this is a real constraint on what you can ask a v3 entity to count — see Choosing the right method.

requiredGroups is null rather than an empty array when a field is required by nothing — guard before iterating it.

The flag is the source of truth, and the set moves. Which fields an entity marks filterable or sortable is decided by the Bitrix24 module that owns the entity, and it changes from one module version to the next. The reference documentation states the current answer per method — tasks.task.list on restApi:v3, for instance, documents id as the only supported filter — but the portal in front of you is the one that answers your request. Read the flag rather than assume, especially in code that has to keep working across portal upgrades.

Why it is worth the call

A v3 field that is not marked Filterable or Sortable is refused — the portal does not quietly ignore the clause. Both refusals were measured, on two entities. Both arrive soft: a 4xx in the restApi:v3 envelope is not thrown, so check isSuccess rather than writing a try/catch around these.

// `title` has `filterable: false` — this answers HTTP 400
await $b24.actions.v3.call.make({
  method: 'tasks.task.list',
  params: { filter: [['title', '=', 'x']], select: ['id'] }
})
{
  "error": {
    "code": "BITRIX_REST_V3_EXCEPTION_VALIDATION_REQUESTVALIDATIONEXCEPTION",
    "validation": [{ "field": "title", "message": "…requires the `Filterable` attribute…" }]
  }
}

Ordering by a field with sortable: false answers the same way, naming Sortable — measured on main.eventlog.list ordered by description, one of the thirteen fields that method returns:

{
  "error": {
    "code": "BITRIX_REST_V3_EXCEPTION_VALIDATION_REQUESTVALIDATIONEXCEPTION",
    "validation": [{ "field": "description", "message": "…`EventLogDto`…`Sortable`…" }]
  }
}

A field being returned says nothing about whether it may be filtered or sorted on.

The message is localised — a portal answers in the portal's language. Match on error.code and on validation[].field, never on the text.

The useful habit is therefore: read the fields, then build the request.

const meta = await $b24.actions.v3.call.make<{
  items: Array<{ name: string, filterable: boolean, sortable: boolean }>
}>({ method: 'tasks.task.field.list', params: { select: ['name', 'filterable', 'sortable'] } })

const fields = meta.getData()?.result?.items ?? []
const canFilterOn = new Set(fields.filter(field => field.filterable).map(field => field.name))

// On the portal measured, `tasks.task` exposes exactly one filterable field: `id`.
if (canFilterOn.has('deadline')) {
  // …only then send a filter on `deadline`
}

Field names

restApi:v3 field names are camelCase. Measured across two entities and 108 descriptors — tasks.task (95) and main.eventlog (13) — not one of the 108 starts with an uppercase letter: id, title, creatorId, responsibleId, startPlan, storyPoints, timestampX, auditTypeId.

restApi:v2 is the opposite: ID, TITLE, RESPONSIBLE_ID.

That is the whole reason for the SDK's paging defaults, and it is a rule rather than a per-method quirk:

Default idKey
actions.v3.callList / fetchList'id'
actions.v2.callList / fetchList'ID'

cursorIdKey exists for the methods that spell the id differently in the request and in the response. Under restApi:v2, tasks.task.list is the known case: it returns a lowercase id but filters on an uppercase ID, so a walk left on the defaults reads the cursor from a field that is not there, never advances, and repeats the first page for ever.

// restApi:v2 `tasks.task.list` — without `cursorIdKey` the walk never ends
const response = await $b24.actions.v2.callList.make({
  method: 'tasks.task.list',
  params: { select: ['ID', 'TITLE'] },
  idKey: 'id',
  cursorIdKey: 'ID',
  customKeyForResult: 'tasks'
})

Under restApi:v3 the same method needs no override — request and response agree on id.

When a walk returns rows but the same ones over and over, this is the first thing to check. Ask <entity>.field.list what the response calls its id.

Availability

Near-universal, not universal. On the cloud portal measured, seven entities publish a .list with no matching .field.list — the four crm.*.timeline.activity.email families, humanresources.access.permission, humanresources.node.communication and rest.scope. Treat a missing metadata method as ordinary: check isSuccess and fall back to the OpenAPI document or to documented field names.

The counts here are portal-specific, like the rest of the v3 surface — the portals measured published 147, 220 and 245 methods in total. Read them as an order of magnitude, not a contract.

Alternatives and Recommendations

  • One entity's fields, with flags<entity>.field.list. Small, cheap, per entity, and the only source of filterable / editable / requiredGroups.
  • The whole method surfacerest.documentation.openapi. One document, often 100 KB or more; fetch it once and cache it.
  • Neither — for restApi:v2, the classic crm.item.fields / *.fields methods still apply; this family is v3.