Developing 1C-Bitrix Integrations via REST API
1C-Bitrix provides its own REST API through the bitrix.rest module (starting from version 14.0). This is not merely a set of endpoints — it is a complete framework for building applications and integrations, with OAuth 2.0 authentication, an event system, and webhooks.
Types of REST Applications in 1C-Bitrix
Local application — installed on a specific Bitrix24 portal, not published to the marketplace. Created under Applications → Developers → Other → Local Application. Simpler to configure, no review process required.
Inbound webhook — a simplified variant: a fixed token bound to a specific user. Suitable for server-to-server integrations that do not require user-facing OAuth.
OAuth application — a full application with user authorisation via OAuth 2.0. Required when the application serves multiple portals.
Creating a REST API for 1C-Bitrix as a Data Source
The standard bitrix.rest module exposes 1C-Bitrix data to external systems. Sometimes the reverse is needed: creating a REST API for 1C-Bitrix data that an external system will call.
Use the main module and Bitrix D7 routing:
// In a module or init.php — register the handler
use Bitrix\Main\Routing\Controllers\PublicPageController;
$app = \Bitrix\Main\Application::getInstance();
$app->getRouter()->add(
'GET', '/api/v1/products/{id}',
function(\Bitrix\Main\HttpRequest $request, int $id) {
// Validate API key
$apiKey = $request->getHeader('X-API-Key');
if (!validateApiKey($apiKey)) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
die();
}
$element = \CIBlockElement::GetByID($id)->GetNext();
header('Content-Type: application/json');
echo json_encode(['product' => $element]);
die();
}
);
API Versioning and Documentation
For long-lived integrations, version the API in the URL (/api/v1/, /api/v2/). Changes in v2 do not break clients on v1. Documentation is generated via OpenAPI/Swagger: a YAML schema file published at /api/docs.
Handling Large Data Volumes
Pagination is mandatory for methods that return lists:
// Standard pagination for a catalogue REST method
function getProductsList(int $page = 1, int $limit = 50): array {
$offset = ($page - 1) * $limit;
$result = \CIBlockElement::GetList(
['ID' => 'ASC'],
['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'],
false,
['nTopCount' => $limit, 'iNumPage' => $page],
['ID', 'NAME', 'DETAIL_TEXT', 'PREVIEW_PICTURE', 'PROPERTY_*']
);
$items = [];
while ($item = $result->GetNext()) {
$items[] = $item;
}
$total = \CIBlockElement::GetList(
[], ['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'], []
);
return [
'items' => $items,
'pagination' => [
'page' => $page,
'limit' => $limit,
'total' => $total,
'pages' => ceil($total / $limit),
],
];
}
Authentication and Security
For machine-to-machine integrations (external system → 1C-Bitrix), use API keys stored in b_option. Rotate keys every 90 days. All requests must enforce:
- HTTPS — all integrations over TLS 1.2+ only.
- IP-based restrictions in nginx:
allow 192.168.1.0/24; deny all;for endpoints called only from the corporate network. - Rate limiting:
limit_req_zonein nginx, 100 requests/minute per IP.
Response Caching
A REST API without caching hits the database on every request. Use \Bitrix\Main\Data\Cache:
$cache = \Bitrix\Main\Data\Cache::createInstance();
$cacheKey = 'product_' . $productId . '_' . LANGUAGE_ID;
if ($cache->initCache(1800, $cacheKey, '/api/products/')) {
return $cache->getVars();
}
$cache->startDataCache();
$data = fetchProductData($productId);
$cache->endDataCache($data);
return $data;
A 30-minute TTL for the catalogue is a reasonable balance between data freshness and database load.
| Task | Effort |
|---|---|
| API schema design and documentation | 4–8 h |
| CRUD method implementation (per entity) | 4–6 h |
| Authentication and security | 4–6 h |
| Pagination, filtering, caching | 4–6 h |
| Tests and integration documentation | 6–8 h |







