Configuring Vue.js Integration with the 1C-Bitrix REST API
Bitrix provides several mechanisms for working with data from Vue: the built-in REST API (/bitrix/rest/), ORM methods via AJAX controllers (Bitrix\Main\Engine\Controller), and direct AJAX requests to component handlers. The choice of mechanism affects performance, security, and code volume. Let's walk through each approach with practical examples.
Bitrix Built-in REST API
Available at /rest/ for cloud Bitrix24, and requires configuration for the on-premise ("box") version. Methods include sale.basket.getlist, catalog.product.list, crm.deal.list, and others. Authentication is via OAuth 2.0 or webhooks (webhook URL with a token).
For a public API on a website (not Bitrix24) — webhooks with limited permissions:
const BX_WEBHOOK = window.BX_STATE.webhook; // passed from PHP
async function getProducts(filter) {
const res = await fetch(`${BX_WEBHOOK}catalog.product.list`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ filter, select: ['ID', 'NAME', 'PRICE'] }),
});
return res.json();
}
Limitations of the built-in REST: request rate limits (50 per second for cloud), not all entities are available, arbitrary database queries cannot be executed.
Custom Controllers via Engine\Controller
For on-premise Bitrix projects — this is the primary approach. The controller lives in a custom module:
// local/modules/project.api/lib/controller/product.php
namespace Project\Api\Controller;
use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Engine\ActionFilter;
class Product extends Controller
{
public function configureActions(): array
{
return [
'list' => [
'prefilters' => [new ActionFilter\Authentication()],
],
];
}
public function listAction(int $categoryId, int $page = 1): array
{
$pageSize = 20;
$res = \CIBlockElement::GetList(
['SORT' => 'ASC'],
['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'SECTION_ID' => $categoryId, 'ACTIVE' => 'Y'],
false,
['nPageSize' => $pageSize, 'iNumPage' => $page],
['ID', 'NAME', 'DETAIL_PICTURE', 'PROPERTY_PRICE']
);
$items = [];
while ($item = $res->GetNext()) {
$items[] = $item;
}
return ['items' => $items, 'page' => $page];
}
}
Controller URL: /bitrix/services/main/ajax.php?action=project:api.product.list. Automatically adds CSRF protection for POST requests.
Axios in Vue: A Unified API Service
// services/api.js
import axios from 'axios';
const api = axios.create({
baseURL: '/bitrix/services/main/ajax.php',
headers: { 'X-Requested-With': 'XMLHttpRequest' },
});
// Automatically append CSRF token
api.interceptors.request.use(config => {
if (config.method === 'post') {
config.data = { ...config.data, sessid: window.BX.bitrix_sessid() };
}
return config;
});
// Handle 401 — redirect to login
api.interceptors.response.use(
res => res.data,
err => {
if (err.response?.status === 401) {
window.location.href = '/auth/?backurl=' + encodeURIComponent(location.pathname);
}
return Promise.reject(err);
}
);
export const getProducts = (categoryId, page) =>
api.post('', { action: 'project:api.product.list', categoryId, page });
All Vue components use functions from services/api.js — they never call fetch directly. Changing the URL or authentication mechanism requires editing only one file.
Composable for Data Fetching
// composables/useProducts.js
export function useProducts(categoryId) {
const items = ref([]);
const loading = ref(false);
const error = ref(null);
const page = ref(1);
async function load() {
loading.value = true;
error.value = null;
try {
const data = await getProducts(categoryId.value, page.value);
items.value = page.value === 1 ? data.items : [...items.value, ...data.items];
} catch (e) {
error.value = e.message;
} finally {
loading.value = false;
}
}
watch(categoryId, () => { page.value = 1; load(); }, { immediate: true });
return { items, loading, error, page, loadMore: () => { page.value++; load(); } };
}
The composable encapsulates loading logic; the component works only with reactive data.
CORS and Security Policy
For an SPA on a separate subdomain (app.example.com) calling an API on (example.com), CORS must be configured in PHP:
// at the top of the controller or in the OnPageStart event
header('Access-Control-Allow-Origin: https://app.example.com');
header('Access-Control-Allow-Credentials: true');
The Bitrix cookie session is sent with withCredentials: true in axios — the authentication session works cross-domain.
Typical timeline: setting up an API service with 3–5 methods, axios with interceptors, and basic composables — 2–3 working days. Developing a full REST API for catalog + cart + authentication — 1–2 weeks.







