---
title: "Discovering v3 methods (OpenAPI)"
description: "Use rest.documentation.openapi to fetch the portal's own machine-readable list of every available REST API v3 method — the source of truth the SDK relies on instead of a hardcoded allowlist. Especially useful for AI agents and codegen."
canonical_url: "https://bitrix24.github.io/b24jssdk/docs/working-with-the-rest-api/discovering-v3-methods"
last_updated: "2026-06-25"
---
# Discovering v3 methods (OpenAPI)

> Use rest.documentation.openapi to fetch the portal's own machine-readable list of every available REST API v3 method — the source of truth the SDK relies on instead of a hardcoded allowlist. Especially useful for AI agents and codegen.

## Overview

`rest.documentation.openapi` is a v3 REST method that returns the portal's **own**[OpenAPI 3.0.0](https://spec.openapis.org/oas/v3.0.0){rel="[\"nofollow\"]"} document — a single
machine-readable description of every REST API v3 method that exists **on that
specific portal**, with the request body fields (and example values) and the
response envelope for each one.

This is the **source of truth** for v3 method availability. The SDK deliberately
keeps **no** hardcoded list of v3 methods (an earlier allowlist both lagged the
server and blocked valid methods); instead, `$b24.actions.v3.*` sends any method
to the server and lets it decide. When you need to know *what's actually there*
— which methods, which fields — you ask the portal itself with this call.

> [!NOTE]
> The document reflects the **modules installed on this portal** and the **scopes
> your token holds**, so two portals can return different method sets. Always treat
> it as portal-specific, not a global catalogue.

## Calling it through the SDK

It's an ordinary v3 call — no special helper:

```ts
const response = await $b24.actions.v3.call.make<{ openapi: string }>({
  method: 'rest.documentation.openapi'
})

if (!response.isSuccess) {
  console.error(new Error(`Error: ${response.getErrorMessages().join('; ')}`))
} else {
  const doc = response.getData()?.result
  console.log(`OpenAPI ${doc?.openapi}`) // e.g. "3.0.0"
}
```

## What the document looks like

A standard OpenAPI 3.0.0 object. The parts you care about in practice:

| Field | What it holds |
| --- | --- |
| `openapi` | spec version string, e.g. `"3.0.0"` |
| `info` | `{ title: "Bitrix24 REST V3 API", version }` |
| `tags` | one entry **per module** — `humanresources`, `mail`, `main`, `note`, `rest`, `tasks`, `timeman`, … |
| `paths` | one entry **per method**, keyed by `/method.name` (e.g. `/tasks.task.list`) |

Each `paths['/method.name']` carries `post` (and `get`) operations with a
`tags` array (the owning module), a `requestBody` JSON Schema describing the
accepted parameters — often with an `example` field listing the real field
names — and a `responses` schema for the `{ result }` envelope.

```ts
// Shape (abridged) — the fields you read in practice
type OpenApiDoc = {
  openapi: string // e.g. "3.0.0"
  info: { title: string, version: string } // title: "Bitrix24 REST V3 API"
  tags: Array<{ name: string, description: string }> // one entry per module
  paths: Record<string, {
    // keyed by "/method.name", e.g. "/tasks.task.list"
    post?: {
      tags?: string[] // the owning module
      requestBody?: { content: { 'application/json': { schema: unknown } } }
    }
    get?: { tags?: string[] }
  }>
}
```

## Why this matters for AI agents

The document is the cleanest way for an LLM or a code generator to work against a
portal **without guessing**:

- **Discovery** — enumerate exactly which v3 methods exist before generating a
call, instead of hallucinating a method name that returns
`METHODNOTFOUNDEXCEPTION`.
- **Correct fields** — read the real `select` / parameter names from each
method's `requestBody` schema (and its `example`) instead of inventing them.
- **Typing / codegen** — feed the schema into a generator to produce typed
wrappers, or narrow `$b24.actions.v3.call.make<T>()` with the right `T`.
- **Portal-aware** — because the answer is per-portal, an agent can adapt to the
modules and scopes actually present rather than to a generic assumption.

> [!TIP]
> The document is large (often **100 KB+**) and **response-only** — it does not
> change between calls within a session. Fetch it **once**, cache it, and query the
> cached object. Don't request it on every interaction.

## Error Handling

`rest.documentation.openapi` is a normal v3 call, so it follows the standard
`AjaxResult` contract — always check `isSuccess`{className="language-ts-type shiki shiki-themes material-theme-lighter material-theme material-theme-palenight" language="ts-type" style=""} before reading
the document:

```ts
const response = await $b24.actions.v3.call.make<{ openapi: string }>({
  method: 'rest.documentation.openapi'
})

if (!response.isSuccess) {
  // e.g. the token lacks the scope, or the portal is unreachable
  console.error(new Error(`Error: ${response.getErrorMessages().join('; ')}`))
} else {
  const doc = response.getData()?.result
  console.log(`OpenAPI ${doc?.openapi}`)
}
```

## Examples

### List every available method

```ts
const response = await $b24.actions.v3.call.make<{
  paths: Record<string, unknown>
}>({ method: 'rest.documentation.openapi' })

const methods = Object.keys(response.getData()?.result?.paths ?? {})
  .map(path => path.replace(/^\//, '')) // "/tasks.task.list" → "tasks.task.list"

console.log(`${methods.length} v3 methods available`)
```

### Methods grouped by module

```ts
type OpenApiDoc = {
  paths: Record<string, { post?: { tags?: string[] } }>
}

const doc = (await $b24.actions.v3.call.make<OpenApiDoc>({
  method: 'rest.documentation.openapi'
})).getData()?.result

const byModule = new Map<string, string[]>()
for (const [path, ops] of Object.entries(doc?.paths ?? {})) {
  const moduleName = ops.post?.tags?.[0] ?? 'unknown'
  const list = byModule.get(moduleName) ?? []
  list.push(path.replace(/^\//, ''))
  byModule.set(moduleName, list)
}

console.log([...byModule.keys()]) // ['humanresources', 'mail', 'main', 'note', 'rest', 'tasks', 'timeman', …]
```

### Check whether a specific method exists

```ts
const doc = (await $b24.actions.v3.call.make<{ paths: Record<string, unknown> }>({
  method: 'rest.documentation.openapi'
})).getData()?.result

const exists = Boolean(doc?.paths?.['/note.collection.list'])
console.log(`note.collection.list on v3: ${exists}`)
```

## Alternatives and Recommendations

- **Apidocs reference**: the public [REST API v3 reference](https://apidocs.bitrix24.com/api-reference/rest-v3/index.html){rel="[\"nofollow\"]"}
documents methods in human-readable form; `rest.documentation.openapi` is the
*programmatic, portal-specific* counterpart.
- **For calling a discovered method**: use [`Call`](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/call-rest-api-ver3.md),
[`CallList`](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/call-list-rest-api-ver3.md) /
[`FetchList`](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/fetch-list-rest-api-ver3.md), or the
native [`CallTail` / `FetchTail`](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/fetch-list-rest-api-ver3.md)
when the method publishes a `tail` action.
- **Picking v2 vs v3**: see [Choosing the right method](https://bitrix24.github.io/b24jssdk/raw/docs/working-with-the-rest-api/choosing-the-right-method.md).

## Sitemap

See the full [sitemap](/b24jssdk/sitemap.md) for all pages.
