Bitrix + Kontur.Elba Integration: Automated Invoicing
Elba is a cloud service for tax accounting for sole proprietors on the simplified tax system and patent. Unlike MoeDelo and Kontur.Accounting, Elba is tailored for micro-businesses with simplified operations. Elba's API provides access to documents (invoices, acts) and counterparties, but not payment management. This defines the possibilities and limitations of integration with Bitrix.
We are a team with 10 years of experience in 1C-Bitrix development and certified "1C-Bitrix" specialists. Our integration solves the problem of automatic invoicing and acts from online store orders directly to Elba. Order a turnkey integration—we will take into account all the specifics of your business.
Problems We Solve
Manual invoice entry. Without integration, a manager manually copies data from Bitrix to Elba—errors, delays, lost customers. Our solution eliminates the human factor, saving up to 15 hours per week on data entry.
OAuth 2.0 without errors. Incorrect token caching leads to API blocks. We implement a correct Client Credentials flow with proactive refresh.
Elba API limitations. No payment API and request limits—we offer workarounds: webhooks from payment systems, a queue via Bitrix agents. This allows us to handle up to 1000 orders per day without blocks.
How to Set Up OAuth 2.0 for Elba
Authorization is performed using the OAuth 2.0 protocol (Client Credentials). For server integration, it is enough to obtain client_id and client_secret from the Elba dashboard.
class ElbaOAuthService
{
private string $clientId;
private string $clientSecret;
private string $redirectUri;
private string $tokenUrl = 'https://auth.kontur.ru/connect/token';
public function getClientCredentialsToken(): string
{
// For server integration — Client Credentials flow
$ch = curl_init($this->tokenUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'grant_type' => 'client_credentials',
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'scope' => 'elba.api',
]),
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
// Cache the token for (expires_in - 60) seconds
$this->cacheToken($response['access_token'], $response['expires_in'] - 60);
return $response['access_token'];
}
}
Elba API Client in PHP
class ElbaApiClient
{
private ElbaOAuthService $auth;
private string $baseUrl = 'https://api.e-kontur.ru/api/v1';
public function request(string $method, string $path, array $data = []): array
{
$token = $this->auth->getCachedToken();
$ch = curl_init($this->baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"Authorization: Bearer {$token}",
],
CURLOPT_POSTFIELDS => in_array($method, ['POST', 'PUT'])
? json_encode($data) : null,
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
throw new \RuntimeException("Elba API error {$httpCode}: {$json}");
}
return json_decode($json, true) ?? [];
}
}
How to Automatically Issue Invoices from Bitrix?
The main scenario: when an order is created, we automatically generate an invoice in Elba and send it to the customer by email. To do this, we first find or create a counterparty by INN, then form an array of product items.
public function findOrCreateCounterparty(\Bitrix\Sale\Order $order): string
{
$props = $order->getPropertyCollection();
$inn = $props->getItemByOrderPropertyCode('INN')?->getValue();
$email = $props->getUserEmail();
if ($inn) {
// Search by INN
$list = $this->client->request('GET', '/counterparties?inn=' . urlencode($inn));
if (!empty($list)) {
return $list[0]['id'];
}
}
// Create counterparty
$isLegal = !empty($inn);
$payload = $isLegal ? [
'fullName' => $props->getItemByOrderPropertyCode('COMPANY')?->getValue() ?? '',
'inn' => $inn,
'kpp' => $props->getItemByOrderPropertyCode('KPP')?->getValue() ?? '',
'email' => $email,
] : [
'fullName' => $props->getBuyerName(),
'email' => $email,
'type' => 'individual',
];
$created = $this->client->request('POST', '/counterparties', $payload);
return $created['id'];
}
public function createInvoiceForOrder(\Bitrix\Sale\Order $order): array
{
$counterpartyId = $this->findOrCreateCounterparty($order);
$items = [];
foreach ($order->getBasket() as $item) {
$items[] = [
'name' => $item->getField('NAME'),
'count' => $item->getQuantity(),
'price' => $item->getPrice(),
'unit' => 'pcs.',
'ndsRate' => 'NoNds', // USN — no VAT. Options: Nds0, Nds10, Nds20
];
}
// Delivery as a separate item
$deliveryPrice = $order->getField('PRICE_DELIVERY');
if ($deliveryPrice > 0) {
$items[] = [
'name' => 'Delivery',
'count' => 1,
'price' => $deliveryPrice,
'unit' => 'service',
'ndsRate' => 'NoNds',
];
}
$invoice = $this->client->request('POST', '/invoices', [
'number' => $order->getField('ACCOUNT_NUMBER'),
'date' => date('Y-m-d'),
'counterpartyId' => $counterpartyId,
'items' => $items,
'comment' => 'Order from website #' . $order->getField('ACCOUNT_NUMBER'),
'paymentDueDate' => date('Y-m-d', strtotime('+3 days')),
]);
return $invoice;
}
What Limitations Does the Elba API Have and How to Work Around Them?
No API for payment registration. When an order is paid in Bitrix, you cannot automatically mark the invoice as paid in Elba through the API. Workaround: webhook from payment systems → email notification to the accountant with the invoice number. Or use Elba's bank integration—when money arrives in the account, Elba itself matches the payment with the issued invoice.
API limits. The Elba API has request rate limits. For a store with a large number of orders—a send queue via \Bitrix\Main\Agent or a separate worker.
Only invoices and acts, not waybills. For goods shipment, an act document is not entirely legally correct. For sole proprietors on USN, this is usually not critical, but for LLCs—consider Kontur.Accounting.
Act of Completed Work for Services
For services (not goods), we generate an act instead of an invoice:
public function createActForOrder(\Bitrix\Sale\Order $order, string $counterpartyId): array
{
// Similar items structure
return $this->client->request('POST', '/acts', [
'date' => date('Y-m-d'),
'counterpartyId' => $counterpartyId,
'items' => $this->buildItems($order),
'comment' => 'Services for order #' . $order->getField('ACCOUNT_NUMBER'),
]);
}
Service Comparison
| Criterion | Elba (SKB Kontur) | Kontur.Accounting | MoeDelo |
|---|---|---|---|
| Orientation | Sole proprietors on USN, patent | Sole proprietors and LLCs, any regime | Sole proprietors and LLCs |
| API for invoices | Yes | Yes | Yes |
| API for payments | No | Yes | Yes |
| Waybill support | No | Yes | Yes |
| Cost | Low | Medium | Medium |
Elba is better for micro-businesses, but it falls short of Kontur.Accounting in functionality—the latter has payment and waybill APIs.
Field Mapping: Bitrix → Elba
| Bitrix Field | Elba Field (counterparty/invoice) |
|---|---|
| Order property INN | counterparty.inn |
| Company name (COMPANY) | counterparty.fullName |
| Customer email | counterparty.email |
| Product name (Basket.NAME) | invoice.items[].name |
| Quantity (Basket.QUANTITY) | invoice.items[].count |
| Price (Basket.PRICE) | invoice.items[].price |
| Delivery cost | invoice.items (separate item) |
Typical Integration Errors
- Token expiration during a long session—solved by caching with a margin.
- Incorrect scope when requesting a token—use
elba.api. - Error 400 when creating a counterparty—possibly missing INN or email.
- Exceeding request limits—add a queue via
CAgent.
What Is Included in the Work
We provide a ready-made turnkey solution:
- OAuth 2.0 integration with token caching
- PHP client for the Elba API
- Counterparty search and creation
- Automatic invoice generation on order creation
- Error handling, logging, retries
- Documentation and staff training
- 3-month warranty on correct operation
Work Process
- Analysis—we study your document flow, identify integration points.
- Design—we develop the architecture, agree on the stack (PHP version, Bitrix).
- Development—we write code, configure agents, test on a staging environment.
- Testing—we check the full cycle: order → invoice → payment → notification.
- Deployment—we roll out to the production server, monitor the first days.
Timelines and Cost
Timelines: from 2 to 4 weeks depending on complexity (availability of atypical fields, non-standard payment scenarios).
Integration typically pays for itself within 3 months due to manager time savings. Get a consultation from an engineer—we will calculate the exact cost and timeline for your project.
Official Elba API documentation is available at https://api.e-kontur.ru.







