Imagine: every order from your Bitrix online store needs to be manually entered into MoeDelo — as a sales, create a counterparty, issue an invoice. This takes 10–15 minutes per order. With 50 orders per day, that's up to 12 hours of routine per month. Errors in details, incorrect VAT, missed payments — typical consequences. We automate this process turnkey, reducing processing time by 80% and minimizing errors. For a store with 200 orders per month, this saves approximately $300–$500 monthly on manual labor. Our experience with MoeDelo integrations spans over 15 projects, guaranteeing stable 24/7 synchronization. We'll assess your project for free — just contact us.
What Problems We Solve
Manual Counterparty Entry
Each new customer requires creating a card in MoeDelo: TIN, name, address. With repeat orders, duplicates easily appear. Our algorithm automatically searches for a counterparty by email or TIN and creates one only if not found.
VAT Calculation Errors
VAT rates vary: 0%, 10%, 20%. Manual transfer leads to mistakes, causing discrepancies with tax authorities. The integration takes the rate from the product properties in Bitrix — eliminating human error.
Lost Payments
A paid order is not always reflected in MoeDelo as a receipt. We hook into the OnSalePaymentPaid event — payment is automatically recorded as an incoming payment. This is especially important for 54-FZ and shift closure.
How to Integrate Bitrix with MoeDelo?
We use the public MoeDelo API with token-based authorization. On the Bitrix side, we write a PHP client (8.1+), use infoblocks v2.0 and ORM. Each order goes through the chain: counterparty → sales document → invoice (optional) → payment. For returns, we create a return document.
Here is an example of creating a counterparty (code snippet):
class MoeDeloClient
{
private string $apiKey;
private string $baseUrl = 'https://api.moedelo.org';
public function request(string $method, string $endpoint, array $body = [], array $query = []): array
{
$url = $this->baseUrl . $endpoint;
if ($query) {
$url .= '?' . http_build_query($query);
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"X-DM-Auth-Token: {$this->apiKey}",
],
CURLOPT_POSTFIELDS => in_array($method, ['POST', 'PUT', 'PATCH'])
? json_encode($body) : null,
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 400) {
throw new \RuntimeException("MoeDelo API {$httpCode}: {$json}");
}
return json_decode($json, true) ?? [];
}
}
Counterparties
For individuals (B2C orders without details), we create a counterparty of type individual:
public function findOrCreateContragent(\Bitrix\Sale\Order $order): int
{
$props = $order->getPropertyCollection();
$email = $props->getUserEmail();
$name = $props->getBuyerName();
$phone = $props->getPhone();
$inn = $props->getItemByOrderPropertyCode('INN')?->getValue();
// Search by email
$search = $this->client->request('GET', '/api/v1/counteragents', [], ['search' => $email]);
foreach ($search['data'] ?? [] as $ca) {
if ($ca['email'] === $email) {
return $ca['id'];
}
}
// Create
$isLegal = !empty($inn);
$payload = $isLegal ? [
'type' => 'legal_entity',
'name' => $props->getItemByOrderPropertyCode('COMPANY')->getValue(),
'inn' => $inn,
'kpp' => $props->getItemByOrderPropertyCode('KPP')?->getValue() ?? '',
'email' => $email,
'phone' => $phone,
] : [
'type' => 'individual',
'fullname' => $name,
'email' => $email,
'phone' => $phone,
];
$result = $this->client->request('POST', '/api/v1/counteragents', $payload);
return $result['id'];
}
Sales Document (Invoice / Waybill)
public function createSaleDocument(\Bitrix\Sale\Order $order, int $contragentId): int
{
$items = [];
foreach ($order->getBasket() as $basketItem) {
// VAT from product properties
$vatRate = $this->resolveVatRate($basketItem->getProductId());
$vatValue = round($basketItem->getPrice() * $basketItem->getQuantity()
* ($vatRate / (100 + $vatRate)), 2);
$items[] = [
'name' => $basketItem->getField('NAME'),
'quantity' => $basketItem->getQuantity(),
'unit' => 'pcs',
'price' => $basketItem->getPrice(),
'total' => round($basketItem->getPrice() * $basketItem->getQuantity(), 2),
'vat_rate' => $vatRate, // 0, 10, 20
'vat_value' => $vatValue,
];
}
// Discount at order level
$discount = $order->getField('PRICE_DELIVERY') > 0 ? [
'name' => 'Delivery',
'amount' => $order->getField('PRICE_DELIVERY'),
] : null;
$doc = $this->client->request('POST', '/api/v1/documents/sale', [
'date' => date('Y-m-d'),
'number' => $order->getField('ACCOUNT_NUMBER'),
'counteragent_id' => $contragentId,
'items' => $items,
'shipping' => $discount,
'comment' => 'Order from site #' . $order->getField('ACCOUNT_NUMBER'),
]);
return $doc['id'];
}
Payment Invoice
For B2B orders, after creating the sales document, we generate an invoice:
public function createInvoice(int $documentId, \Bitrix\Sale\Order $order): string
{
$invoice = $this->client->request('POST', '/api/v1/invoices', [
'document_id' => $documentId,
'due_date' => date('Y-m-d', strtotime('+5 days')),
]);
// Get invoice PDF and attach to order in Bitrix
$pdfUrl = $invoice['pdf_url'] ?? '';
if ($pdfUrl) {
$this->attachInvoicePdfToOrder($order->getId(), $pdfUrl);
}
return $invoice['number'] ?? '';
}
Incoming Payments
AddEventHandler('sale', 'OnSalePaymentPaid', function(\Bitrix\Sale\Payment $payment) {
$order = $payment->getOrder();
$docId = MoeDeloSyncTable::getDocumentId($order->getId());
if (!$docId) return;
(new MoeDeloSyncService())->registerPayment($docId, $payment);
});
public function registerPayment(int $docId, \Bitrix\Sale\Payment $payment): void
{
$this->client->request('POST', '/api/v1/payments/income', [
'date' => date('Y-m-d'),
'amount' => $payment->getSum(),
'document_id' => $docId,
'type' => $payment->getPaySystem()->getField('CODE') === 'cash'
? 'cash' : 'bank',
'comment' => 'Payment for order #' . $payment->getOrder()->getField('ACCOUNT_NUMBER'),
]);
}
Automation via Events
| Bitrix Event | Action in MoeDelo |
|---|---|
| Order created (status "New") | Create counterparty + sales document |
| Order paid | Record incoming payment |
| Order canceled | Create return document |
| Order "Awaiting payment" | Issue invoice (for B2B) |
Why Automation Beats Manual Entry?
Automation outperforms manual entry: each order is processed in 5 seconds instead of 10–15 minutes — 180 times faster. Manual entry errors reach 5%, while automation yields less than 0.1% — a 50 times lower error rate. Duplicate counterparties are eliminated, documents always comply with tax authority requirements. The integration pays for itself in 2–3 months by reducing manual labor — real savings.
| Parameter | Manual Entry | Our Integration |
|---|---|---|
| Time per order | 10–15 minutes | 3–5 seconds |
| Errors | up to 5% | < 0.1% |
| Duplicate counterparties | frequent | eliminated |
| 24/7 operation | no | yes |
What's Included
We deliver a complete package:
- PHP client for MoeDelo API
- Search and creation of counterparties (individuals and legal entities)
- Creation of sales documents and invoices
- Registration of payments and returns
- Synchronization table, error handling, and retry logic
- Integration documentation and staff training
- 3 months of warranty support
What Is Synchronized Automatically?
Beyond orders, we synchronize counterparties (with duplicate detection), product items (optional), reconciliation acts (on request), returns, and adjustments. All data undergoes validation before being sent to MoeDelo — eliminating format errors.
Work Process
- Audit — analyze current Bitrix configuration, order schema, document requirements.
- Design — agree on field mapping and error scenarios.
- Implementation — write code, configure events, test on staging.
- Testing — run 100+ orders, check all scenarios (payment, cancellation, return).
- Deploy — roll out to production, monitor for 2 weeks, train staff.
Typical Mistakes in Self-Integration
Incorrect date format (API accepts only YYYY-MM-DD), lack of retry logic on timeouts (orders lost), ignoring API rate limits (30 requests per minute — a queue is needed). We account for all these details, ensuring stable integration. To handle API rate limits, we implement a queue system with exponential backoff. Failed requests are retried up to 5 times with increasing delays, ensuring no order is lost.
Timeline: basic integration from 3 weeks, extended up to 8 weeks. We assess your project for free based on your technical specifications. Contact us to discuss details. Get a consultation — we'll help you choose the optimal scope of work.
Our automatic order export to MoeDelo ensures counterparty synchronization and invoice automation. We provide 1C-Bitrix MoeDelo integration for online stores, enabling seamless document export to MoeDelo.







