1C-Bitrix Integration with DaData (Address Suggestions)
When placing an order, users enter addresses freehand in arbitrary formats: "msk lenina 5 apt 12", "Moscow, Lenin St., 5". The database becomes inconsistent, integration with shipping carriers breaks down, and delivery cost calculation stops working. DaData standardizes and normalizes the address against FIAS right as the user types.
What DaData provides
- Suggestions on input (Suggestions API) — address autocomplete linked to FIAS/KLADR.
- Standardization (Cleaner API) — normalize a freehand address into a canonical form.
- Geocoding — coordinates from an address and an address from coordinates.
- Company suggestions — tax ID (INN) → full company details.
Connecting the Suggestions API
Register at dadata.ru, obtain an API key and a secret key. Free tier limits: 10,000 requests/day. A paid plan is recommended for production.
Frontend — connect the widget:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/suggestions-jquery/dist/css/suggestions.min.css">
<script src="https://cdn.jsdelivr.net/npm/suggestions-jquery/dist/js/jquery.suggestions.min.js"></script>
<script>
$("#delivery-address").suggestions({
token: "<?= COption::GetOptionString('site', 'dadata_api_key') ?>",
type: "ADDRESS",
/* restrict geography: */
constraints: { locations: [{ country: "Russia" }] },
onSelect: function(suggestion) {
// Populate form fields from the address
const d = suggestion.data;
$("#field-city").val(d.city || d.settlement);
$("#field-street").val(d.street_with_type);
$("#field-house").val(d.house);
$("#field-flat").val(d.flat);
$("#field-zip").val(d.postal_code);
$("#field-fias-id").val(d.fias_id); // store the FIAS ID
$("#field-region").val(d.region_with_type);
$("#field-lat").val(d.geo_lat);
$("#field-lon").val(d.geo_lon);
}
});
</script>
It is important to store fias_id — it is used for integration with shipping carriers (CDEK, Boxberry) and uniquely identifies the address.
Server-side address standardization
When an address is entered without the widget (CSV import, API orders), normalize it on the server:
function standardizeAddress(string $rawAddress): array {
$apiKey = COption::GetOptionString('site', 'dadata_api_key');
$secretKey = COption::GetOptionString('site', 'dadata_secret_key');
$http = new \Bitrix\Main\Web\HttpClient();
$http->setHeader('Authorization', 'Token ' . $apiKey);
$http->setHeader('X-Secret', $secretKey);
$http->setHeader('Content-Type', 'application/json');
$response = $http->post(
'https://cleaner.dadata.ru/api/v1/clean/address',
json_encode([$rawAddress])
);
$result = json_decode($response, true)[0] ?? [];
return [
'city' => $result['city'] ?? '',
'street' => $result['street_with_type'] ?? '',
'house' => $result['house'] ?? '',
'flat' => $result['flat'] ?? '',
'fias_id' => $result['fias_id'] ?? '',
'postal' => $result['postal_code'] ?? '',
'qc' => $result['qc'] ?? 3, // quality: 0-good, 3-unrecognized
];
}
The qc (quality code) field is critical: 0 — address recognized unambiguously, 1 — recognized with assumptions, 3 — not recognized. When qc = 3, flag the order for manual review by a manager.
Company details from tax ID (INN)
B2B registration form: the user enters the INN — the company name, KPP, legal address, and director's name are automatically populated. This saves 2–3 minutes during registration.
$("#inn").suggestions({
token: dadataToken,
type: "PARTY",
onSelect: function(suggestion) {
const d = suggestion.data;
$("#company-name").val(d.name.short_with_opf);
$("#kpp").val(d.kpp);
$("#ogrn").val(d.ogrn);
$("#legal-address").val(d.address.value);
$("#director").val(d.management ? d.management.name : '');
}
});
Data from DaData is saved to Bitrix user properties (CUser::Update()) and to the company table if a B2B cabinet is implemented.
Caching suggestions
Every keystroke in the address field triggers a request to the DaData API. With active users, the quota is consumed quickly. Optimization: 300 ms debounce in JS, a server-side proxy with caching of frequent requests in memcached or Redis for 1 hour.
Case: a plumbing supplies store with 800 orders/day. Without optimization — 15,000 requests to DaData per day (exceeding the free tier). After implementing debounce and proxy cache — 3,000 requests/day.
| Task | Effort |
|---|---|
| Connecting the suggestions widget | 3–4 h |
| Server-side standardization + qc handling | 4–6 h |
| INN suggestions for B2B | 3–4 h |
| Proxy cache to reduce request count | 4–6 h |







