Перейти до вмісту

Інтеграція з Новою поштою в Python

Матеріал з K2 ERP Wiki Ukraine — База знань з автоматизації та санкцій в Україні


SEO title: Технічне завдання: Інтеграція з Новою поштою для Python SEO description: Технічне завдання на реалізацію Python-сервісу для інтеграції K2 ERP, CRM або інтернет-магазину з Новою поштою: створення експрес-накладних, довідники міст і відділень, розрахунок вартості, статуси відправлень, друк маркувань, реєстри, помилки, dashboard та журналювання. SEO keywords: Python, Нова пошта, Nova Post API, API Нова пошта, експрес-накладна, ТТН, ЕН, доставка, K2 ERP, CRM, інтернет-магазин, FastAPI, логістика, відділення, поштомати, реєстр відправлень Alternative to:



Головна ідея: розробити Python-сервіс, який інтегрує K2 ERP / CRM / інтернет-магазин / WMS із API Нової пошти для створення експрес-накладних, розрахунку вартості доставки, синхронізації довідників, отримання статусів, друку маркувань та контролю відправлень.

Критично важливо: інтеграція не повинна створювати дублікати експрес-накладних. Кожне замовлення, кожна ЕН / ТТН, повторний запит, помилка API, друк маркування та зміна статусу повинні мати внутрішній ID, idempotency_key, журнал подій і контроль повторної обробки.

Важливо: у Нової пошти API-запити зазвичай будуються через поля modelName, calledMethod та methodProperties. Конкретні моделі та методи потрібно звіряти з актуальною офіційною документацією API перед реалізацією production-версії.

Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker.

Управлінський результат: менеджер і керівник повинні бачити, скільки замовлень передано в Нову пошту, скільки ЕН створено, які посилки доставлені, які очікують отримання, які повертаються, де є помилки адреси, оплати, ваги або статусу.

1. Мета

Метою задачі є створення Python-сервісу для інтеграції з Новою поштою з метою автоматизації процесів доставки.

Сервіс повинен забезпечити:

  • зберігання налаштувань інтеграції;
  • отримання та оновлення довідників Нової пошти;
  • пошук міст;
  • пошук відділень;
  • пошук поштоматів;
  • пошук вулиць;
  • створення контрагентів або використання існуючих;
  • створення контактних осіб;
  • створення адрес;
  • розрахунок вартості доставки;
  • розрахунок орієнтовної дати доставки;
  • створення експрес-накладної;
  • редагування експрес-накладної, якщо дозволено API;
  • видалення / скасування експрес-накладної, якщо дозволено API;
  • друк маркування;
  • формування реєстру відправлень;
  • отримання статусів відправлень;
  • синхронізацію статусів назад у K2 ERP;
  • журналювання всіх API-запитів;
  • dashboard для контролю логістики.

2. Область застосування

Інтеграція призначена для:

  • інтернет-магазинів;
  • CRM;
  • ERP;
  • WMS;
  • складів;
  • служб доставки;
  • торгових компаній;
  • дистриб'юторів;
  • компаній, які створюють багато експрес-накладних;
  • компаній, які хочуть контролювати доставку прямо з K2 ERP.

3. Основні можливості API Нової пошти

API Нової пошти використовується для автоматизації логістичних процесів бізнесу. Офіційна сторінка інтеграції описує генерацію API Key у бізнес-кабінеті, а API-портал Nova Post окремо вказує можливості для бізнесу: обробка й відправлення замовлень, доступ до функцій Nova Post та інформації про посилки. :contentReference[oaicite:1]{index=1}

Типові моделі API:

Модель Призначення Приклади використання
Address Робота з адресними довідниками. Міста, населені пункти, відділення, поштомати, вулиці.
InternetDocument Робота з експрес-накладними. Створення ЕН, розрахунок вартості, дата доставки, друк.
TrackingDocument Відстеження відправлень. Отримання статусів за номерами ЕН.
Counterparty Контрагенти. Відправники, отримувачі.
ContactPerson Контактні особи. Телефон, ПІБ, прив'язка до контрагента.
Common Загальні довідники. Типи вантажу, типи сервісу, форми оплати тощо.
ScanSheet Реєстри прийому-передачі. Формування реєстру відправлень.

У старій відкритій документації API описані моделі `InternetDocument`, `Common`, `Counterparty`, `ContactPerson`, `Address`, `ScanSheet`, а також структура запиту через `modelName`, `calledMethod` і `methodProperties`; це корисно як орієнтир, але production-реалізацію потрібно звіряти з актуальним API-порталом. :contentReference[oaicite:2]{index=2}

4. Передумови

Для реалізації задачі необхідно отримати:

  • бізнес-акаунт Нової пошти;
  • API Key;
  • доступ до актуальної API-документації;
  • дані відправника;
  • контактну особу відправника;
  • адресу / відділення відправника;
  • правила оплати доставки;
  • правила зворотної доставки;
  • правила післяплати;
  • правила страхування;
  • перелік типів вантажу;
  • перелік типів доставки;
  • правила друку маркувань;
  • правила формування реєстрів;
  • правила оновлення статусів;
  • вимоги K2 ERP до збереження ЕН.

Критично важливо: API Key потрібно зберігати тільки в зашифрованому вигляді або secret storage. Заборонено зберігати API Key у коді, Git, frontend-змінних або відкритих логах.

5. Основні бізнес-сценарії

5.1. Створення експрес-накладної з K2 ERP

K2 ERP передає в Python-сервіс замовлення, дані отримувача, місто, відділення або адресу, параметри вантажу та оплату.

Python-сервіс:

  • перевіряє замовлення;
  • перевіряє отримувача;
  • перевіряє місто;
  • перевіряє відділення / адресу;
  • розраховує вартість доставки;
  • створює експрес-накладну;
  • зберігає номер ЕН;
  • передає номер ЕН назад у K2 ERP;
  • формує маркування для друку.

5.2. Доставка у відділення

Замовлення доставляється у відділення Нової пошти.

Потрібно передати:

  • місто отримувача;
  • Ref міста;
  • Ref відділення;
  • ПІБ отримувача;
  • телефон отримувача;
  • кількість місць;
  • вагу;
  • об'єм;
  • оголошену вартість;
  • платника доставки;
  • форму оплати;
  • опис вантажу.

5.3. Доставка у поштомат

Замовлення доставляється у поштомат.

Особливості:

  • потрібно обрати поштомат зі списку доступних;
  • потрібно перевіряти обмеження по вазі та габаритах;
  • потрібно валідувати телефон отримувача;
  • потрібно контролювати статус прибуття й термін зберігання.

5.4. Адресна доставка

Замовлення доставляється кур'єром на адресу.

Потрібно передати:

  • місто;
  • вулицю;
  • будинок;
  • квартиру / офіс, якщо є;
  • контактну особу;
  • телефон;
  • часові або сервісні параметри, якщо доступні;
  • тип сервісу DoorsDoors або WarehouseDoors залежно від сценарію.

5.5. Зворотна доставка / післяплата

Якщо використовується післяплата або повернення коштів, потрібно передбачити:

  • суму післяплати;
  • платника комісії;
  • тип зворотної доставки;
  • контроль статусу оплати;
  • зв'язок із фінансовими документами в K2 ERP.

5.6. Синхронізація статусів

Python-сервіс регулярно отримує статуси відправлень і оновлює K2 ERP.

Синхронізуються:

  • створено;
  • прийнято у відділенні;
  • у дорозі;
  • прибуло у відділення;
  • прибуло у поштомат;
  • видано отримувачу;
  • відмова;
  • повернення;
  • повернуто відправнику;
  • зберігання;
  • помилка / уточнення.

6. Основні сутності

Сутність Опис
Integration Account Налаштування API Нової пошти.
Sender Відправник.
Recipient Отримувач.
Counterparty Контрагент API Нової пошти.
Contact Person Контактна особа.
City Місто / населений пункт з довідника Нової пошти.
Warehouse Відділення або поштомат.
Address Адреса для кур'єрської доставки.
Delivery Order Замовлення на доставку в K2 ERP.
Internet Document Експрес-накладна / ЕН / ТТН.
Scan Sheet Реєстр прийому-передачі.
Tracking Status Статус доставки.
API Event Подія інтеграції.

7. User Story

7.1. Створення ЕН

Як менеджер інтернет-магазину, я хочу натиснути кнопку «Створити ЕН Нової пошти», щоб система автоматично створила експрес-накладну без ручного введення в кабінеті Нової пошти.

7.2. Друк маркування

Як комірник, я хочу надрукувати маркування по створеній ЕН, щоб наклеїти його на посилку.

7.3. Контроль статусів

Як менеджер, я хочу бачити статус доставки прямо в K2 ERP, щоб швидко реагувати на відмови, повернення та прострочені доставки.

7.4. Формування реєстру

Як працівник складу, я хочу сформувати реєстр відправлень, щоб передати партію посилок у Нову пошту.

7.5. Dashboard керівника

Як керівник, я хочу бачити статистику по доставках, щоб контролювати якість логістики, повернення, затримки та помилки.

8. Типи доставки

Тип Код Опис Колір
Відділення → Відділення WarehouseWarehouse Класична доставка між відділеннями. Базова
Відділення → Адреса WarehouseDoors Відправка з відділення на адресу отримувача. Додаткова
Адреса → Відділення DoorsWarehouse Кур'єр забирає у відправника, доставка у відділення. Додаткова
Адреса → Адреса DoorsDoors Кур'єрська доставка від дверей до дверей. Важлива
Відділення → Поштомат WarehousePostomat Доставка в поштомат, якщо підтримується сценарієм. Додаткова

Важливо: коди сервісів і доступність конкретних сценаріїв потрібно перевірити за довідниками API Нової пошти, оскільки правила можуть змінюватися.

9. Статуси відправлень

Статус K2 ERP Код Опис Колір
Чернетка DRAFT Замовлення є в K2 ERP, але ЕН ще не створено. Сірий
Очікує створення ЕН PENDING_CREATE Замовлення в черзі на створення ЕН. Жовтий
Створюється CREATING Виконується API-запит до Нової пошти. Блакитний
ЕН створено CREATED Експрес-накладну створено. Зелений
Маркування надруковано MARKING_PRINTED Маркування або PDF отримано / надруковано. Зелений
Передано у реєстр IN_SCAN_SHEET Відправлення додано в реєстр. Блакитний
Прийнято Новою поштою ACCEPTED_BY_NP Відправлення прийнято оператором. Блакитний
У дорозі IN_TRANSIT Посилка рухається між терміналами. Блакитний
Прибуло ARRIVED Відправлення прибуло у відділення / поштомат / місто. Жовтий
Доставлено DELIVERED Відправлення отримано. Зелений
Відмова REFUSED Отримувач відмовився. Червоний
Повернення RETURNING Відправлення повертається. Помаранчевий
Повернуто RETURNED Відправлення повернуто відправнику. Помаранчевий
Помилка ERROR Помилка створення або синхронізації. Червоний
Потребує повтору NEEDS_RETRY Технічна помилка, можна повторити. Помаранчевий
Скасовано CANCELLED ЕН або замовлення скасовано. Сірий

10. Єдина логіка кольорів

Колір HTML Значення Де використовується
Зелений #c8e6c9 Успішно: ЕН створено, маркування надруковано, доставлено. Dashboard, список відправлень, картка замовлення.
Блакитний #bbdefb Операція виконується або доставка в процесі. Черга, API-статуси, транспортування.
Жовтий #fff9c4 Очікування або прибуття. Очікує створення, прибуло у відділення.
Помаранчевий #ffcc80 Потрібна дія або є ризик. Повернення, retry, проблемні статуси.
Червоний #ef9a9a Помилка або негативний результат. Відмова, помилка API, неправильна адреса.
Фіолетовий #f3e5f5 Спеціальний або ручний сценарій. Ручна перевірка, нестандартна доставка.
Сірий #eeeeee Чернетка, скасовано або неактивно. Архів, чернетки.

11. Архітектура рішення

11.1. Загальна схема

K2 ERP / CRM / Website / WMS
        |
        | 1. Замовлення, клієнт, адреса, вантаж
        v
Python Nova Poshta Integration Service
        |
        | 2. Валідація, мапінг, дедублікація, черга
        v
Nova Poshta API Client
        |
        | 3. API Нової пошти
        v
Нова пошта
        |
        | 4. ЕН, статуси, маркування, реєстри
        v
Python Status Sync Worker
        |
        | 5. Оновлення статусів
        v
K2 ERP / Dashboard / Склад / Менеджер

11.2. Основні компоненти Python-сервісу

Компонент Опис
API Layer REST API для прийому замовлень і команд із K2 ERP.
Validation Layer Перевіряє отримувача, адресу, відділення, вагу, габарити, оплату.
Mapping Layer Перетворює структури K2 ERP у формат API Нової пошти.
Nova Poshta Client Python-клієнт для API Нової пошти.
Directory Sync Worker Оновлює довідники міст, відділень, поштоматів, вулиць.
Delivery Queue Черга створення ЕН.
Tracking Worker Оновлює статуси відправлень.
Print Service Отримує PDF / маркування / друковані форми.
Scan Sheet Service Формує реєстри відправлень.
Audit Logger Зберігає запити, відповіді, помилки та зміни статусів.
Dashboard API Дані для менеджера, складу та керівника.

12. Nova Poshta Client

12.1. Призначення

Nova Poshta Client — це Python-клас або пакет, який інкапсулює роботу з API Нової пошти.

12.2. Загальний формат API-запиту

Типовий запит має містити:

{
  "apiKey": "********",
  "modelName": "InternetDocument",
  "calledMethod": "save",
  "methodProperties": {}
}

Важливо: конкретний modelName, calledMethod і methodProperties потрібно брати з актуальної документації API Нової пошти.

12.3. Основні методи Python-клієнта

class NovaPoshtaClient:
    def check_connection(self) -> "ConnectionStatus":
        pass

    def call_api(self, model_name: str, called_method: str, properties: dict) -> dict:
        pass

    def get_cities(self, query: str | None = None) -> "CityListResponse":
        pass

    def get_warehouses(self, city_ref: str, warehouse_type: str | None = None) -> "WarehouseListResponse":
        pass

    def get_streets(self, city_ref: str, query: str) -> "StreetListResponse":
        pass

    def get_document_price(self, payload: "DeliveryPricePayload") -> "DeliveryPriceResponse":
        pass

    def get_document_delivery_date(self, payload: "DeliveryDatePayload") -> "DeliveryDateResponse":
        pass

    def create_internet_document(self, payload: "InternetDocumentPayload") -> "InternetDocumentResponse":
        pass

    def update_internet_document(self, ref: str, payload: "InternetDocumentPayload") -> "InternetDocumentResponse":
        pass

    def delete_internet_document(self, ref: str) -> "DeleteDocumentResponse":
        pass

    def get_tracking_statuses(self, document_numbers: list[str]) -> "TrackingStatusResponse":
        pass

    def get_print_form(self, document_refs: list[str], format: str = "pdf") -> bytes:
        pass

    def create_scan_sheet(self, document_refs: list[str]) -> "ScanSheetResponse":
        pass

13. Конфігурація клієнта

from pydantic_settings import BaseSettings


class NovaPoshtaSettings(BaseSettings):
    base_url: str = "https://api.novaposhta.ua/v2.0/json/"
    api_key: str
    timeout_seconds: int = 30
    retry_count: int = 3
    retry_backoff_seconds: int = 5
    verify_ssl: bool = True
    language: str = "ua"

Приклад `.env`:

NOVA_POSHTA_BASE_URL=https://api.novaposhta.ua/v2.0/json/
NOVA_POSHTA_API_KEY=********
NOVA_POSHTA_TIMEOUT_SECONDS=30
NOVA_POSHTA_RETRY_COUNT=3
NOVA_POSHTA_RETRY_BACKOFF_SECONDS=5
NOVA_POSHTA_LANGUAGE=ua

14. API Python-сервісу

14.1. Створення інтеграції

POST /api/v1/nova-poshta/integrations

14.2. Перевірка підключення

POST /api/v1/nova-poshta/integrations/{integration_id}/check-connection

14.3. Синхронізація довідників

POST /api/v1/nova-poshta/directories/sync

14.4. Пошук міст

GET /api/v1/nova-poshta/cities?query=Київ

14.5. Пошук відділень

GET /api/v1/nova-poshta/warehouses?city_ref={city_ref}

14.6. Розрахунок вартості доставки

POST /api/v1/nova-poshta/delivery/calculate-price

14.7. Розрахунок дати доставки

POST /api/v1/nova-poshta/delivery/calculate-date

14.8. Створення експрес-накладної

POST /api/v1/nova-poshta/internet-documents

14.9. Оновлення експрес-накладної

PATCH /api/v1/nova-poshta/internet-documents/{document_id}

14.10. Скасування / видалення експрес-накладної

POST /api/v1/nova-poshta/internet-documents/{document_id}/cancel

14.11. Друк маркування

GET /api/v1/nova-poshta/internet-documents/{document_id}/print-form

14.12. Синхронізація статусів

POST /api/v1/nova-poshta/tracking/sync

14.13. Створення реєстру

POST /api/v1/nova-poshta/scan-sheets

14.14. Dashboard

GET /api/v1/nova-poshta/dashboard?date_from=2026-05-01&date_to=2026-05-31

15. Приклад запиту на створення ЕН

{
  "external_order_id": "K2-ORDER-2026-000123",
  "idempotency_key": "K2-ORDER-2026-000123-np-v1",
  "sender": {
    "counterparty_ref": "sender-counterparty-ref",
    "contact_ref": "sender-contact-ref",
    "city_ref": "sender-city-ref",
    "warehouse_ref": "sender-warehouse-ref",
    "phone": "+380501112233"
  },
  "recipient": {
    "first_name": "Іван",
    "middle_name": "Іванович",
    "last_name": "Петренко",
    "phone": "+380671112233",
    "city_ref": "recipient-city-ref",
    "warehouse_ref": "recipient-warehouse-ref"
  },
  "delivery": {
    "service_type": "WarehouseWarehouse",
    "cargo_type": "Parcel",
    "description": "Одяг",
    "cost": 1500.00,
    "seats_amount": 1,
    "weight": 2.5,
    "volume_general": 0.01,
    "payer_type": "Recipient",
    "payment_method": "Cash"
  },
  "backward_delivery": {
    "enabled": true,
    "amount": 1500.00,
    "payer": "Recipient"
  }
}

16. Валідація перед створенням ЕН

Перед створенням експрес-накладної система повинна перевірити:

  • наявність external_order_id;
  • наявність idempotency_key;
  • чи не створена вже ЕН для цього замовлення;
  • API Key активний;
  • місто відправника існує;
  • місто отримувача існує;
  • відділення або поштомат існує;
  • відділення активне;
  • телефон отримувача валідний;
  • ПІБ отримувача заповнено;
  • вага більше 0;
  • кількість місць більше 0;
  • оголошена вартість більше або дорівнює 0;
  • тип сервісу сумісний із адресними даними;
  • післяплата не перевищує правила бізнесу;
  • платник доставки визначений;
  • форма оплати визначена;
  • опис вантажу заповнений.

Критично важливо: якщо ЕН уже створена, повторний запит не повинен створювати нову ЕН. Система повинна повернути існуючу ЕН та її поточний статус.

17. Довідники Нової пошти

17.1. Довідник міст

Довідник міст потрібен для вибору коректного `CityRef`.

Поле Опис
Ref Унікальний ідентифікатор міста в Новій пошті.
Description Назва українською.
DescriptionRu Назва російською, якщо доступна.
Area Область.
SettlementTypeDescription Тип населеного пункту.
IsBranch Ознака наявності відділень, якщо доступна.

У відкритій документації API метод `getCities` у моделі `Address` описується як метод отримання довідника населених пунктів; там же зазначено рекомендацію зберігати копію довідників на стороні клієнта й оновлювати її раз на добу. :contentReference[oaicite:3]{index=3}

17.2. Довідник відділень і поштоматів

Потрібно зберігати:

  • Ref відділення;
  • номер відділення;
  • назву;
  • адресу;
  • місто;
  • тип відділення;
  • максимальну вагу;
  • ознаку поштомата;
  • графік роботи;
  • координати;
  • ознаку активності.

17.3. Довідник вулиць

Для адресної доставки потрібно підтримати пошук вулиць за містом.

17.4. Графік оновлення довідників

Довідник Частота оновлення Коментар
Міста 1 раз на добу Базовий довідник.
Відділення 1 раз на добу або частіше Важливо для актуальності активних відділень.
Поштомати 1 раз на добу або частіше Потрібно враховувати активність і обмеження.
Вулиці За потреби або кешуванням Може бути великий обсяг.
Загальні довідники 1 раз на добу Типи вантажів, сервісів, оплат.

18. Дедублікація

Система повинна не допускати дублювання ЕН.

Ключі дедублікації:

Ключ Призначення
external_order_id ID замовлення в K2 ERP.
idempotency_key Унікальний ключ конкретної спроби створення ЕН.
np_document_ref Ref експрес-накладної в API.
np_document_number Номер ЕН / ТТН.
document_hash Hash основних параметрів відправлення.

Приклад hash:

sha256(external_order_id + recipient_phone + city_ref + warehouse_ref + cost + weight)

19. Черга створення ЕН

19.1. Логіка черги

1. K2 ERP створює замовлення.
2. Користувач натискає «Створити ЕН» або спрацьовує автоматичне правило.
3. Python-сервіс виконує валідацію.
4. Створюється запис delivery_order зі статусом PENDING_CREATE.
5. Worker викликає API Нової пошти.
6. API повертає Ref і номер ЕН.
7. Python-сервіс зберігає номер ЕН.
8. K2 ERP отримує номер ЕН.
9. Print Service отримує маркування.
10. Tracking Worker оновлює статуси доставки.

19.2. Пріоритети задач

Тип задачі Пріоритет Коментар
Створення ЕН Високий Основний процес відвантаження.
Друк маркування Високий Потрібно для складу.
Скасування ЕН Високий Важливо до передачі посилки.
Створення реєстру Середній Групова операція.
Синхронізація статусів Середній Фоновий процес.
Оновлення довідників Низький Регламентна задача.

20. Модель даних

20.1. nova_poshta_integrations

Поле Тип Опис
id uuid ID інтеграції.
provider varchar nova_poshta.
name varchar Назва інтеграції.
base_url varchar URL API.
api_key_encrypted text Зашифрований API Key.
default_sender_ref varchar Відправник за замовчуванням.
default_contact_ref varchar Контакт за замовчуванням.
default_city_ref varchar Місто відправника.
default_warehouse_ref varchar Відділення відправника.
is_active boolean Активність.
created_at timestamp Дата створення.
updated_at timestamp Дата оновлення.

20.2. np_cities

Поле Тип Опис
id uuid Внутрішній ID.
ref varchar Ref міста в Новій пошті.
description varchar Назва міста.
area varchar Область.
settlement_type varchar Тип населеного пункту.
is_active boolean Активність.
updated_at timestamp Дата оновлення.

20.3. np_warehouses

Поле Тип Опис
id uuid Внутрішній ID.
ref varchar Ref відділення.
city_ref varchar Ref міста.
number varchar Номер відділення.
description varchar Назва / опис.
address text Адреса.
warehouse_type varchar Тип відділення.
max_weight numeric Максимальна вага.
latitude numeric Широта.
longitude numeric Довгота.
schedule jsonb Графік роботи.
is_active boolean Активність.

20.4. np_delivery_orders

Поле Тип Опис
id uuid ID доставки.
external_order_id varchar ID замовлення K2 ERP.
idempotency_key varchar Ключ дедублікації.
np_document_ref varchar Ref ЕН.
np_document_number varchar Номер ЕН / ТТН.
service_type varchar Тип доставки.
cargo_type varchar Тип вантажу.
sender_ref varchar Відправник.
recipient_ref varchar Отримувач, якщо створений.
recipient_name varchar ПІБ отримувача.
recipient_phone varchar Телефон отримувача.
recipient_city_ref varchar Місто отримувача.
recipient_warehouse_ref varchar Відділення / поштомат.
recipient_address text Адреса для кур'єрської доставки.
seats_amount integer Кількість місць.
weight numeric Вага.
volume_general numeric Об'єм.
cost numeric Оголошена вартість.
delivery_price numeric Розрахована вартість доставки.
payer_type varchar Платник доставки.
payment_method varchar Форма оплати.
backward_delivery_amount numeric Сума післяплати.
status varchar Статус K2 ERP.
np_status varchar Оригінальний статус Нової пошти.
raw_request jsonb Запит.
raw_response jsonb Відповідь.
error_message text Помилка.
created_at timestamp Дата створення.
sent_at timestamp Дата створення ЕН.
delivered_at timestamp Дата доставки.

20.5. np_scan_sheets

Поле Тип Опис
id uuid ID реєстру.
np_scan_sheet_ref varchar Ref реєстру в Новій пошті.
number varchar Номер реєстру.
status varchar Статус.
documents_count integer Кількість ЕН.
raw_response jsonb Відповідь API.
created_at timestamp Дата створення.

20.6. np_events

Поле Тип Опис
id uuid ID події.
entity_type varchar integration, order, document, scan_sheet, directory.
entity_id uuid ID сутності.
event_type varchar Тип події.
old_status varchar Попередній статус.
new_status varchar Новий статус.
source varchar K2_ERP, PYTHON_SERVICE, NOVA_POSHTA, USER.
payload jsonb Технічні дані.
created_at timestamp Дата події.

21. Приклад Python-логіки

21.1. Базовий API-клієнт

import httpx


class NovaPoshtaApiError(Exception):
    pass


class NovaPoshtaClient:
    def __init__(self, base_url: str, api_key: str, timeout_seconds: int = 30):
        self.base_url = base_url
        self.api_key = api_key
        self.timeout_seconds = timeout_seconds

    async def call_api(
        self,
        model_name: str,
        called_method: str,
        properties: dict | None = None,
    ) -> dict:
        payload = {
            "apiKey": self.api_key,
            "modelName": model_name,
            "calledMethod": called_method,
            "methodProperties": properties or {},
        }

        async with httpx.AsyncClient(timeout=self.timeout_seconds) as client:
            response = await client.post(self.base_url, json=payload)
            response.raise_for_status()

        data = response.json()

        if not data.get("success"):
            raise NovaPoshtaApiError(str(data.get("errors") or data))

        return data

21.2. Створення ЕН

async def create_np_document(command: "CreateNpDocumentCommand", db: "Session") -> "NpDeliveryOrder":
    existing = np_order_repository.get_by_idempotency_key(
        db=db,
        idempotency_key=command.idempotency_key,
    )

    if existing:
        return existing

    np_validator.validate(command)

    order = np_order_repository.create(
        db=db,
        data={
            "external_order_id": command.external_order_id,
            "idempotency_key": command.idempotency_key,
            "status": "PENDING_CREATE",
            "recipient_name": command.recipient.full_name,
            "recipient_phone": command.recipient.phone,
            "recipient_city_ref": command.recipient.city_ref,
            "recipient_warehouse_ref": command.recipient.warehouse_ref,
            "service_type": command.delivery.service_type,
            "cargo_type": command.delivery.cargo_type,
            "weight": command.delivery.weight,
            "cost": command.delivery.cost,
            "raw_request": command.model_dump(),
        },
    )

    delivery_queue.enqueue(
        task_name="send_np_document",
        payload={"delivery_order_id": str(order.id)},
    )

    audit_logger.log(
        entity_type="np_delivery_order",
        entity_id=order.id,
        event_type="NP_DOCUMENT_QUEUED",
        new_status="PENDING_CREATE",
        payload={"external_order_id": command.external_order_id},
    )

    db.commit()
    return order

21.3. Worker створення ЕН

async def send_np_document(delivery_order_id: str, db: "Session") -> None:
    order = np_order_repository.get_by_id(db, delivery_order_id)

    if order.status in ["CREATED", "DELIVERED"] and order.np_document_number:
        return

    try:
        order.status = "CREATING"
        db.commit()

        payload = np_mapper.to_internet_document_payload(order)

        response = await nova_poshta_client.call_api(
            model_name="InternetDocument",
            called_method="save",
            properties=payload,
        )

        document_data = response["data"][0]

        order.np_document_ref = document_data.get("Ref")
        order.np_document_number = document_data.get("IntDocNumber")
        order.status = "CREATED"
        order.raw_response = response
        order.sent_at = utc_now()

        audit_logger.log(
            entity_type="np_delivery_order",
            entity_id=order.id,
            event_type="NP_DOCUMENT_CREATED",
            old_status="CREATING",
            new_status="CREATED",
            payload={
                "np_document_ref": order.np_document_ref,
                "np_document_number": order.np_document_number,
            },
        )

    except TemporaryNovaPoshtaError as exc:
        order.status = "NEEDS_RETRY"
        order.error_message = str(exc)

    except Exception as exc:
        order.status = "ERROR"
        order.error_message = str(exc)

    finally:
        db.commit()

21.4. Синхронізація статусів

async def sync_np_statuses(document_numbers: list[str], db: "Session") -> None:
    response = await nova_poshta_client.call_api(
        model_name="TrackingDocument",
        called_method="getStatusDocuments",
        properties={
            "Documents": [
                {"DocumentNumber": number}
                for number in document_numbers
            ]
        },
    )

    for item in response.get("data", []):
        number = item.get("Number")
        order = np_order_repository.get_by_document_number(db, number)

        if not order:
            continue

        old_status = order.status
        new_status = np_status_mapper.from_np(item)

        if old_status != new_status:
            order.status = new_status
            order.np_status = item.get("Status")

            if new_status == "DELIVERED":
                order.delivered_at = utc_now()

            audit_logger.log(
                entity_type="np_delivery_order",
                entity_id=order.id,
                event_type="NP_STATUS_SYNCED",
                old_status=old_status,
                new_status=new_status,
                payload=item,
            )

    db.commit()

22. Обробка помилок

22.1. Типи помилок

Тип помилки Опис Дія системи
ValidationError Некоректні дані замовлення. Не створювати ЕН, показати список помилок.
AuthError Невірний API Key. Зупинити інтеграцію, повідомити адміністратора.
CityNotFoundError Місто не знайдено. Перевести в NEEDS_CORRECTION.
WarehouseNotFoundError Відділення або поштомат не знайдено. Перевести в NEEDS_CORRECTION.
PhoneValidationError Некоректний телефон отримувача. Перевести в NEEDS_CORRECTION.
DeliveryCalculationError Не вдалося розрахувати доставку. Показати менеджеру.
ApiError API повернув помилку. Зберегти raw-відповідь.
TimeoutError Перевищено час очікування. Перевести в NEEDS_RETRY.
DuplicateDocumentError ЕН уже створено. Повернути існуючу ЕН.
TrackingError Не вдалося отримати статус. Повторити фоново.

22.2. Retry-логіка

Retry дозволений для:

  • timeout;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасової недоступності API;
  • тимчасової помилки друку маркування;
  • тимчасової помилки синхронізації статусів.

Retry заборонений для:

  • неправильного API Key;
  • помилок валідації;
  • неправильного міста;
  • неправильного відділення;
  • некоректного телефону;
  • ЕН, яка вже створена;
  • ЕН, яка вже доставлена;
  • ЕН, яка вже скасована.

23. Dashboard менеджера і керівника

23.1. Основні KPI

KPI Опис Колір
Замовлень до відправки Замовлення без ЕН. Увага
ЕН створено Кількість створених ЕН. Норма
Маркування надруковано Готові до пакування відправлення. Норма
У дорозі Відправлення в транспортуванні. В роботі
Прибуло Очікує отримувача. Контроль
Доставлено Успішні доставки. Норма
Відмова Отримувач відмовився. Критично
Повернення Посилки повертаються. Потрібна дія
Помилки API Помилки створення або статусів. Критично

23.2. Приклад dashboard

Показник Значення Стан
Замовлень до відправки 84 Увага
ЕН створено сьогодні 312 Норма
Маркування надруковано 298 Норма
У дорозі 1270 В роботі
Прибуло у відділення 240 Контроль
Доставлено 980 Норма
Відмова 18 Критично
Повернення 35 Потрібна дія
Помилки створення ЕН 6 Критично

23.3. Проблемні відправлення

Дата Замовлення ЕН Отримувач Статус Причина Дія
07.05.2026 K2-ORDER-123 - Іван Петренко Помилка Не знайдено відділення Виправити адресу
07.05.2026 K2-ORDER-124 20450000000000 Олена Сидоренко Відмова Відмова отримувача Зв'язатися з клієнтом
07.05.2026 K2-ORDER-125 20450000000001 ТОВ «Альфа» Повернення Не отримано вчасно Контроль повернення

24. Безпека

Система повинна забезпечити:

  • зберігання API Key тільки у secret storage або в зашифрованому вигляді;
  • заборону логування API Key;
  • HTTPS для всіх API-запитів;
  • перевірку SSL;
  • рольову модель доступу;
  • окремі права на створення ЕН;
  • окремі права на скасування ЕН;
  • окремі права на друк маркувань;
  • окремі права на формування реєстрів;
  • журнал усіх дій;
  • захист від дублювання ЕН;
  • маскування телефонів отримувачів у логах;
  • контроль доступу до персональних даних.

25. Логування та аудит

Система повинна логувати:

Подія Що зберігати
Створення запиту на ЕН Замовлення, отримувач, місто, відділення, сума.
Валідація Результат, список помилок.
Розрахунок доставки Параметри, вартість, дата.
Створення ЕН Номер ЕН, Ref, дата, відповідь API.
Друк маркування Хто надрукував, коли, формат.
Створення реєстру Номер реєстру, список ЕН.
Отримання статусу Старий статус, новий статус, джерело.
Помилка API Код, повідомлення, raw-відповідь.
Повторна операція Хто запустив, причина, результат.
Скасування ЕН Хто скасував, причина.

26. Acceptance Criteria

26.1. Інтеграція

Критерій Очікуваний результат
AC-1 Адміністратор створює інтеграцію Нової пошти. Інтеграція зберігається в системі.
AC-2 Адміністратор перевіряє підключення. Система повертає успішний або помилковий статус.
AC-3 API Key неправильний. Система показує AuthError і не створює ЕН.

26.2. Довідники

Критерій Очікуваний результат
AC-4 Система запускає синхронізацію міст. Довідник міст оновлюється.
AC-5 Система запускає синхронізацію відділень. Довідник відділень оновлюється.
AC-6 Відділення стало неактивним. Його не можна вибрати для нових ЕН.

26.3. Створення ЕН

Критерій Очікуваний результат
AC-7 K2 ERP передає валідне замовлення. Python-сервіс створює ЕН.
AC-8 API повертає номер ЕН. Номер зберігається в K2 ERP.
AC-9 Повторний запит має той самий idempotency_key. Друга ЕН не створюється.
AC-10 Відділення не знайдено. ЕН не створюється, статус NEEDS_CORRECTION.

26.4. Друк і реєстри

Критерій Очікуваний результат
AC-11 Користувач натискає «Друк маркування». Система повертає PDF або інший доступний формат.
AC-12 Користувач формує реєстр. ЕН додаються до реєстру.
AC-13 ЕН уже в реєстрі. Повторне додавання блокується або обробляється за правилом.

26.5. Статуси

Критерій Очікуваний результат
AC-14 Tracking API повертає новий статус. K2 ERP оновлює статус відправлення.
AC-15 Відправлення доставлено. Статус стає DELIVERED і підсвічується зеленим.
AC-16 Отримувач відмовився. Статус стає REFUSED і підсвічується червоним.
AC-17 Відправлення повертається. Статус стає RETURNING і підсвічується помаранчевим.

26.6. Dashboard

Критерій Очікуваний результат
AC-18 Менеджер відкриває dashboard. Він бачить замовлення, ЕН, доставки, відмови, повернення та помилки.
AC-19 Є помилки створення ЕН. Вони підсвічуються червоним.
AC-20 Є повернення. Вони підсвічуються помаранчевим.

27. MVP

До MVP входить:

  • створення інтеграції Нової пошти;
  • перевірка API Key;
  • синхронізація міст;
  • синхронізація відділень;
  • пошук міст і відділень;
  • розрахунок вартості доставки;
  • створення ЕН;
  • збереження номера ЕН;
  • друк маркування;
  • синхронізація статусів;
  • дедублікація;
  • retry-механізм;
  • журнал подій;
  • dashboard API;
  • базові unit-тести;
  • mock API для інтеграційних тестів.

До MVP не входить:

  • повна підтримка всіх додаткових послуг;
  • складна робота з міжнародною доставкою;
  • повна автоматизація післяплати;
  • автоматичне створення всіх типів контрагентів;
  • складний UI складу;
  • інтеграція з NovaPay;
  • власна система доставки замість API Нової пошти.

28. Етапи реалізації

Етап 1. Аналіз API Нової пошти

  • отримати API Key;
  • перевірити доступ до API;
  • отримати актуальну документацію;
  • перевірити моделі Address, InternetDocument, TrackingDocument, ScanSheet;
  • перевірити розрахунок вартості;
  • перевірити створення тестової ЕН;
  • перевірити друк маркування.

Етап 2. Базовий Python-сервіс

  • створити FastAPI-проєкт;
  • налаштувати PostgreSQL;
  • створити моделі інтеграції, довідників, ЕН, подій;
  • налаштувати Alembic;
  • реалізувати healthcheck.

Етап 3. Nova Poshta Client

  • реалізувати call_api;
  • реалізувати get_cities;
  • реалізувати get_warehouses;
  • реалізувати get_document_price;
  • реалізувати get_document_delivery_date;
  • реалізувати create_internet_document;
  • реалізувати get_tracking_statuses;
  • реалізувати get_print_form;
  • реалізувати create_scan_sheet;
  • реалізувати обробку помилок.

Етап 4. Довідники

  • реалізувати синхронізацію міст;
  • реалізувати синхронізацію відділень;
  • реалізувати пошук;
  • реалізувати кешування;
  • реалізувати регламентне оновлення.

Етап 5. ЕН і валідація

  • реалізувати створення ЕН;
  • реалізувати мапінг K2 ERP → API Нової пошти;
  • реалізувати валідацію;
  • реалізувати hash документа;
  • реалізувати дедублікацію.

Етап 6. Статуси та друк

  • реалізувати синхронізацію статусів;
  • реалізувати друк маркування;
  • реалізувати реєстри;
  • реалізувати retry.

Етап 7. Dashboard та аудит

  • реалізувати dashboard API;
  • реалізувати список проблемних відправлень;
  • реалізувати фільтри;
  • реалізувати експорт, якщо потрібно.

Етап 8. Production hardening

  • додати rate limiting;
  • додати моніторинг;
  • додати alerting;
  • додати dead letter queue;
  • додати резервне копіювання;
  • додати безпечне зберігання секретів.

29. Ризики

Ризик Опис Як зменшити
Неправильний API Key Інтеграція не працюватиме. Check-connection і повідомлення адміністратору.
Застарілі довідники Користувач може обрати неактивне відділення. Оновлювати довідники щодня або частіше.
Дублювання ЕН Повторний запит може створити другу накладну. Idempotency key і перевірка external_order_id.
Неправильний телефон API може відхилити ЕН. Валідація номера до відправки.
Неправильна вага / габарити Вартість доставки буде некоректна. Валідація параметрів вантажу.
Зміна API Можуть змінитись методи або поля. Версіонування клієнта і contract-тести.
Недоступність API ЕН не створюються. Черга, retry, dashboard помилок.
Повернення не контролюються Менеджер може пропустити повернення. Окрема шахматка повернень і статусів.

30. Відкриті питання

  1. Який бізнес-кабінет і API Key використовуються?
  2. Чи потрібно підтримувати декілька відправників?
  3. Чи потрібно підтримувати декілька складів?
  4. Чи потрібна доставка у поштомати?
  5. Чи потрібна адресна доставка?
  6. Чи потрібна післяплата?
  7. Чи потрібна інтеграція з NovaPay?
  8. Чи потрібно створювати контрагентів через API?
  9. Чи потрібно автоматично друкувати маркування після створення ЕН?
  10. Який формат друку потрібен: A4, термопринтер, PDF, Zebra?
  11. Чи потрібно формувати реєстри?
  12. Як часто синхронізувати статуси?
  13. Чи потрібно показувати строк зберігання у відділенні?
  14. Чи потрібно автоматично сповіщати клієнта?
  15. Чи потрібно підтримувати міжнародну доставку?
  16. Чи потрібна інтеграція з K2 ERP документами реалізації та оплат?

31. Джерела

  • Офіційна сторінка інтеграції Нової пошти для бізнесу.
  • API Portal Nova Post.
  • Офіційна документація API Нової пошти в кабінеті / API-порталі.
  • Довідники API: міста, відділення, типи сервісів, типи вантажів.
  • Документація моделей Address, InternetDocument, TrackingDocument, Counterparty, ContactPerson, ScanSheet.

32. Див. також