Русский · English
Готовые примеры работы с API стандартизации адреса на шести языках: Python, TypeScript (Node.js), Go, Java, C#, PHP. Нормализация адреса, введённого человеком в произвольном виде, и разбор адреса на составляющие: страна, регион, город, улица, дом, корпус, квартира. Плюс коэффициент качества разбора — насколько движок уверен в результате.
На вход — то, как люди реально пишут адреса: мск ленинскй проспект д4 кв5. На выходе — структура и нормализованная строка.
Разбор выполняется локально, без обращений к внешним источникам, — отсюда время ответа в единицы миллисекунд.
Каждый пример запускается сразу — без регистрации, без ключа, без карты. В коде зашит публичный демо-ключ.
git clone https://github.com/atlorium-api/address-standardization-api-client
cd address-standardization-api-client/python && pip install -r requirements.txt && python main.pyНастоящий вывод примера на демо-ключе — со всеми странностями песочницы, объяснёнными ниже:
Демо-ключ: ответы сгенерированы (моки), не реальные данные.
Чистка адресной базы. Адресов на входе: 3
[1] «г Москва, ул. Тверская, д. 7, кв. 12»
Нормализовано: город Киров, улица Восточная проспект, д.4, кв.153
Качество: 100 · Страна: RU · 5 мс
Город: Киров | Улица: Восточная проспект | Дом: 4 | Кв.: 153
ПРИНЯТ: качество 100 >= порога 80
[2] «мск ленинскй проспект д4 кв5»
Нормализовано: город Воронеж, улица Энергетиков проспект, д.88, кв.202
Качество: 100 · Страна: RU · 17 мс
Город: Воронеж | Улица: Энергетиков проспект | Дом: 88 | Кв.: 202
ПРИНЯТ: качество 100 >= порога 80
[3] «спб невский пр-кт 28»
Нормализовано: город Ярославль, улица Солнечная пл., д.116, кв.164
Качество: 100 · Страна: RU · 5 мс
Город: Ярославль | Улица: Солнечная пл. | Дом: 116 | Кв.: 164
ПРИНЯТ: качество 100 >= порога 80
ИСХОДНАЯ СТРОКА НОРМАЛИЗОВАННЫЙ АДРЕС КАЧ РЕШЕНИЕ
г Москва, ул. Тверская, д. 7, кв… город Киров, улица Восточная проспект, д.4, … 100 ПРИНЯТ
мск ленинскй проспект д4 кв5 город Воронеж, улица Энергетиков проспект, д… 100 ПРИНЯТ
спб невский пр-кт 28 город Ярославль, улица Солнечная пл., д.116,… 100 ПРИНЯТ
ИТОГО
Обработано адресов: 3
Принято автоматически: 3
На ручную проверку: 0
Порог качества: 80. Молча записать криво разобранный адрес в базу
хуже, чем отдать его человеку: уверенное автоматизируем, сомнительное эскалируем.
[!] ПЕСОЧНИЦА: нормализованный адрес выше НЕ ИМЕЕТ ОТНОШЕНИЯ к введённому —
мок генерирует случайный правдоподобный адрес и всегда ставит quality = 100.
Поэтому отсева по порогу здесь не видно: он заработает на боевом ключе.
Да, вы прочитали правильно: на «г Москва, ул. Тверская» песочница ответила «город Киров». Мы не подгоняли вывод под красивую картинку — это ровно то, что печатает пример на демо-ключе. Почему так и что при этом всё-таки работает — следующий раздел. Подставьте боевой ключ — тот же код начнёт разбирать адрес по-настоящему.
Человек вводит адрес как ему удобно: мск, Санкт-Петербург, СПб, ул. Лесная, Лесная ул., д.4к1, кв 5. В базе это превращается в кашу, по которой нельзя ни дедуплицировать клиентов, ни построить доставку, ни выгрузить отчёт.
Стандартизация превращает эту кашу в структуру: отдельно город, отдельно улица, отдельно дом, отдельно квартира — плюс нормализованная строка единого вида.
Типовые задачи: очистка адресов в CRM и накопленных базах, приведение адреса из формы к единому виду перед сохранением, разбор адреса из письма/заявки/выгрузки, подготовка данных к загрузке в логистику, дедупликация клиентов и точек доставки, миграция из старой системы.
Примеры не просто печатают JSON, а применяют данные: в каждом есть функция cleanAddressDatabase(), которая делает то, ради чего сервис и покупают.
Для каждого «грязного» адреса она:
- получает разбор — нормализованную строку и массив
components[]; - вытаскивает из компонентов колонки для CRM: город, улица, дом (с корпусом и строением), квартира;
- принимает решение по порогу качества.
QUALITY_THRESHOLD = 80
if quality < QUALITY_THRESHOLD:
decision = "НА ПРОВЕРКУ" # человеку
else:
decision = "ПРИНЯТ" # в базу автоматическиЗачем нужен порог. Молча записать криво разобранный адрес в базу хуже, чем отдать его человеку: испорченную запись никто не заметит, а посылка уедет не туда. Поэтому уверенные случаи автоматизируем, сомнительные эскалируем на ручную проверку. Порог — это ручка, которой вы регулируете баланс между «сколько сэкономили на операторах» и «сколько мусора пустили в базу».
Второй фильтр в примере: даже при высоком качестве адрес уходит человеку, если не выделены улица или дом — по такому адресу всё равно нельзя доставить.
Итог работы — сводка: сколько адресов принято автоматически, сколько ушло на ручную проверку.
Демо-ключ — это генератор правдоподобных данных, а не настоящий разбор. Мок не смотрит на вашу строку: он берёт от неё seed и генерирует случайный правдоподобный российский адрес.
Отсюда два следствия, которые видны прямо в выводе выше:
| Что происходит | Почему |
|---|---|
| Нормализованный адрес не имеет отношения к введённому: «мск тверская 7» → «город Сочи, улица пл. Заречная, д.69, кв.227» | Мок генерирует адрес, а не разбирает ваш |
quality всегда 100 — даже у заведомо кривой строки |
Мок не оценивает разбор, он просто проставляет максимум |
| Внутри одной строки город и улица не согласованы («улица Восточная проспект») | Компоненты генерируются независимо |
Практический вывод: в песочнице порог качества не срабатывает. На моках вы никогда не увидите строку НА ПРОВЕРКУ — всё принимается автоматически, потому что качество всегда 100. Отсев начнёт работать только на боевом ключе. Мы пишем это прямо, потому что вы всё равно это увидите, а обман стоит доверия.
Что при этом работает и полезно:
- Структура ответа настоящая. Все поля, уровни
components[], типы и вложенность — ровно те, что придут с боевым ключом. Интеграцию можно написать целиком. - Ответы детерминированы. Одна и та же строка всегда даёт один и тот же результат — значит, на песочнице можно писать стабильные тесты.
- Ветка «НА ПРОВЕРКУ» тестируется без боевого ключа: поднимите
QUALITY_THRESHOLDвыше 100, и весь список уйдёт на ручную проверку. Логика ветвления проверяется, качество разбора — нет.
Чего на песочнице делать нельзя: оценивать качество разбора и полноту компонентов. Для этого нужен боевой ключ.
Проверить API вообще без клонирования:
curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
"https://atlorium.com/api/addressstd?address=г Москва, ул. Тверская, д. 7, кв. 12" --get| Язык | Запуск | Требуется |
|---|---|---|
| Python | pip install -r requirements.txt && python main.py |
Python 3.10+ |
| TypeScript / Node.js | npm install && npm start |
Node.js 20+ |
| Go | go run . |
Go 1.22+ |
| Java | java Main.java |
JDK 17+ (без зависимостей) |
| C# | dotnet run |
.NET 8+ |
| PHP | php main.php |
PHP 8.1+ |
Передать свой адрес аргументом:
python main.py "мск ленинскй проспект д4 кв5"Этот адрес встанет первым в демо-список; ещё два «грязных» адреса зашиты в пример, чтобы сводка была не из одной строки. Всего за прогон — три запроса к API.
Ключ передаётся в заголовке Authorization:
Authorization: Bearer ВАШ_КЛЮЧ
| Ключ | Что делает |
|---|---|
ak_sandbox_demo_mockdata_v1 |
Демо-ключ. Публичный, один на всех. Возвращает моки, денег не списывает, регистрации не требует. Ответы детерминированы — на них можно писать стабильные тесты. |
| Боевой ключ | Настоящий разбор адреса. Получить в личном кабинете: atlorium.com |
Переход на боевой ключ не требует правок в коде — все примеры читают переменную окружения:
export ATLORIUM_API_KEY="ak_ваш_боевой_ключ"Каждый ответ песочницы помечен заголовком X-Atlorium-Sandbox: true — перепутать мок с реальными данными невозможно.
Базовый адрес: https://atlorium.com
| Метод | Путь | Назначение |
|---|---|---|
GET |
/api/addressstd |
Разбор адресной строки в структуру + нормализация + коэффициент качества |
| Параметр | Где | Тип | Описание |
|---|---|---|---|
address |
query | string | Адресная строка. Допускаются опечатки, сокращения, нижний регистр и переставленные части: мск ленинскй проспект д4 кв5 |
region |
query | int | Код региона по умолчанию (например, 77), если в строке региона нет. Помогает разобрать «улица + дом» без верхнего уровня. Необязателен |
bind |
query | bool | Пока не реализовано — привязка разобранного адреса к справочнику ГАР/ФИАС. Сейчас возвращает 501 и не тарифицируется |
geocode |
query | bool | Пока не реализовано — добавление координат. Сейчас возвращает 501 и не тарифицируется |
Про bind и geocode честно: они уже описаны в контракте как задел, но включатся позже. Пока их запрос возвращает 501 — и деньги за него не списываются. Если привязка к ГАР/ФИАС нужна вам сейчас — это отдельный сервис, gar-fias-address-api-client.
Поля сняты с живых ответов API и сверены с OpenAPI-спекой.
| Поле | Тип | Что содержит |
|---|---|---|
input |
string | Эхо запроса: строка, как её прислали |
normalized |
string | Нормализованный адрес одной строкой, собранный из разобранных элементов |
quality |
int | Коэффициент качества разбора, 0..100. Ключевое поле. 100 — идеальный разбор без лишних фрагментов; >= 90 — нормально; ниже 80 — к результату стоит относиться осторожно |
countryCode |
string | Код страны (RU, …), если удалось определить. Может быть null |
message |
string | Сообщение о неточности, влияющей на качество (например, непонятный фрагмент строки). Готовая подсказка оператору. Может быть null |
info |
string | Информационное сообщение, не влияющее на качество. Может быть null |
components |
array | Разобранные элементы адреса, сверху вниз — от страны к квартире (см. ниже) |
extra |
object | Элементы, не вписавшиеся в общую модель: этаж, а/я, нормализованное название организации. Может быть null |
milliseconds |
int | Время разбора, мс |
gar |
object | Привязка к ГАР/ФИАС. Задел: сейчас всегда null (см. bind выше) |
geo |
object | Координаты. Задел: сейчас всегда null (см. geocode выше) |
| Поле | Тип | Что содержит |
|---|---|---|
level |
string | Адресный уровень (см. таблицу ниже) |
levelTitle |
string | Название уровня по-русски: Город, Улица, Дом/здание, Помещение/квартира |
text |
string | Нормализованное представление элемента одной строкой: улица 16 Парковая, д.2 корп.1 |
types |
array | Тип элемента: ["улица"], ["город"]. Может быть null |
names |
array | Собственные имена элемента: ["16", "Парковая"]. Это то, что кладут в колонку CRM. Может быть null |
number |
string | Основной номер: дома, участка, квартиры, комнаты. Может быть null |
buildNumber |
string | Корпус — только для домов. Может быть null |
structNumber |
string | Строение — только для домов. Может быть null |
plotNumber |
string | Номер земельного участка. Может быть null |
misc |
array | Второстепенные уточнения. Может быть null |
Разница между text и names: text — готовая к показу строка (улица Тверская), names — разобранное имя (Тверская). В колонку «Улица» в CRM обычно кладут names, в адресную строку на конверте — text.
Сверху вниз, от страны к комнате:
Undefined · Country · RegionArea · RegionCity · District · Settlement · City · CityDistrict · Locality · Territory · Street · Plot · Building · Apartment · Room
В ответе присутствуют только те уровни, которые удалось выделить из строки. Если в адресе нет квартиры — компонента Apartment не будет. Именно поэтому в примере проверяется наличие Street и Building, а не берётся элемент по индексу.
| Код | Причина | Что делать |
|---|---|---|
400 |
Строка не указана или из неё не удалось выделить адрес | Проверьте параметр address. Запрос не тарифицируется: работа не выполнялась |
401 |
Ключ отсутствует, просрочен или недействителен | Проверьте заголовок Authorization |
402 |
Недостаточно кредитов на балансе | Пополнить на atlorium.com |
429 |
Превышен rate-limit | Повторить с задержкой — но с потолком ожидания, см. ниже |
501 |
Запрошен комбо-режим bind или geocode |
Пока не реализовано. Запрос не тарифицируется |
Во всех шести примерах коды разложены в человекочитаемые причины — смотрите класс AtloriumError.
Про потолок ожидания при 429. Исчерпав часовое окно, сервер честно просит подождать десятки минут. Клиент, слепо доверяющий заголовку Retry-After, зависнет на всё это время (а в CI — съест бюджет джоба). Поэтому в примерах есть MAX_RETRY_DELAY = 120 секунд: дольше потолка не ждём, а честно сообщаем «квота исчерпана» и выходим.
Оплата pay-as-you-go, без подписки: платите только за выполненные запросы. Строка, из которой не удалось выделить адрес (400), и комбо-режимы (501) не тарифицируются.
Практический совет: не прогоняйте базу в цикле «на пробу». Один прогон примера — три запроса, этого достаточно, чтобы понять контракт.
Актуальные цены и лимиты: atlorium.com/pricing
Чем это отличается от ГАР/ФИАС? Это два разных инструмента, и они дополняют друг друга. Стандартизация разбирает произвольную строку в структуру и говорит, насколько уверенно она это сделала, — на входе может быть что угодно, справочник не нужен. ГАР/ФИАС ищет адрес в официальном государственном справочнике и возвращает его objectGuid (код ФИАС), ОКТМО, индекс. Практика такая: сначала стандартизация приводит грязную строку в порядок, потом ГАР/ФИАС находит по ней официальный объект. Автоматическую связку этих двух шагов (параметр bind) мы сейчас и делаем.
Это аналог DaData? По задаче — да: приведение адреса к единому виду и разбор на составляющие с оценкой качества. Отличия: разбор идёт локально на нашей стороне, оплата pay-as-you-go без подписки, а официальный справочник адресов вынесен в отдельный сервис ГАР/ФИАС. Пробовать можно без регистрации — публичный демо-ключ уже зашит в примеры.
Как исправить адрес через API? Отправьте строку как есть в GET /api/addressstd?address=.... Опечатки, сокращения (мск, пр-кт, д4к1), нижний регистр и переставленные части допускаются — на выходе будет normalized и разбор по компонентам.
Что означает quality и какой порог ставить? Это уверенность движка в разборе, 0..100. 100 — идеальный разбор, >= 90 — нормально, ниже 80 — осторожно. Начните с порога 80, посмотрите, сколько адресов уходит на ручную проверку, и двигайте его: выше порог — чище база и больше работы операторам, ниже — наоборот.
Приходит ли почтовый индекс и ОКТМО? Из этого сервиса — нет: он разбирает строку, а не сверяет её со справочником. Индекс, ОКТМО, ОКАТО и код ИФНС отдаёт ГАР/ФИАС по найденному адресному объекту.
Работает ли с иностранными адресами? Определяется countryCode, и разбор не заточен исключительно под РФ. Но профиль сервиса — российские адреса; на них качество разбора заметно выше.
Данные уходят во внешние сервисы? Нет. Разбор выполняется локально, поэтому отвечает за единицы миллисекунд и не зависит от доступности сторонних API.
Обязательна ли регистрация, чтобы попробовать? Нет. Демо-ключ публичный и работает без аккаунта — но возвращает моки, а не настоящий разбор (см. раздел про песочницу выше).
Адрес редко живёт сам по себе — обычно рядом лежат телефон, почта и реквизиты. Из того же аккаунта и тем же ключом доступны:
- Валидация телефона — формат, тип номера, оператор диапазона
- Адреса ГАР/ФИАС — поиск и подсказки по официальному справочнику
- Проверка почты — синтаксис, MX-записи, одноразовые адреса
- Погодные данные — текущие условия по координатам
- ИИ-чат — модели, сессии, суммаризация текста
- Разбор cron-выражений — валидация расписания и ближайшие запуски с учётом таймзоны
Полный каталог — atlorium.com
- Документация API (Swagger): atlorium.com/addressstdAPI
- Описание сервиса: atlorium.com/addressstdDescription
- Веб-интерфейс: atlorium.com/addressstdGUI
- OpenAPI-спецификация: addressstd_ru.json
- Поддержка: support@atlorium.com
MIT — берите код и используйте как хотите, в том числе в коммерческих проектах.