Configuring Vue.js interaction with the 1C-Bitrix REST API

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    745
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

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.