For AI agents: markdown of this page — /docs-content-en/keys-auth/me.md documentation index — /llms.txt

Key self-description

GET /v1/me

Returns a self-description of the key that made the request: its type, the bound Bitrix24 account, that account's plan and the platform capabilities available on it. No scope is needed — the endpoint responds to any valid key and serves as an AI model's starting point for exploring the Bitrix24 account.

The response shape depends on the key type. How the key is passed in the request — Passing the key.

Parameters

Parameter Type Required Values Description
refresh (query) string no tariff Forces a live re-check of the Bitrix24 account plan before the response is built. Works only for keys bound to a Bitrix24 account. Without the parameter the response is served from the server cache.

Examples

curl — personal key

Terminal
curl https://vibecode.bitrix24.com/v1/me \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl https://vibecode.bitrix24.com/v1/me \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/me', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data } = await res.json()
console.log('Key type:', data.type, '· portal:', data.portal)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/me', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})
const { data } = await res.json()

Response fields

The response describes the key, not an entity on the Bitrix24 account. The top-level data.* blocks are a capability map: some blocks are common to all keys, some appear only for a key of a certain type. The "Key type" column shows which key types each block appears for.

If this is your first look at the key, four blocks are enough. type tells you which key you are working with. scopes — which data you have access to. accessMode — whether writing is allowed. capabilities — which operations are available on this Bitrix24 account and why the rest are denied. The other blocks are needed for a specific task: deployment and infra when working with servers, ai and webSearch when calling models, storage when uploading files.

Field Type Key type Description
success boolean all Always true on success
data.type string all Key type: personal, oauth_app or management
data.portal string vibe_api_, vibe_app_ Domain of the bound Bitrix24 portal
data.portalId string vibe_api_, vibe_app_ Stable identifier of the bound Bitrix24 portal. Unlike the domain, it survives a rename or a move of the portal — use it whenever local data is split per account. A key with no portal never reaches this response: it gets 401 NO_PORTAL, so the field is never empty in a successful response
data.tariff object all Bitrix24 account plan: code, name, isCommercial, wasEverCommercial, checkedAt, kind
data.tariff.name string · null all Human-readable edition name — meant for display, not for comparison in code. May be null. Details below
data.tariff.wasEverCommercial boolean all The account has been seen on a commercial plan. The flag is not one-way — see below
data.tariff.checkedAt string all Time of the last ATTEMPT to check the plan against Bitrix24, ISO 8601. Updated when called with ?refresh=tariff — including when the check failed and the plan could not be read. A SUCCESSFUL check is marked by a separate response header, X-Tariff-Checked-At (see Infrastructure), and that header may be absent from the very same response. If the field is present but the header is not, the check was attempted and the plan could not be read
data.scopes array all Key scopes. Choosing a set — Scopes
data.api.scopeRequirements object all Map of the key's scopes: what it lacks and what each missing scope would open. A pre-flight check instead of calling blind. Details below
data.api.scopeRequirements.granted object all Granted scopes, split into bitrix24 and platform — they are obtained differently
data.api.scopeRequirements.coverage object all Map completeness: entities is always complete, paths is complete or partial. When paths is partial, the path list is incomplete, and the absence of a path from unlocks does NOT prove the path is ungated
data.api.scopeRequirements.missing object all Missing scopes. Each carries entities — entities it would open, unlocks — paths (at most five, the rest in unlocksRemaining next to truncated), howToObtain — how to get it
data.api.scopeRequirements.unobtainable object all Scopes this key cannot obtain, and why. Two reasons: a personal webhook key carries no app-context scopes, and some scopes are minted by the platform itself and are not available to a user on any surface
data.api.scopeRequirements.aliases object all Spellings Bitrix24 treats as one scope (task and tasks)
data.accessMode string all Key access mode: READWRITE or READONLY. More — Access mode
data.capabilities object all Matrix of available operations. The top-level keys are groups, and each group holds operation slots. The shape of a slot is described below
data.capabilities.apps object all Operation slots create — create an application, publish — publish it to the catalog, bindPlacements — bind placements. Plus sourceStorage — not an operation but a source-storage settings block with its own field set
data.capabilities.apps.sourceStorage object all Source-storage settings: enabled, requiredBeforeDeploy, automaticOnDeploy, limits.maxBlobBytes, endpoint, mcpToolName, contentTypes, docs. The freshnessWindowMinutes field is added only when the platform checks the snapshot's age before publishing. This block carries no available or reason fields
data.capabilities.servers object all Slots create — create a server, deploy — publish sources, preview — work with access tokens: a preview link and a Bearer token for an end-to-end (E2E) check, wake — wake the server
data.capabilities.agents object all Slot create — create an AI agent
data.capabilities.managedBots object all Slot create — create a managed bot
data.capabilities.aiRouter object all Slots chatCompletions — model calls, byok — working with your own provider key
data.capabilities.<group>.<slot>.available boolean all Whether this key can perform the operation on this Bitrix24 account right now
data.capabilities.<group>.<slot>.reason string all State code of the slot. It arrives both on available: true (COMMERCIAL, TRIAL_ACTIVE) and on a denial — for example SESSION_REQUIRED, WRITE_BLOCKED_READONLY_KEY, BILLING_EXHAUSTED, FEATURE_DISABLED, INFRA_NOT_PERMITTED, SERVER_CREATION_DISABLED, SERVER_CREATION_ADMINS_ONLY, INT_TARIFF_REQUIRED, COMMERCIAL_PLAN_REQUIRED, TRIAL_PORTAL_LIMIT, PLAN_NOT_ALLOWED_ON_TRIAL. On .com, infrastructure and key issuance additionally require a Vibe+ plan (INT_VIBE_PLUS_REQUIRED). The set grows — treat an unknown code as a denial and rely on available
data.capabilities.<group>.<slot>.userMessage string all Ready-made text in the user's language. It arrives on a denial — show it as is
data.capabilities.<group>.<slot>.note string all A condition that available: true does not cover: a Bitrix24-side prerequisite, how much of a limit is already used, or a free-access restriction
data.webResearch.promptForAgents string all A ready-made hint for an agent: how to call research and where to find the provider catalog
data.capabilities.<group>.<slot>.limits object all Limits in force for the slot — for example allowedPlans and maxPortalTotal under free access
data.capabilities.<group>.<slot>.alternatives array all What to do instead of the blocked operation: items with the fields type, description, url or endpoint
data.api object all API usage rules in the _rules array, the entities exposed by the entity API in entityApi, a link to the full reference
data.rateLimit object all Call-rate limits: requestsPerSecond — the Bitrix24 account limit, shared across all of its keys, edgeRequestsPerSecondPerIp — the platform edge limit per client IP address. More — Request limits
data.ai object all AI Router access: default model, available models, catalog size. More — AI Router
data.webSearch object all Web search providers and their cost. More — Provider list
data.webResearch object all Deep research: available, endpoint, providers, defaultProvider, streaming, docs. More — Deep research
data.webResearch.providers[].cost object all Price of one research run with the provider: research — the price in Vibe credits (Ꝟ), currency — the billing unit. For a provider used with your own key, research equals 0
data.storage object all Object storage: usage, pricing, upload endpoints. More — Storage
data.deployment object all Application deployment contract — depends on the target server type. More — Deploy API
data.deployment.primary string all The placement model the platform treats as primary for this account: galaxyApp — an app inside a galaxy, standalone — a dedicated virtual machine
data.deployment.galaxyApp object all The contract for deploying into a galaxy. During trial access, the block arrives only when stored state shows a suitable host. This is an advisory assessment: POST /v1/infra/servers makes the final live-capacity check
data.deployment.placementNote string all Why the galaxy is unavailable and how to deploy in that state. During trial access, the field distinguishes the absence of a host from an existing but unsuitable host. The field is absent when Galaxy mode is disabled, see Galaxy app
data.deployment.limits object all The publication limits in force: the body and archive ceilings, the per-step time budget, the number of log lines, the ceiling on concurrent inline-body publications
data.deployment.limits.uploadInlineMax string all The HTTP body ceiling for a publication with an inline archive, as a string with its unit — for example 96MB. Above it, 413 INLINE_SOURCE_TOO_LARGE arrives. See Deploy
data.deployment.limits.uploadInlineMaxArchive string all The same ceiling expressed as the size of the archive itself — for example 72MB. It is about a third lower than uploadInlineMax: the contents travel as base64 and are heavier than the source bytes. The value comes from the same constant as the refusal, so you do not need to recompute the ceiling yourself
data.deployment.limits.uploadUrlMax string all The ceiling for publishing by link and by a stored version — 500MB. Those paths are streamed and do not fall under the inline body ceiling
data.infra object all Infrastructure: providers, server limit, list of unhealthy servers, servers of other teams the key owner is on. More — Infrastructure
data.infra.collaboratorServers object all Servers where the key owner is on the development team rather than owning them: total — how many memberships there are in total, count — how many rows fit into the response, items — the rows themselves. These servers do not count towards infra.limits — the machines belong to someone else. The same servers arrive in GET /v1/infra/servers carrying the access.via: "collaborator" block
data.infraState object all Whether infrastructure is stopped over an unpaid balance. The strings inside the block are machine-readable; the client writes the human-facing text
data.infraState.frozen boolean all Whether servers, deploys and storage are stopped over an unpaid balance. On true the 402 ACCOUNT_FROZEN refusal arrives on calls paid for from the Vibe credits balance, while requests to your own Bitrix24, AI within the plan's monthly quota and the paid period of a Cowork/Code subscription keep working. Until the narrowed refusal reaches your Bitrix24 account, true means "almost everything is stopped": the self-description, the guide, the spec, four Feedback conversation calls — filing a ticket, listing tickets, reading one ticket and commenting on it — and the revocation of your own Cowork/Code key keep working; everything else answers 402 ACCOUNT_FROZEN. The full list is in Error codes
data.infraState.reason string or null all The stop reason code: DEBT, or null when nothing is stopped
data.infraState.topupUrl string or null all The top-up address for your Vibecode account, or null when there is nothing to top up
data.feedback object all Feedback endpoints and limits. More — Feedback
data.auth object all How to pass the key in a request: headers, and for the authorization key — OAuth authorization steps
data.quickstart object all A short list of first calls for exploring the API
data.b24Credentials object vibe_api_ Whether the key can call Bitrix24: ready. When ready: false it also carries reason, plus paywallCode and upgradeUrl for plan-related reasons. The hint field arrives when the access state is worth re-reading. The block is absent for a key that is not bound to a Bitrix24 account and for a key with no Bitrix24 scopes — the flag does not apply there. The reason values and the action for each — Error codes
data.b24Credentials.ready boolean vibe_api_ true — the key carries credentials for calls to the Bitrix24 account, false — it does not, and any such call returns 401 TOKEN_MISSING
data.docs string all Link to the full API reference — GET /v1/guide
data.errorCodes object all Error response format and a link to the full error code reference
data.changelog object all Link to the API changelog
data.expiresAt string or null vibe_api_ Key expiration date. null — no expiration
data.owner object vibe_api_ Key owner: name, userId
data.portalEmbedding object vibe_api_ The embedding flow through POST /v1/apps → OAuth authorization → POST /v1/apps/:id/publish, plus the personal-key boundaries: it does not call placements/bind directly and is not itself a transparent-auth credential
data.app object vibe_app_ Bound application: title, id
data.currentUser object or null vibe_app_ The Bitrix24 user on whose behalf the request runs. Filled when a session token is passed. Without one it arrives as null
data.placements object vibe_app_ Embedding the application in the Bitrix24 account interface: available and registered placements, endpoints, how incoming requests are handled. More — Embedding an app in the Bitrix24 account
data.placements.bindPrerequisite object vibe_app_ The Bitrix24-side condition without which binding a placement will not succeed. The contents of the block depend on the account type
data.placements.bindPrerequisite.subscriptionRequired boolean vibe_app_ false — a commercial Bitrix24 plan is enough to bind a placement
data.placements.bindPrerequisite.note string vibe_app_ Text describing the condition and how to satisfy it
data.placements.bindPrerequisite.errorCodes array vibe_app_ The codes the bind call returns while the condition is unmet — INT_TARIFF_REQUIRED and BITRIX_UNAVAILABLE. On a self-hosted account, SESSION_REQUIRES_ADMIN is added to the set. Regardless of account type the set also carries PLACEMENT_APP_GRANT_MISSING, PLACEMENT_OPTIONS_REQUIRED and PLACEMENT_NOT_REST_BINDABLE — refusals about a specific placement rather than about account access
data.oauth object vibe_app_ OAuth authorization URL and required parameters
data.oauthTutorial object vibe_app_ Step-by-step OAuth authorization walkthrough
data.eventDelivery object vibe_app_ Receiving Bitrix24 account events on your server without polling
data.schemaDiscovery object vibe_app_ How to read the field schema without a session token

The management key (vibe_live_) returns a different set of blocks — portals, totalAppKeys, a reduced capabilities — and carries no Bitrix24 account data. Description — Management keys.

Response example

Personal key (vibe_api_) — main fields shown:

JSON
{
  "success": true,
  "data": {
    "type": "personal",
    "portal": "mycompany.bitrix24.com",
    "portalId": "8c3d1e04-…",
    "tariff": {
      "code": "en_basic",
      "name": "Basic",
      "isCommercial": true,
      "wasEverCommercial": true,
      "checkedAt": "2026-07-08T08:57:58.270Z",
      "kind": "CLOUD"
    },
    "scopes": ["crm", "task", "tasks", "im", "imbot", "disk", "user"],
    "accessMode": "READWRITE",
    "capabilities": {
      "apps": {
        "create": { "available": true },
        "publish": { "available": true },
        "bindPlacements": { "available": true }
      },
      "servers": {
        "create": { "available": true, "reason": "COMMERCIAL" },
        "deploy": { "available": true, "reason": "COMMERCIAL" },
        "preview": { "available": true },
        "wake": { "available": true }
      },
      "agents": {
        "create": {
          "available": true,
          "reason": "COMMERCIAL",
          "note": "Agent servers count toward the portal's infrastructure limit (currently 2/10)."
        }
      },
      "managedBots": {
        "create": {
          "available": true,
          "reason": "COMMERCIAL",
          "note": "Managed bot servers count toward the portal infrastructure limit."
        }
      },
      "aiRouter": {
        "chatCompletions": { "available": true },
        "byok": { "available": true }
      }
    },
    "owner": { "name": "John Brown", "userId": "1" },
    "expiresAt": null
  }
}

The apps.publish and apps.bindPlacements slots always carry a note — it is omitted from the example above, but the endpoint returns the full text.

Authorization key (vibe_app_) without a session token — showing the blocks a personal key does not have:

JSON
{
  "success": true,
  "data": {
    "type": "oauth_app",
    "portal": "mycompany.bitrix24.com",
    "portalId": "8c3d1e04-…",
    "accessMode": "READWRITE",
    "app": { "title": "CRM Dashboard", "id": "f2342f7a-…" },
    "currentUser": null,
    "placements": {
      "available": true,
      "registered": ["LEFT_MENU"],
      "endpoints": [
        "POST https://vibecode.bitrix24.com/v1/placements/bind",
        "POST https://vibecode.bitrix24.com/v1/placements/unbind",
        "GET https://vibecode.bitrix24.com/v1/placements",
        "GET https://vibecode.bitrix24.com/v1/placements/available"
      ],
      "bindPrerequisite": {
        "subscriptionRequired": false,
        "note": "Binding a placement requires a Bitrix24-side prerequisite: the portal must be on a commercial Bitrix24 plan…",
        "errorCodes": [
          "INT_TARIFF_REQUIRED",
          "BITRIX_UNAVAILABLE"
        ]
      }
    }
  }
}

oauth.authorizeUrl is a template, not a ready-made link. The /v1/oauth/authorize endpoint requires the state parameter (16–512 characters) — a CSRF token per RFC 6749 §10.12 that the client generates: create a cryptographically random string, add it to the URL, and verify the value returned in the callback. The server cannot generate state for you — otherwise CSRF protection does not work. Opening authorizeUrl as is returns 400 INVALID_REQUEST "state: Required". Optionally add redirect_uri (your callback address — without it the built-in /oauth/complete page is used) and scope. Full-link example:

https://vibecode.bitrix24.com/v1/oauth/authorize?app_key=vibe_app_…&state=aAbBcCdDeEfFgGhH&redirect_uri=https://myapp.com/callback

Error response example

401 — invalid key:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "Invalid API key"
  }
}

Errors

HTTP Code Description
401 MISSING_API_KEY The X-Api-Key header is missing
401 INVALID_API_KEY The key was not found
401 KEY_INACTIVE The key is revoked
401 KEY_EXPIRED The key has expired
401 KEY_NOT_FOUND The key was deleted while the request was being processed
403 IP_NOT_ALLOWED Request from an address outside the allowed IP list

Full list of common API errors — Errors.

Known specifics

?refresh=tariff checks the plan no more than once per minute. The parameter forces a live check of the Bitrix24 account plan and resets the response cache. If the previous check was less than a minute ago, the request returns the already known value without a new check. For a management key the parameter does nothing — such a key is not bound to a Bitrix24 account.

The response is cached server-side for about 30 seconds. A change of scopes or access mode is reflected in the response immediately. The plan, balance and infrastructure state are updated on the first read after the cache expires. A request with ?refresh=tariff resets the cache, and the next read without this parameter returns an up-to-date plan.

For a key in read-only mode, nine capabilities slots come back closed. They are apps.publish, apps.bindPlacements, servers.create, servers.deploy, servers.wake, agents.create, managedBots.create and both aiRouter operations — all nine return available: false and reason: "WRITE_BLOCKED_READONLY_KEY". For a read-only key the response root also carries writeRestriction — the WRITE_BLOCKED_READONLY_KEY code, the scope it applies to, and a link to the access-mode page. The field is present only while the restriction is in force: a platform administrator may lift it, and then the field disappears from the response along with the restriction itself. Inside the field an exceptions list names the routes that check the mode themselves and therefore partly succeed; today that is POST /v1/apps, where a read-only key creates an application in the same mode, plus two non-GET addresses that are not writes: DELETE /v1/cowork/key (emergency key revocation) and DELETE /v1/infra/servers/{id}/lock (releasing a stuck lock, pointed at by the recoveryAction field of an EXEC_BUSY response). A management key carries the field too, but nothing lifts it there: the write block for such keys is unconditional. The field exists because the response names writing endpoints in some thirty places (storage, feedback, source-storage and cowork hints): those are addresses, not permissions. Per-operation availability is in capabilities.

apps.create does NOT come back closed: such a key can create an application in READONLY mode, and the ban on READWRITE is spelled out in that slot's note field. Reads are not affected by the mode — servers.preview, for one. More — Access mode.

The plan name is for display, not for comparison. The data.tariff.name field is assembled at read time and can change without the plan itself changing. The platform picks it in this order. If the plan code is known to the edition catalog — from there, in English. Otherwise the license name as Bitrix24 reported it, in the account's language. Otherwise the previously stored name. Otherwise null. Three things follow. First, null is a normal value, not an error. Second, the name does not depend on who asks — neither Accept-Language nor the key owner's interface language changes it. Third, the plan code is never substituted for the name — when there is no name, you get null, not pro100. Branch your logic on data.tariff.code, isCommercial, and kind. The labels of known editions have also been refined — three of them: the demo edition is now Trial period, Project is now Project — legacy free, and NFR is now NFR — partner licence.

The wasEverCommercial flag is not one-way. A plan downgrade does not withdraw trust: the switch to a free plan does not clear the value by itself. Yet the flag is not one-way — the platform brings it in line with the facts when no grounds for it are found, and that has already happened on both cloud and self-hosted portals. Do not build logic on this field that assumes the transition can only go one way — check capabilities in the same response instead.

The downward correction does not reach every account. The flag is kept when the account has a completed payment behind it, when it moved from a trial period to a paid plan, or when the license region of a self-hosted account could not be determined. That last case is not a failure — trust is not withdrawn over a state that was not read in full. See Connecting a self-hosted Bitrix24.

Determine the placement model from the deployment block, not from the account plan. On the free Bitrix24 plan a new galaxy is not created. When Galaxy mode is enabled but there is no host, deployment.galaxyApp is absent, deployment.primary is standalone, and deployment.placementNote describes the two-step path. It is available only while capabilities.servers.create.available in the same response is true; select an allowed plan ID from capabilities.servers.create.limits.allowedPlans. When Galaxy mode is disabled, placementNote is absent, a one-shot request carrying source returns 400 SOURCE_AT_CREATE_GALAXY_ONLY, and the same capabilities slot decides whether the two-step path is available. When an existing host passes the advisory stored-state check, the galaxyApp block is present and a one-shot create carrying source is worth trying. This is not a guarantee: only POST /v1/infra/servers checks live capacity.

When an existing host fails the advisory check, the galaxyApp block is absent. While capabilities.servers.create.available is false, placementNote rules out a two-step dedicated-machine create: with trial enforcement active, the occupied slot returns 402 TRIAL_PORTAL_LIMIT. To retry one-shot creation, wait for the host to recover, ask an administrator to repair it, or upgrade the plan. After removing the host, re-read GET /v1/me and use the two-step path advertised there. Follow the hint in the actual POST response. The call sequence — Create a server and Deploy API.

Without a key in a browser the endpoint returns HTML. A GET /v1/me request without the X-Api-Key header and with the Accept: text/html header returns a stub page with status 200, not JSON. A request with a key or without text/html in the Accept header always gets the JSON self-description.

Scope requirements map

Until now the only way to learn a key's boundary was to make the call: the request went out and came back with a 403 SCOPE_DENIED refusal naming the missing scope. The list of available entities showed only what was open, while what was closed was simply absent — and absence alone could not distinguish "no such entity in the product" from "it exists but your key cannot reach it".

The data.api.scopeRequirements block answers that before the call:

JSON
{
  "granted": { "bitrix24": ["imbot"], "platform": ["vibe:ai", "vibe:search"] },
  "missing": {
    "bitrix24": {
      "crm": {
        "entities": ["deals", "contacts", "companies", "leads"],
        "unlocks": ["/v1/duplicates/find", "/v1/addresses"],
        "unlocksRemaining": 41,
        "truncated": true,
        "howToObtain": "reissue-key"
      }
    },
    "platform": {}
  }
}

Bitrix24 binds its scopes to a key when the key is issued, so their howToObtain is reissue-key: adding a scope in the settings of an already-issued key is not enough; the key has to be reissued. Vibecode scopes are edited in your Vibecode account.

The map describes the platform-side scope check only. It does not promise the call will succeed. A scope granted in your Vibecode account after the key was issued shows up in the map, but Bitrix24 does not honour it and answers BITRIX_ACCESS_DENIED. Refusals by key kind, ownership, read-only mode, account freeze and plan are separate axes and are not described in the map. The _note field inside the block carries the same warning.

Path coverage is not complete yet, and the map says so itself. A coverage.paths value of partial means some custom routes still lack a machine-checked verdict, so unlocks and unlocksRemaining under-report. Absence of a path from the list does NOT prove the path is ungated: if a call still answers with a scope refusal, trust the refusal, not the map. The entity list is always complete.

The refusal has not changed: a call without the required scope still returns 403 SCOPE_DENIED naming that scope. The map is a pre-flight check, not a replacement for the refusal.

See also