# twogis-service > Внутренний HTTP-сервис для работы с 2GIS в проектах satushi: подсказки > адресов внутри города, карточка организации (рейтинг и число отзывов), > полная выгрузка отзывов и browser-backed сбор Catalog. Аутентификация — заголовок `X-Internal-Token`, > ошибки — конверт `{"detail": "..."}`. Ключ 2GIS и обход блокировок живут > в сервисе, интегратору нужен только токен. ## Documentation - [API reference (RU)](/docs/api.md) — полный справочник: запросы, ответы, коды ошибок, список городов, примеры на Python и Java. - [HTML-версия](/docs) — тот же справочник страницей. - [OpenAPI 3.1](/openapi.json) — машинная схема для генерации клиентов. ## API POST /twogis/search — экспериментальный local-first поиск с онлайн-резервом Hybrid. Параметры offline/search + mode=auto|local|online. В auto резерв при пустой, недоступной или устаревшей локальной выдаче. source/provider/fallback_reason показывают происхождение. Следующие страницы требуют mode=source первой страницы. Онлайн total_scope=returned_candidates, catalog/revision=null: это не полный региональный снимок, результаты не записываются в историю. Резерв для 68/67, текст ≥2 символов, те же строгие фильтры. 502/503 не маскируется пустым успехом. Только внутренний токен; offline/search остаётся строго локальным. Offline catalog v1 (новые исходники; production rollout отдельный): POST /twogis/offline/search; GET /twogis/offline/status, /entity, /snapshot, /changes. Загрузки (только по команде Pulse, одна за раз): GET /twogis/offline/manifest; POST/GET /twogis/offline/operations, GET /operations/{id}, POST /operations/{id}/cancel, /approval. Выгрузки пакетов (NDJSON, внутренние): GET /twogis/offline/routing/versions, /routing/export; GET /twogis/offline/transit/versions, /transit/export (остановки, маршруты, направления, геометрия). Виды сущностей сверх branch/building включаются полем include_kinds операции. Все под общим /twogis/offline префиксом и X-Internal-Token. region_id строка: 68 Астана/окрестности, 67 Алматы/окрестности. Поиск — локальный, а не upstream. Дата пакета data_as_of, missing не равно закрытию. Курсор сохранять из next_cursor; ревизию применять целиком. Snapshot 409 требует начать заново. Подробности в API. Базовый URL: `https://twogis.satushi.me`. Внутри кластера — `http://twogis-service.twogis.svc.cluster.local:8081`. - `POST /twogis/address-search` — подсказки адресов. Тело: `query` (2–300 символов), `city` (обязателен, из списка поддерживаемых), `locale` (по умолчанию `ru_KZ`), `limit` (1–50), `timeout_sec` (5–60). Отдаёт `items[]` с `address`, `latitude`, `longitude`, `source_url`. - `POST /twogis/apartment` — подъезд и этаж по квартире. Тело: `address` (2–300 символов), `apartment` (строка, либо квартира с меткой «кв» в конце адреса), `city` (либо город внутри адреса), `timeout_sec` (5–60). Отдаёт `status`, `building`, `matches[]` с `entrance`, `floor`, `floor_source`, `calculated`, `floor_range`, `apartment_ranges`, `floor_apartments`. `floor_source=calculated` означает расчёт при равномерном размещении квартир. Неизвестный этаж — `null`; неоднозначность явно обозначается статусом. Не выбирайте совпадение автоматически при `ambiguous_apartment`/`ambiguous_building`. - `POST /twogis/place` — карточка организации. Тело: `branch_id` либо `source_url`, `timeout_sec`. Отдаёт `rating` и `reviews_count`. - `POST /twogis/reviews` — выгрузка отзывов. Тело: `branch_id` либо `source_url`, `max_reviews` (0 — все), `timeout_sec` (10–900). Отдаёт `reviews[]`, `total_count`, `branch_rating`, `complete`. - `POST /twogis/session` — открывает 2GIS в headless Chromium и возвращает живую Catalog browser-session. Тело: `source_url`, `timeout_sec` (5–120). - `POST /twogis/search-pages` — собирает сырые Catalog `items` со страниц поисковой выдачи через headless Chromium. Тело: `source_url`, `max_pages` (0–300; 0 — все), `timeout_sec` (30–900). - `POST /twogis/catalog` — нормализованные операции public-page(s), catalog-page(s), browser-search, building, branch-building, indoor, suggests, byid, building-address. Ответ {data, error}; частичные результаты не считать полными снимками. - `POST /scrape` — запуск parser-2gis: city, category, source_url, resume_from_run_id, paginate_pages. Возвращает run_id. - `GET /status/{run_id}` — статус, progress, log_tail, rows_emitted, checkpoint. - `GET /rows/{run_id}?after=0&limit=500` — JSONL-поток: rows, total, next_after, checkpoint. - `GET /result/{run_id}` — CSV с исходными колонками. - `POST /pause/{run_id}`, `POST /resume/{run_id}`, `POST /cancel/{run_id}` — управление процессом. После перезапуска продолжение: новый POST /scrape с resume_from_run_id. - `GET /health`, `GET /healthz` — liveness/readiness, без токена. ## Authentication Каждый рабочий запрос, включая задания сбора, требует заголовок: ``` X-Internal-Token: ``` Токен — в Infisical: проект `twogis`, env `prod`, ключ `TWOGIS_INTERNAL_TOKEN`. В Kubernetes приезжает через External Secrets в secret `twogis-secrets`. ## Notes - Город в `/twogis/address-search` обязателен: 2GIS ищет внутри прямоугольника города, а не по тексту запроса. Поддержаны Актау, Актобе, Алматы, Астана, Атырау, Караганда, Каскелен, Кентау, Кокшетау, Костанай, Павлодар, Петропавловск, Семей, Талгар, Тараз, Темиртау, Уральск, Усть-Каменогорск, Шымкент; понимаются алиасы вроде `Нур-Султан` и `Almaty`. - Пустой `items` — это 200, а не ошибка. - Для читающих операций `502` может быть временной ошибкой. `400`, `401`, `422` — чинить запрос. Не повторяйте автоматически `POST /scrape` при неопределённом ответе: можно создать дубликат задания. - Файловый сбор требует постоянного DATA_DIR с правами UID/GID 10001 и одной реплики/worker. Не удаляйте старые каталоги заданий при переключении с Pulse. - Полная выгрузка отзывов занимает минуты: поднимайте `timeout_sec` и таймаут HTTP-клиента. - `/twogis/session` возвращает внутренние credentials browser-session; не передавайте ответ пользовательскому клиенту и не логируйте его целиком. ### Кэш домов для /twogis/apartment Все подъезды и диапазоны дома сохраняются в common DB (схема twogis, база app) на стороне сервиса. Можно повторно запрашивать разные квартиры: сервис проверит сохранённые диапазоны, не обращаясь к 2ГИС снова. Ключ — нормализованный город/улица/дом без квартиры; пустые/неоднозначные ответы тоже сохраняются без автоматического обновления. `captured_at` отражает время загрузки дома, а не время чтения кэша. HTTP 202 с `Retry-After: 5` означает ожидание в очереди. Повторите тот же POST через указанное время; это не ошибка провайдера, резервный канал пока не нужен. Внешние запросы идут по одному, минимум через 5 секунд после ответа. Клиентские опросы продвигают FIFO-очередь; без опросов задачи остаются в очереди. Нужен `TWOGIS_DATABASE_URL` к общей PostgreSQL БД. Ошибки провайдера и прерванные попытки сохраняются без автоматического повтора (HTTP 502).