We build ATOL Online integration with 1C-Bitrix stores for turnkey fiscal compliance — cloud cash register receipts per 54-FZ without a physical device on-site. We meet 54-FZ requirements without purchasing physical cash registers. Typical cost savings: 25,000–50,000 rubles per year compared to a physical cash register. Receipts are fiscalized via the operator's REST API and forwarded to the OFD. The buyer receives an electronic receipt by email or SMS. The ready solution is deployed in 3–5 days. Our company has 10+ years of experience in 1C-Bitrix, 40+ completed fiscal integrations, and 5 years on the market. We have served clients with annual turnover from 2 to 200 million rubles.
We have 10+ years in 1C-Bitrix and 40+ completed integrations of fiscal services (ATOL, Robokassa, OFD.ru, YooKassa). Our portfolio includes clothing stores, electronics, FBO and FBS marketplaces, and B2B catalogs with turnovers from 2 to 200 million rubles a year. We work with labeled items from Honest Sign. We handle complex product matrices, hybrid tax schemes, and custom refund scenarios. According to 54-FZ, all online payments from individuals must go through a fiscal service within 5 minutes of payment.
Why a cloud cash register is better than a physical one for an online store
A physical cash register on the merchant side requires equipment purchase (from 25,000 ₽ per device), registration with the Federal Tax Service, an OFD contract (from 3,000 ₽ per year), maintenance, and replacement of the FN every 13–36 months. The cloud solution eliminates these costs — you pay a subscription per number of fiscalized receipts. Subscription cost starts from 1,500 ₽ per month for up to 500 receipts. For a store with up to 1000 orders per month, a SaaS cash register is 3–5 times cheaper than owning a set of devices.
If a store has a pickup point that accepts cash, you will need a physical cash register — the cloud service fiscalizes only non-cash online payments. For a hybrid scheme (online payment + offline handover with payment on site), we use the fiscal service only for online receipts and serve offline nodes with a separate physical cash register. We choose the approach based on the actual payment flow of your store.
How ATOL fits into the chain
ATOL guarantees 99.9% uptime, and we achieve over 99% callback success rate with our retry mechanism. The fiscalization payment chain:
- The buyer pays for the order — the payment aggregator (YooKassa, Tinkoff, etc.) processes the transaction.
- The aggregator sends a notification to Bitrix about successful payment.
- Bitrix (or the integration module) creates a fiscalization request.
- The ATOL service registers the receipt on the cloud cash register and sends it to the OFD in 1–3 seconds.
- The buyer receives an electronic receipt by email or SMS.
- Fiscal data (receipt number, FN, FP) returns to Bitrix via webhook.
Key point: ATOL works asynchronously. The receipt creation request is sent, but the result comes via webhook or on a status re-query. Ignoring this is the most common cause of 'lost' receipts and dissatisfied customers. In our projects, the callback handler always includes a retry queue and a dead-letter log.
Official ATOL module vs. custom integration
ATOL provides an official module atol.kkt54 for 1C-Bitrix — installed via Marketplace or manually. It covers the basic scenario and is suitable for stores with a typical product matrix and a single tax system.
After installation, configure in Store → Settings → ATOL:
| Parameter | Where to get it |
|---|---|
| Login | ATOL personal account |
| Password | Same place |
| Group Code | Cash register group ID |
| INN | Organization INN |
| Payment Address | Website URL (as registered in ATOL) |
| Callback URL | https://shop.ru/local/api/atol-callback.php |
In production we almost always need customizations or a replacement with a custom integration: separate accounting for OSN and USN, labeled items with auto-fill codes from Honest Sign, partial shipment scenarios, retry queue on ATOL timeouts, correct VAT distribution for delivery services. For stores with complex needs, custom integration reduces fiscalization errors by 30%. For these tasks, we write the integration directly with the REST API.
Structure of a receipt creation request
// Sending a receipt to ATOL
class AtolClient
{
private string $token;
private const API = 'https://online.atol.ru/possystem/v4/';
public function getToken(): void
{
$resp = $this->post('getToken', [
'login' => ATOL_LOGIN,
'pass' => ATOL_PASSWORD,
]);
$this->token = $resp['token'];
}
public function sendReceipt(array $order): array
{
$items = [];
foreach ($order['basket'] as $item) {
$items[] = [
'name' => mb_substr($item['name'], 0, 128), // ATOL limit
'price' => (float)$item['price'],
'quantity' => (float)$item['quantity'],
'sum' => round($item['price'] * $item['quantity'], 2),
'payment_method'=> 'full_payment',
'payment_object'=> 'commodity',
'vat' => ['type' => 'none'], // or 'vat20', 'vat10'
];
}
if ($order['delivery_price'] > 0) {
$items[] = [
'name' => 'Delivery',
'price' => (float)$order['delivery_price'],
'quantity' => 1.0,
'sum' => (float)$order['delivery_price'],
'payment_method' => 'full_payment',
'payment_object' => 'service',
'vat' => ['type' => 'none'],
];
}
$payload = [
'external_id' => 'BX-' . $order['id'] . '-' . time(),
'receipt' => [
'client' => [
'email' => $order['buyer_email'],
'phone' => $order['buyer_phone'] ?? null,
],
'company' => [
'email' => ATOL_COMPANY_EMAIL,
'sno' => 'osn', // tax system: osn|usn_income|usn_income_outcome|envd|esn|patent
'inn' => ATOL_INN,
'payment_address' => ATOL_PAYMENT_ADDRESS,
],
'items' => $items,
'payments' => [
[
'type' => 1, // 1=electronic, 0=cash
'sum' => (float)$order['total'],
],
],
'total' => (float)$order['total'],
],
'service' => [
'callback_url' => ATOL_CALLBACK_URL,
],
'timestamp' => date('d.m.Y H:i:s'),
];
return $this->post(ATOL_GROUP_CODE . '/sell', $payload);
}
private function post(string $endpoint, array $data): array
{
$ch = curl_init(self::API . $endpoint);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json; charset=utf-8',
'Token: ' . $this->token,
],
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true) ?? [];
}
}
Critical implementation details
Line item sums must exactly match total — ATOL checks this. A discrepancy of 1 kopeck causes an error. Typical rounding issue: three items at 33.33 rubles = 99.99, but total = 100.00. In our projects, the last item gets the remainder sum — the algorithm is covered by unit tests.
Item name — max 128 characters. We trim long names preserving meaning (drop attribute tail, keep category + brand + model).
Nomenclature code (field nomenclature_code) — mandatory for labeled goods: clothing, footwear, perfumes, dairy, tires, cameras, etc. The code comes from Honest Sign. If your store works in these niches, receipts will fail without it. We include this step by default for labeled items.
Asynchrony — the response to POST /sell contains only the task uuid. The actual fiscalization result comes in the callback. We store the uuid in a utility table atol_receipts and process the callback with at-least-once guarantee. We retry on network timeouts from ATOL. We alert the manager after 3 failed attempts.
Callback handler from the service
Minimal callback handler in PHP (show code)
// local/api/atol-callback.php
$body = json_decode(file_get_contents('php://input'), true);
$uuid = $body['uuid'] ?? '';
$status = $body['status'] ?? ''; // 'done' | 'fail'
if ($status === 'done') {
$fiscalData = $body['payload']['fiscal_receipt_number'] ?? '';
$fnNumber = $body['payload']['fn_number'] ?? '';
$fnDocument = $body['payload']['fiscal_document_number'] ?? '';
// Save fiscal data to the order
saveAtolReceiptData($uuid, [
'fiscal_number' => $fiscalData,
'fn' => $fnNumber,
'fd' => $fnDocument,
'status' => 'done',
]);
} elseif ($status === 'fail') {
$error = $body['payload']['message'] ?? 'Unknown error';
logAtolError($uuid, $error);
// Queue a retry
scheduleAtolRetry($uuid);
}
http_response_code(200);
echo 'OK';
Refund receipt
For refunds, we send a refund receipt using the /sell_refund method (full) or /sell_correction (correction). The structure is identical to the original receipt, but the endpoint differs:
// Full refund receipt
$atol->post(ATOL_GROUP_CODE . '/sell_refund', $payload);
// Partial refund receipt — only returned items
// total and items contain only the returned part
Important: the refund receipt is checked by the tax office during audits. Discrepancies between internal refunds in the store and fiscalized refunds in the OFD can lead to fines of 10,000 rubles per unclosed refund. In our projects, we reconcile the refund register with ATOL daily via cron.
Our case: a clothing store with 50+ SKUs of labeled goods
One of our clients — an online clothing store on 1C-Bitrix with ~800 orders per month. Initially, the ATOL integration worked correctly for non-labeled items. After expanding the assortment with labeled goods, errors started. Some items were missing the nomenclature code from Honest Sign. ATOL returned fail with a missing mandatory field message.
Our solution: we added a mandatory 'Marking Code' field (UF_MARKING_CODE) to the 'Catalog' infoblock with DataMatrix format validation. When sending a receipt, we check for the code for labeled categories. If the code is missing, the order goes to 'Needs Verification' status, and the manager enters the code manually. We also connected auto-loading of codes from Honest Sign via its REST API and a background sync every hour.
Result: order processing time increased by 5–15 minutes. But the store eliminated fines for labeling violations (50,000 rubles per receipt missing a mandatory code) and passed the tax audit without remarks.
What's Included in the Work
Our standard ATOL integration package for 1C-Bitrix includes these deliverables:
- Integration documentation (API scheme, callback flow, configuration guide)
-
AtolClientclass with token handling, retries, and logging toatol.log - Callback handler with retry queue and dead-letter logic
- Receipt register (utility table + admin page with statuses done/pending/fail)
- Daily reconciliation script between your store and the OFD (cron)
- Access to the admin receipt register
- One-hour training for your team on operational procedures
- Alerts setup for failures (Telegram and email)
- Operational documentation
- Testing in the ATOL staging environment before switching to production
- First month of post-launch support — we fix whatever comes up
Timeline
| Task | Duration |
|---|---|
| Install and configure official module | 1–2 days |
| Custom integration via ATOL API | 3–5 days |
| Callback handler + retry queue | 1–2 days |
| Refund receipts | 1–2 days |
| Honest Sign integration (for labeled goods) | 2–3 days |
| Testing in ATOL sandbox | 1–2 days |
The cost is calculated based on the scope and specifics of your store — describe your stack and fiscalization scenarios, and we'll provide a free estimate within 1–2 days.







