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

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

Матеріал з K2 ERP Wiki

! ! |- | recipient_client_id | uuid | Клієнт-одержувач. |- | Внутрішні листи | Окремий API-сценарій для листів. |- | AC-20 | виступає як повернення. Реальні URI API потрібно брати з актуальної Swagger-документації Укрпошти. | Потрібен для UI та валідації. |- | sms_enabled | boolean | Чи замовлено SMS. |- | Некоректна адреса | API здатна повернути помилку. |- | declared_price | numeric | Оголошена вартість. continue

if old_status != new_status:

Критично критично: user token і authorization bearer потрібно зберігати тільки в зашифрованому вигляді або secret storage. | Перевести в NEEDS_CORRECTION.=== 27.4. Друк ярлика === ! Заборонено зберігати їх у коді, Git, frontend-змінних або відкритих логах. | style="background:#eeeeee;" | Сірий |}

method=method,
def get_shipment(self, shipment_id: str) -> "ShipmentResponse":
params.setdefault("token", self.user_token)

! Критерій

  • ID або код відділення;
  • поштовий індекс;
  • назву;
  • адресу;
  • населений пункт;
  • координати, якщо доступні;
  • графік роботи;
  • ознаку активності;
  • доступні сервіси. |-

| Відстеження відправлень | Отримання статусів доставки. |- | AC-2 | Адміністратор перевіряє підключення. |}

15.8. оновлення версій відправлення

  1. Який тип договору та доступу до API застосовується для? |-

| Recipient Address | Адреса одержувача. Одержувач

"street": "Хрещатик",

|- | Внутрішня посилка | DOMESTIC_PARCEL | Відправлення по Україні. | Print count збільшується, дія логуються. Дія системи

delivery_queue.enqueue(
Статус стає UNKNOWN_STATUS і потрапляє в список ручної перевірки. | Винести в окремий етап. |- Ukrposhta Client - AC-8 - entity_type varchar - height numeric - Міжнародні відправлення Повернення, retry, неправильна адреса. |- raw_request jsonb Запит. Подія
return existing

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

Замовлень до відправки - shipment_id uuid - building varchar - Recipient Client style="background:#c8e6c9;" | Зелений
Повертається RETURNING Відправлення повертається відправнику. payload={"shipment_id": str(shipment.id)},
  • реалізувати синхронізацію статусів;
  • реалізувати друк ярлика;
  • реалізувати retry;
  • реалізувати збереження PDF. |-
Скасування відправлення Високий - Sender Client - Невідомі статуси - PostcodeError інтеграційні функції ERP зберігається в системі. | Довідник відділень оновлюється. №
"postpay_enabled": command.delivery.postpay_enabled,
path: str,
shipment.status = "CREATED"
"external_order_id": command.external_order_id,
sender_address = await address_service.ensure_sender_address(shipment)

Python-сервіс:


=== 15.7. Створення відправлення ===
=== 22.4. Синхронізація статусів ===
 sender_client=sender_client,

! |-
| AC-19
| виступає як помилки створення відправлень. Дія

1. | Перевести в NEEDS_CORRECTION. Поле
 "recipient": {

 "address_id": "sender-address-id",
 try:

 audit_logger.log(
 db.commit()

10. | style="background:#fff9c4;" | Додаткова
|-
| Група відправлень
| SHIPMENT_GROUP
| Пакетна передача декількох відправлень. №

<syntaxhighlight lang="python">

* менеджер;
* комірник;
* оператор складу. Стан
=== 13.1. Призначення ===

 if response.content:

=== 15.12. Dashboard ===
[[Категорія:Технічні завдання]]
K2 ERP / Dashboard / складський облік / Менеджер

! | базовий сценарій для MVP. def track_shipments(self, barcodes: list [str]) -> "TrackingListResponse":

* PDF або інший формат, який повертає API;
* файл зберігається у картці відправлення;
* статус змінюється на LABEL_PRINTED;
* дія логуються в аудиті.=== 21.3. ukrposhta_clients ===

<syntaxhighlight lang="python">
 old_status=old_status,
 "client_id": "sender-client-id",
!<pre>

 return {}

 url=f"{self.base_url}/{path.lstrip('/')}",

API Укрпошти має окрему документацію для внутрішніх листів. | style="background:#fff9c4;" | Увага
|-
| Відправлень створено
| Кількість створених відправлень. Дата
 def create_shipment_group(self, payload: "ShipmentGroupPayload") -> "ShipmentGroupResponse":
щоб контролювати якість логістики, повернення, затримки та помилки. | style="background:#bbdefb;" | Блакитний
|-
| У дорозі
| IN_TRANSIT
| Відправлення рухається. |-
| new_status
| varchar
| Новий статус. # Як часто синхронізувати статуси? pass

"postcode": "01001",
shipment.raw_response = response.raw_payload

щоб наклеїти його на посилку. |-

Фіолетовий #f3e5f5 Спеціальний або невідомий статус. SEO-опис
pass

! |-
| Некоректний індекс
| Відправлення здатна не створитись. |-
| print_count
| integer
| Кількість друків. KPI
== 28. MVP ==
 user_token: str,
 "building": "10",
 }
 new_status="CREATED",
 payload={"external_order_id": command.external_order_id},
{| class="wikitable"
 except Exception as exc:
 "city": "Львів",
=== 23.1. Типи помилок ===
 existing = shipment_repository.get_by_idempotency_key(
 self.bearer_token = bearer_token
=== 27.2. Довідники ===
<pre>
! | Barcode зберігається в K2 ERP. * зберігання налаштувань інтеграції;
* перевірку підключення до API;
* створення адреси відправника;
* створення адреси одержувача;
* створення клієнта-відправника;
* створення клієнта-одержувача;
* створення відправлення або групи відправлень;
* друк супровідних документів / ярликів;
* розрахунок вартості доставки, якщо підтримується API;
* перевірку доступності маршруту доставки;
* пошук поштових індексів;
* пошук відділень;
* отримання статусів відправлень;
* синхронізацію статусів назад у K2 ERP;
* підтримку внутрішніх відправлень по Україні;
* підтримку міжнародних відправлень як окремого сценарію;
* журналювання всіх API-запитів;
* dashboard для контролю логістики. |-
| TrackingError
| Не вдалося отримати статус. |}

на `REGISTERED` виступає ключовою рисою У документації для міжнародних відправлень описується lifecycle із полями `status` та `statusDate`; після створення статус змінюється на `CREATED`, а після реєстрації. | Address classifier і ручна перевірка. | платформа повертає успішний або помилковий статус. | style="background:#fff9c4;" | Жовтий
|-
| Створюється
| CREATING
| Виконується API-запит до Укрпошти. |-
| Directory Sync Worker
| Оновлює адресний класифікатор, індекси, відділення. |-
| Дублювання відправлень
| Повторний запит здатна створити друге відправлення.

Як керівник,

6.1. Створення відправлення з K2 ERP

"declared_price": command.delivery.declared_price,
pass

21.6. ukrposhta_events

Integration Account - postcode varchar Поштовий індекс. "first_name": "Іван", Замовлення }

платформа повинна не допускати дублювання відправлень. Label Service отримує супровідний ярлик. До MVP не входить:

v
new_status=new_status,

21.5. ukrposhta_labels

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

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

ValidationError Некоректні інформаційні дані замовлення.
Він бачить замовлення, відправлення, доставки, повернення та помилки. Очікуваний результат

21.4. ukrposhta_shipments

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

Зелений #c8e6c9 - created_at timestamp - Друк ярлика }

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

error_message text Помилка. )
db: "Session",

POST /api/v1/ukrposhta/integrations

- AC-11 користувач системи натискає «Друк ярлика». SEO-опис Check-connection і повідомлення адміністратору.</syntaxhighlight>
"street": "Січових Стрільців",

Як комірник,

shipment.status = "NEEDS_RETRY"
критично: для роботи з API Укрпошти використовуються user token та authorization bearer, які потрібно отримати після підписання договору.
! |-
| file_id
| uuid
| Файл у сховищі. self.timeout_seconds = timeout_seconds
! # Чи потрібна післяплата? |}

 }

{| class="wikitable"
 shipment.sent_at = utc_now()
 def create_address(self, payload: "AddressPayload") -> "AddressResponse":

 new_status="PENDING_CREATE",

 )

 shipment=shipment,
я хочу надрукувати супровідний ярлик по створеному відправленню, 
UKRPOSHTA_LABEL_BASE_URL=https://www.ukrposhta.ua/ecom/0.0.1/
=== Етап 6. Статуси та друк ===
=== 21.2. ukrposhta_addresses ===
 verify_ssl: bool = True
 timeout_seconds: int = 30
'''критично:''' методи Python-клієнта виступає як внутрішньою абстракцією. |-
| Swagger
| Технічна документація API. | Черга, API-статуси, транспортування. |-
| ukrposhta_status
| varchar
| Оригінальний статус API. SEO-опис

! SEO-опис
 self.user_token = user_token
 v
<pre>
|-
| AC-4
| платформа запускає синхронізацію індексів. Очікуваний результат
async def send_ukrposhta_shipment(shipment_id: str, db: "Session") -> None:

 entity_id=shipment.id,

UKRPOSHTA_BEARER_TOKEN=********
== 31. Відкриті питання ==
=== Етап 3. Ukrposhta Client ===
! |-
| Створення відправлення
| Shipment ID, barcode, дата, відповідь API. | style="background:#bbdefb;" | Групова
|}

{| class="wikitable"

 "building": "1",
 if existing:
 )
POST /api/v1/ukrposhta/shipments
 def track_shipment(self, barcode: str) -> "TrackingResponse":
|-
| Чернетка
| DRAFT
| Замовлення виступає як в K2 ERP, але відправлення ще не створено. !=== 8.4. Dashboard керівника ===

* створити FastAPI-проєкт;
* налаштувати PostgreSQL;
* створити моделі інтеграції, адрес, клієнтів, відправлень, ярликів, подій;
* налаштувати Alembic;
* реалізувати healthcheck. ! |-
| Помилка API
| Код, повідомлення, raw-відповідь. | Не створювати відправлення, показати список помилок. |-
| payload
| jsonb
| Технічні інформаційні дані.=== 15.9. Скасування / видалення відправлення ===
{| class="wikitable"
== 18. Адресний класифікатор і довідники ==

=== 23.2. Retry-логіка ===
{| class="wikitable"
 shipment = shipment_repository.get_by_id(db, shipment_id)

 payload={

== 24. Dashboard менеджера і керівника ==
 shipment.delivered_at = utc_now()
 v

== 3. Основні функції ERP API Укрпошти ==
[[Категорія:Ukrposhta API]]

Retry заборонений для:
! SEO-опис

 def update_shipment(self, shipment_id: str, payload: "ShipmentPayload") -> "ShipmentResponse":

 }
=== 8.1. Створення відправлення ===
! Поле
 "middle_name": "Іванович",

 sender_client = await client_service.ensure_sender_client(shipment, sender_address)
<pre>

=== 22.2. Створення відправлення ===
! Замовлення, клієнт ERP, адреса, вантаж
K2 ERP / CRM / Website / WMS
 event_type="UKRPOSHTA_SHIPMENT_QUEUED",
 |
 | 2. | Потрібен для синхронізації з K2 ERP.== 10. Статуси відправлень ==

* https://dev.ukrposhta.ua/
* https://dev.ukrposhta.ua/documentation
* https://dev.ukrposhta.ua/faq
* https://dev.ukrposhta.ua/for-business
* API documentation 2025. |-
| AC-17
| API повертає невідомий статус. Розділ API

* неправильного user token;
* неправильного bearer token;
* помилок валідації;
* неправильного індексу;
* недоступного маршруту;
* некоректного телефону;
* відправлення, яке вже створене;
* відправлення, яке вже доставлене;
* відправлення, яке вже скасоване. SEO-опис

6. Критерій
платформа повинна забезпечити:
офіційний портал API Укрпошти містить такі ключові напрями:
! |-
| created_at
| timestamp
| Дата створення. Python-сервіс виконує валідацію. | style="background:#fff9c4;" | Контроль
|-
| Доставлено
| Успішні доставки.[[Категорія:Python]]

<syntaxhighlight lang="python">

* інший формат створення;
* митний SEO-опис;
* категорію вкладення;
* країну призначення;
* англомовні адресні поля;
* обмеження по вазі;
* додаткові статуси;
* друк митних або супровідних документів. | style="background:#ffcc80;" | Потрібна дія
|-
| Помилки API
| Помилки створення або статусів. Сутність
 finally:

</pre>

=== Етап 5. Відправлення і валідація ===
! Колір
 response = await client.request(

 def delete_shipment(self, shipment_id: str) -> "DeleteShipmentResponse":

 },

== 7. Основні сутності ==

 command: "CreateUkrposhtaShipmentCommand",

* перевіряє замовлення;
* перевіряє одержувача;
* перевіряє адресу та індекс;
* створює або знаходить адресу відправника;
* створює або знаходить адресу одержувача;
* створює або знаходить клієнта-відправника;
* створює або знаходить клієнта-одержувача;
* створює відправлення;
* зберігає barcode / shipment UUID / номер відправлення;
* формує супровідний ярлик;
* передає номер відправлення назад у K2 ERP. |-
| Відділення
| 1 раз на добу або за потреби
| Потрібні для вибору точки відправлення/видачі. Тип

 def get_label(self, shipment_id: str, format: str = "pdf") -> bytes:

 audit_logger.log(
 params: dict | None = None,
 self,
|-
| API Layer
| REST API для прийому замовлень і команд із K2 ERP. |-
| region
| varchar
| Область. SEO-опис
{| class="wikitable"
Як менеджер, 

 ukrposhta_validator.validate(command)
 payload=status_response.raw_payload,
<pre>
 "idempotency_key": "K2-ORDER-2026-000123-ukrposhta-v1",
POST /api/v1/ukrposhta/shipments/{shipment_id}/cancel
Приклад hash:
from pydantic_settings import BaseSettings
 def __init__(
<pre>
 status_response = await ukrposhta_client.track_shipment(barcode)
 if new_status == "DELIVERED":

<pre>
 if shipment.status in ["CREATED", "REGISTERED", "DELIVERED"] and shipment.barcode:
{| class="wikitable"

=== 24.1. Основні KPI ===
 shipment.error_message = str(exc)
</div>

 "postpay_enabled": true,
! # Чи потрібно експортувати журнал відправлень в Excel? | style="background:#ffcc80;" | Потрібна дія
|}

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

=== 15.4. Пошук індексів ===
 "height": 15,
=== 27.5. Статуси ===
 "barcode": shipment.barcode,
|-
| Замовлень до відправки
| 42
| style="background:#fff9c4;" | Увага
|-
| Відправлень створено сьогодні
| 185
| style="background:#c8e6c9;" | Норма
|-
| Ярлики надруковано
| 172
| style="background:#c8e6c9;" | Норма
|-
| У дорозі
| 620
| style="background:#bbdefb;" | В роботі
|-
| Прибуло
| 88
| style="background:#fff9c4;" | Контроль
|-
| Доставлено
| 410
| style="background:#c8e6c9;" | Норма
|-
| Повернення
| 21
| style="background:#ffcc80;" | Потрібна дія
|-
| Помилки створення
| 5
| style="background:#ef9a9a;" | Критично
|-
| Потребують виправлення
| 9
| style="background:#ffcc80;" | Потрібна дія
|}

=== 6.5. Внутрішні листи ===

Перед створенням відправлення платформа повинна перевірити:
 },
'''Критично критично:''' якщо відправлення вже створене, повторний запит не повинен створювати нове відправлення. ! Ризик
== 2. Область сценарії використання ==

</pre>
 "Authorization": f"Bearer {self.bearer_token}",
== 17. Валідація перед створенням відправлення ==
! Код
=== 15.3. Синхронізація адресних довідників ===
створення відправлень забезпечується через '''Головна ідея:''' розробити Python-сервіс, який інтегрує K2 ERP / CRM / інтернет-магазин / WMS з API Укрпошти; так само реалізовано адрес, клієнтів, друку супровідних ярликів, розрахунку вартості, трекінгу статусів і контролю доставки. Worker створює клієнта-відправника, якщо потрібно. 
3. # Чи потрібно формувати групи відправлень? |-
| AC-3
| Token неправильний. | платформа повертає PDF або інший доступний формат.=== Етап 8. Production hardening ===
! платформа повинна повернути існуючий barcode / shipment_id та його поточний статус. | Окремий сценарій із власними правилами. ! |-
| idempotency_key
| Унікальний ключ конкретної спроби створення відправлення. # Чи потрібно підтримувати декілька відправників? | Перевести в NEEDS_RETRY. |-
| raw_response
| jsonb
| Відповідь API. # Який формат друку потрібен: A4, термопринтер, PDF? | style="background:#c8e6c9;" | Зелений
|-
| Ярлик надруковано
| LABEL_PRINTED
| Супровідний ярлик отримано або надруковано. Worker створює адресу відправника, якщо її ще немає. | платформа показує AuthError і не створює відправлення. |-
| Address Classifier
| Адресний класифікатор. |-
| shipment_id
| varchar
| ID відправлення в API Укрпошти. | Черга, retry, dashboard помилок. SEO-опис

import httpx

Метою задачі виступає як створення Python-сервісу для інтеграції з Укрпоштою з метою автоматизації процесів доставки. |-
| event_type
| varchar
| Тип події. |-
| Міжнародні відправлення складніші
| Потрібні митні й країнові поля. SEO-опис
Результат:
Python Ukrposhta Integration Service

{| class="wikitable"

 "phone": "+380501112233",
! "phone": "+380671112233",

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

</pre>

 pass

[[Категорія:Логістика]]
 entity_type="ukrposhta_shipment",


 retry_backoff_seconds: int = 5
 pass


UKRPOSHTA_LANGUAGE=ua
POST /api/v1/ukrposhta/routes/check-availability
 response = await ukrposhta_client.create_shipment(payload)
== 16. Приклад запиту на створення відправлення ==
== Див. 33. так само ==
 pass
 db=db,
13. |-
| AC-5
| платформа запускає синхронізацію відділень. |-
| Shipment Group
| Група відправлень. |-
| Адресний класифікатор
| 1 раз на добу або за регламентом
| здатна бути великим довідником. |-
| district
| varchar
| Район. Worker створює адресу одержувача. 
 "apartment": "5"
 shipment.ukrposhta_status = status_response.status
=== Етап 4. Адреси та клієнти ===
'''Для K2 ERP:''' цей workflow потрібно приховати від користувача. Колір

 "last_name": "Петренко",
 "length": 30,
<pre>

GET /api/v1/ukrposhta/shipments/{shipment_id}/label

 "region": "Київська",
<pre>
 shipment.status = new_status

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

<syntaxhighlight lang="python">
До MVP входить:
 db=db,

 return response.json()

 json: dict | None = None,
{| class="wikitable"
 bearer_token: str,

 "sms": true

! |-
| Типи відправлень
| 1 раз на добу або після зміни API
| Потрібні для валідації. Критерій
|-
| AC-7
| K2 ERP передає валідне замовлення. | Валідація індексу до API-запиту. | Повернути існуюче відправлення. |-
| client_type
| varchar
| sender або recipient. # Чи потрібна інтеграційні функції ERP з K2 ERP документами реалізації та оплат? Критерій
'''Управлінський результат:''' менеджер, складський облік і керівник повинні бачити, скільки відправлень створено, скільки ярликів надруковано, які посилки доставлені, які повертаються, які мають помилки адреси, індексу, оплати або статусу. |-
| Зміна API
| Можуть змінитись URI або поля. Очікуваний результат
 ):
== 15. API Python-сервісу ==
== 19. Дедублікація ==
=== 27.3. Створення відправлення ===
 entity_type="ukrposhta_shipment",
Ukrposhta API Client
 language: str = "ua"
! |-
| Недоступність API
| Відправлення не створюються. |-
| PhoneValidationError
| Некоректний телефон одержувача. Що зберігати
 params = params or {}

 "address": {
 shipment = shipment_repository.create(

! |}

{| class="wikitable"

! |}

 "shipment_type": command.shipment_type,

 shipment = shipment_repository.get_by_barcode(db, barcode)
__TOC__
 }
<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">
|-
| id
| uuid
| ID ярлика. | здатна бути окремим модулем. |-
| source
| varchar
| K2_ERP, PYTHON_SERVICE, UKRPOSHTA, USER. |}

<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">

 except TemporaryUkrposhtaError as exc:
POST /api/v1/ukrposhta/directories/sync
== 32. Джерела ==
! "city": "Київ",

<pre>

! |-
| style="background:#ef9a9a;" | Червоний
| #ef9a9a
| Помилка або негативний результат. ! |-
| user_token_encrypted
| text
| Зашифрований user token. |-
| TimeoutError
| Перевищено час очікування. "declared_price": 1500.00,

 "shipment_type": "DOMESTIC_PARCEL",

 "description": "Одяг",
 def create_shipment(self, payload: "ShipmentPayload") -> "ShipmentResponse":
12. | Повторити фоново. |-
| street
| varchar
| Вулиця. |-
| Dashboard API
| інформаційні дані для менеджера, складу та керівника. | style="background:#ef9a9a;" | Критично
|-
| Потребують виправлення
| Некоректні адреси, індекси, телефони. Worker створює клієнта-одержувача. |-
| style="background:#bbdefb;" | Блакитний
| #bbdefb
| операційна дія виконується або доставка в процесі. | Відправлення не створюється без виправлення. SEO-опис

* індекс;
* область;
* район;
* населений пункт;
* вулицю, якщо доступна;
* відділення, якщо прив'язане;
* ознаку активності;
* дату оновлення версій. |-
| is_active
| boolean
| Активність. | Статус стає RETURNING і підсвічується помаранчевим. Призначення

=== 6.2. Друк ярлика ===
! Де застосовується для
</div>
 "shipment_id": shipment.shipment_id,

{| class="wikitable"
 if not shipment:
Потрібно зберігати:
{| class="wikitable"
Retry дозволений для:
{
 "address": {
{{DISPLAYTITLE:Технічне завдання: Інтеграція з Укрпоштою для Python}}
я хочу натиснути кнопку «Створити відправлення Укрпошта», 
{| class="wikitable"
4. |-
| Пошук відділень та індексів
| Пошук індексів, відділень, адресних даних.</pre>
POST /api/v1/ukrposhta/tracking/sync
== 26. Логування та аудит ==
|-
| Поштові індекси
| 1 раз на добу або за потреби
| Потрібні для валідації адрес. recipient_address = await address_service.ensure_recipient_address(shipment)

 user_token: str
 payload = ukrposhta_mapper.to_shipment_payload(
[[Категорія:Доставка]]

2. |-
| AuthError
| Невірний user token або bearer token. Як зменшити
|-
| Неправильний token
| інтеграційні функції ERP не працюватиме. |}

Ukrposhta Client  це Python-клас або пакет, який інкапсулює роботу з API Укрпошти. # Чи потрібно зберігати адреси одержувачів у K2 ERP? |-
| delivered_at
| timestamp
| Дата доставки. Призначення

{| class="wikitable"
 )

Після створення відправлення платформа повинна отримати супровідний документ / sticker / label. Створити адресу відправника. | style="background:#ef9a9a;" | Червоний
|-
| Потребує повтору
| NEEDS_RETRY
| Технічна помилка, можна повторити. | Відправлення не створюється, статус NEEDS_CORRECTION. |-
| Друк ярлика
| Високий
| Потрібно для складу. |}

=== 18.2. Відділення ===

 )

{| class="wikitable"

* підписаний договір з Укрпоштою;
* user token;
* authorization bearer;
* доступ до API-документації;
* тестове середовище або тестові інформаційні дані, якщо надаються;
* інформаційні дані відправника;
* адресу відправника;
* контактну особу відправника;
* правила оплати доставки;
* правила післяплати;
* правила міжнародних відправлень, якщо потрібні;
* правила друку ярликів;
* правила оновлення версій статусів;
* перелік сервісів доставки, які будуть використовуватись;
* вимоги K2 ERP до збереження номерів відправлень. | style="background:#ffcc80;" | Помаранчевий
|-
| Потребує виправлення
| NEEDS_CORRECTION
| Некоректна адреса, індекс або інформаційні дані одержувача. Створити клієнта-відправника. |-
| RouteUnavailableError
| Маршрут доставки недоступний. Tracking Worker оновлює статуси доставки. |-
| Адресний класифікатор
| Робота з адресами, індексами та населеними пунктами.</pre>
Укрпошта
<pre>

</pre>

</pre>

<pre>
=== 12.2. Основні компоненти Python-сервісу ===
</div>
class UkrposhtaApiError(Exception):
платформа повинна логувати:
GET /api/v1/ukrposhta/postcodes?query=01001
інтеграційні функції ERP призначена для:
 new_status = ukrposhta_status_mapper.from_api(status_response)

Офіційна інструкція «Як почати роботу з API» описує базовий workflow: створити адресу відправника, створити адресу одержувача, створити клієнта-відправника, створити клієнта-одержувача, створити відправлення або групу відправлень, після чого надрукувати супровідні документи. |-
| Post Office
| Відділення Укрпошти. | Вони підсвічуються помаранчевим. )
UKRPOSHTA_RETRY_BACKOFF_SECONDS=5

</div>
 headers = {
Як менеджер інтернет-магазину, 

<pre>
async def sync_ukrposhta_statuses(barcodes: list [str], db: "Session") -> None:
3. Ключ
! Створюється запис delivery_order зі статусом PENDING_CREATE. ! Критерій
|-
| Відправлення по Україні
| Створення внутрішніх поштових відправлень. SEO-опис
 pass
 pass
 def search_postcodes(self, filters: dict) -> "PostcodeListResponse":

 def search_post_offices(self, filters: dict) -> "PostOfficeListResponse":
! |-
| default_sender_address_id
| varchar
| Адреса відправника за замовчуванням. Коментар
 shipment.error_message = str(exc)

 shipment.shipment_id = response.id

! Довідник
Міжнародні відправлення потрібно реалізовувати окремим модулем, тому що вони можуть мати:
</pre>
 entity_id=shipment.id,
) -> "UkrposhtaShipment":
! Worker створює відправлення. |-
| Audit Logger
| Зберігає запити, відповіді, помилки та зміни статусів. |-
| AC-15
| Відправлення доставлено. |-
| DuplicateShipmentError
| Відправлення вже створено. | застосовується для розробниками. API повертає shipment_id / barcode. |}

 timeout_seconds: int = 30,

}
 return
 entity_type="ukrposhta_shipment",
UKRPOSHTA_USER_TOKEN=********
|-
| id
| uuid
| Внутрішній ID. | style="background:#f3e5f5;" | Фіолетовий
|-
| Скасовано
| CANCELLED
| Відправлення або замовлення скасовано.<div style="border-left: 6px solid #2e7d32; background: #e8f5e9; padding: 12px 16px; margin: 16px 0;">

* реалізувати створення адреси відправника;
* реалізувати створення адреси одержувача;
* реалізувати кешування адрес;
* реалізувати створення клієнтів;
* реалізувати повторне використання клієнтів. |-
| barcode
| Штрихкод / номер відправлення. Статус K2 ERP

=== 8.2. Друк ярлика ===

* наявність external_order_id;
* наявність idempotency_key;
* чи не створено вже відправлення для цього замовлення;
* user token активний;
* bearer token активний;
* ПІБ або назву одержувача;
* телефон одержувача;
* індекс одержувача;
* адресу одержувача;
* індекс відправника;
* адресу відправника;
* доступність маршруту між індексами, якщо застосовується для перевірка;
* вагу більше 0;
* габарити більше 0, якщо обов'язкові;
* оголошену вартість;
* післяплату, якщо застосовується для;
* SMS-опцію, якщо застосовується для;
* коректність типу відправлення;
* коректність міжнародних полів, якщо це міжнародне відправлення. |-
| Sender Address
| Адреса відправника. Критерій

я хочу бачити статистику по доставках Укрпоштою, 
</div>
 |
 | 1. | Показати менеджеру. |-
| Синхронізація статусів
| Середній
| Фоновий бізнес-процес. 14. | style="background:#ffcc80;" | Важлива
|-
| Внутрішній лист
| DOMESTIC_LETTER
| Лист по Україні. SEO-опис
|-
| AC-1
| Адміністратор створює інтеграцію Укрпошти. |-
| Валідація
| Результат, список помилок. Створити відправлення або групу відправлень. |-
| AC-13
| Ярлик друкується повторно. |-
| city
| varchar
| Місто / населений пункт. retry_count: int = 3

* реалізувати базовий request method;
* реалізувати create_address;
* реалізувати create_client;
* реалізувати create_shipment;
* реалізувати get_label;
* реалізувати track_shipment;
* реалізувати check_route_availability;
* реалізувати обробку помилок. | style="background:#ffcc80;" | Помаранчевий
|-
| Помилка
| ERROR
| Помилка створення або синхронізації. |-
| barcode
| varchar
| Штрихкод / номер відправлення. '''Критично критично:''' інтеграційні функції ERP не повинна створювати дублікати відправлень. * створено;
* зареєстровано;
* прийнято;
* у дорозі;
* прибуло;
* доставлено;
* вручено;
* повертається;
* повернуто;
* скасовано;
* помилка;
* невідомий статус. | style="background:#fff9c4;" | Жовтий
|-
| Доставлено
| DELIVERED
| Відправлення вручено / доставлено. |-
| weight
| numeric
| Вага. |-
| AddressError
| Некоректна адреса. |}

! |-
| shipment_id
| ID відправлення в API Укрпошти. |-
| postpay_enabled
| boolean
| Чи виступає як післяплата. |}

{| class="wikitable"

 for barcode in barcodes:

 idempotency_key=command.idempotency_key,

 bearer_token: str

=== 8.3. Контроль статусів ===
[[Категорія:API]]
! Тип
! |-
| AC-10
| Адреса некоректна. |-
| shipment_hash
| Hash основних параметрів відправлення. |-
| status
| varchar
| Статус K2 ERP. Користувачі:

UKRPOSHTA_TIMEOUT_SECONDS=30

! | style="background:#c8e6c9;" | Зелений
|-
| Передано Укрпошті
| ACCEPTED_BY_UKRPOSHTA
| Відправлення прийнято оператором. class UkrposhtaClient:

! Тип
! |-
| style="background:#ffcc80;" | Помаранчевий
| #ffcc80
| Потрібна дія або виступає як ризик. |}

я хочу бачити статус доставки прямо в K2 ERP, 

! |-
| provider
| varchar
| ukrposhta. |-
| default_sender_client_id
| varchar
| Клієнт-відправник за замовчуванням. |-
| entity_id
| uuid
| ID сутності. |-
| API Event
| Подія інтеграції. {| class="wikitable"

щоб оперативно реагувати на повернення, затримки та проблемні доставки.== 4. Передумови ==

sha256(external_order_id + recipient_phone + recipient_postcode + declared_price + weight)

params=params,

20. Черга створення відправлень

async def create_ukrposhta_shipment(

9. Типи відправлень

if response.status_code >= 400:
event_type="UKRPOSHTA_SHIPMENT_CREATED",
pass
- Створення адреси Тип адреси, API ID, відповідь. Відправлення, статуси, ярлики

4. |-

Label Service - apartment varchar - address_id uuid - raw_response jsonb style="background:#bbdefb;" | В роботі
Прибуло - name varchar Назва інтеграції.== 23. Обробка помилок == - Shipment Service Створює відправлення або групи відправлень. Тип - format varchar K2 ERP оновлює статус відправлення. | style="background:#c8e6c9;" | Зелений
Зареєстровано REGISTERED Відправлення зареєстровано. :contentReference [oaicite:2]{index=2} - printed_by uuid користувач системи. Статус :contentReference [oaicite:3]{index=3}
"status": "PENDING_CREATE",
 "idempotency_key": command.idempotency_key,
== 12. технічна архітектура рішення для бізнесу ==
{| class="wikitable"
|-
| external_order_id
| ID замовлення в K2 ERP. |-
| bearer_token_encrypted
| text
| Зашифрований bearer token. |}

 shipment.barcode = response.barcode

=== 15.6. Перевірка маршруту між індексами ===

* timeout;
* HTTP 429;
* HTTP 500;
* HTTP 502;
* HTTP 503;
* HTTP 504;
* тимчасової недоступності API;
* тимчасової помилки друку ярлика;
* тимчасової помилки синхронізації статусів. |-
| Tracking Status
| Статус доставки. | style="background:#c8e6c9;" | Базова
|-
| Міжнародна посилка
| INTERNATIONAL_PARCEL
| Відправлення за кордон. Для них потрібно передбачити окремий тип документа, оскільки листи мають інший життєвий цикл та власні параметри.== 6. Основні бізнес-сценарії ==

* додати rate limiting;
* додати моніторинг;
* додати alerting;
* додати dead letter queue;
* додати резервне копіювання;
* додати безпечне зберігання секретів. Створити клієнта-одержувача. Код
=== 12.1. Загальна схема ===
{{SEO
|title=Технічне завдання: Інтеграція з Укрпоштою для Python
|description=Технічне завдання на реалізацію Python-сервісу для інтеграції K2 ERP, CRM або інтернет-магазину з API Укрпошти: створення відправлень, адреси, клієнти, ярлики, тарифи, статуси, трекінг, міжнародні відправлення, dashboard та журналювання.
|keywords=Python, Укрпошта, Ukrposhta API, API Укрпошта, ТТН, ярлик, відправлення, доставка, K2 ERP, CRM, інтернет-магазин, FastAPI, логістика, поштовий індекс, трекінг
}}
! # Чи потрібні тільки внутрішні відправлення по Україні? |-
| Client Service
| Створює та кешує клієнтів відправника й одержувача. Приклад `.env`:
 db.commit()
 pass
 pass
|-
| 07.05.2026
| K2-ORDER-123
| -
| Іван Петренко
| style="background:#ef9a9a;" | Помилка
| Некоректний індекс
| Виправити адресу
|-
| 07.05.2026
| K2-ORDER-124
| 0500000000000
| Олена Сидоренко
| style="background:#ffcc80;" | Повернення
| Не отримано
| Контроль повернення
|-
| 07.05.2026
| K2-ORDER-125
| 0500000000001
| ТОВ «Альфа»
| style="background:#f3e5f5;" | Невідомий статус
| Новий статус API без мапінгу
| Оновити мапінг
|}

 audit_logger.log(

8. |-
| created_at
| timestamp
| Дата події. # Чи потрібно друкувати ярлики автоматизовано після створення? |-
| label_base_url
| varchar
| URL для супровідних документів. old_status="CREATING",

== 27. Acceptance Criteria ==

== 13. Ukrposhta Client ==

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

Створення запиту на відправлення - name varchar }
self.base_url = base_url.rstrip("/")

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

  • створення інтеграції Укрпошти;
  • перевірка user token і bearer token;
  • створення адреси відправника;
  • створення адреси одержувача;
  • створення клієнта-відправника;
  • створення клієнта-одержувача;
  • створення внутрішнього відправлення по Україні;
  • збереження shipment_id / barcode;
  • друк супровідного ярлика;
  • синхронізація статусів;
  • дедублікація;
  • retry-механізм;
  • журнал подій;
  • dashboard API;
  • базові unit-тести;
  • mock API для інтеграційних тестів. | style="background:#fff9c4;" | Додаткова
Рекомендований лист REGISTERED_LETTER Лист із реєстрацією та трекінгом. raise UkrposhtaApiError(response.text) Dashboard, список відправлень, картка замовлення. |- length numeric Довжина. Тип помилки Потрібен для валідації адрес. API Укрпошти
entity_id=shipment.id,
"postpay_amount": 1500.00,
- raw_response jsonb Відповідь. * Swagger-документація Укрпошти. Тип

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

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

pass

5. |-

AC-9 Повторний запит має той самий idempotency_key. Колір
db.commit()
def create_client(self, payload: "ClientPayload") -> "ClientResponse": json=json, "postpay_amount": command.delivery.postpay_amount,

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

7. |-

phone varchar Телефон. Пріоритет

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

db.commit()
"region": "Львівська",

11. |-

Скасування - AC-6 style="background:#c8e6c9;" | Норма
Повернення - Tracking Worker }

27.1. інтеграційні функції ERP

18.1. Поштові індекси

"Content-Type": "application/json",
async def request(
Компонент

30. Ризики

)
},
event_type="UKRPOSHTA_STATUS_SYNCED",

6.4. Міжнародні відправлення

v

9. * зберігання user token і bearer token тільки у secret storage або в зашифрованому вигляді;

  • заборону логування token;
  • HTTPS для всіх API-запитів;
  • перевірку SSL;
  • рольову модель доступу;
  • окремі права на створення відправлення;
  • окремі права на скасування відправлення;
  • окремі права на друк ярлика;
  • журнал усіх дій;
  • захист від дублювання відправлень;
  • маскування телефонів одержувачів у логах;
  • контроль доступу до персональних даних. |-
Отримання статусу - shipment_type varchar DOMESTIC_PARCEL, INTERNATIONAL_PARCEL тощо. Тип задачі

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

headers=headers,
id uuid style="background:#c8e6c9;" | Норма
У дорозі Відправлення в транспортуванні. Коментар
v

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

id uuid UNKNOWN_STATUS і таблиця status_mapping. |- updated_at timestamp - Жовтий #fff9c4 Зупинити інтеграцію, повідомити адміністратора. №

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

"postcode": "79000",

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

recipient_client=recipient_client,
pass
base_url: str = "https://www.ukrposhta.ua/ecom/0.0.1/"

15.10. Друк ярлика

- sent_at timestamp - Validation Layer Перевіряє одержувача, адресу, індекс, вагу, оплату. Частота оновлення версій
def check_route_availability(self, sender_postcode: str, recipient_postcode: str) -> "RouteAvailabilityResponse":
id uuid class="wikitable"
  • реалізувати створення відправлення;
  • реалізувати мапінг K2 ERP → API Укрпошти;
  • реалізувати валідацію;
  • реалізувати hash відправлення;
  • реалізувати дедублікацію. Authorization bearer передається в заголовку Authorization, а тіло запиту використовує JSON. Надрукувати супровідні документи / ярлик. Менеджер натискає одну кнопку «Створити відправлення Укрпошта», а Python-сервіс сам виконує всі технічні кроки. оновлення версій статусів

Етап 1. Аналіз API Укрпошти

</syntaxhighlight>

Вони підсвічуються червоним. Причина
  • отримати user token;
  • отримати authorization bearer;
  • перевірити доступ до API;
  • отримати актуальну Swagger-документацію;
  • перевірити створення адрес;
  • перевірити створення клієнтів;
  • перевірити створення тестового відправлення;
  • перевірити друк ярлика;
  • перевірити трекінг. Поле
base_url: str, "raw_request": command.model_dump(),

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

</syntaxhighlight>

- Shipment - AC-12 - Повторна операційна дія Python-сервіс створює відправлення. |}
"delivery": {
"weight": command.delivery.weight,
)

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

Сірий #eeeeee Чернетка, скасовано або неактивно. Очікуваний результат
) -> dict:
shipment.status = "ERROR"

22.3. Worker створення відправлення

"name": "ТОВ «Відправник»",

UKRPOSHTA_BASE_URL=https://www.ukrposhta.ua/ecom/0.0.1/

task_name="send_ukrposhta_shipment",
"sender": {
},
Поле Очікує створення, прибуло. 6. |- external_address_id varchar Версіонування клієнта і contract-тести. | Помилка API, неправильний token, недоступний маршрут. №

class UkrposhtaClient:

self,
recipient_client = await client_service.ensure_recipient_client(shipment, recipient_address)
"weight": 2.5,

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

return shipment
old_status = shipment.status
"width": 20,
Створення відправлення Високий базовий бізнес-процес відвантаження. pass
def check_connection(self) -> "ConnectionStatus":

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

8. User Story

- idempotency_key varchar Довідник індексів оновлюється. | Друге відправлення не створюється. Тип

Кожне замовлення. |-

Перевірка маршруту Середній Валідаційний бізнес-процес. K2 ERP отримує номер відправлення. Валідація, мапінг, дедублікація, черга

GET /api/v1/ukrposhta/post-offices?postcode=01001 1. "apartment": null

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

- Address Service UNKNOWN_STATUS, ручна перевірка. 2. |- postpay_amount numeric Сума післяплати. Значення
AC-14 - sender_client_id uuid 3.== 1. Мета ==

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

Показник

UKRPOSHTA_RETRY_COUNT=3

21.1. ukrposhta_integrations

  • повна технічна підтримка міжнародних відправлень;
  • повна технічна підтримка внутрішніх листів;
  • складна робота з митними даними;
  • повна автоматизація процесів післяплати;
  • складний UI складу;
  • власний компонент адресного класифікатора без API;
  • інтеграційні функції ERP з фінансовими сервісами;
  • масова оптимізація логістики. Поле
style="background:#ffcc80;" | Помаранчевий
Невідомий статус UNKNOWN_STATUS - оновлення версій довідників Низький - external_client_id varchar - old_status varchar - width numeric - AC-16 Відправлення повертається. Тип
id uuid }

</syntaxhighlight>

API-документація Укрпошти описує послідовність створення простого відправлення так:

 async with httpx.AsyncClient(timeout=self.timeout_seconds) as client:
AC-18 style="background:#bbdefb;" | Блакитний
Створено CREATED Відправлення створено в API. SEO-опис

25. Безпека

- email varchar Email. Поле pass
HTML

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

24.2. Приклад dashboard

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

Зберегти raw-відповідь. shipment.status = "CREATING" * Як почати роботу з API, реліз системи 11.02.2026. Barcode PATCH /api/v1/ukrposhta/shipments/{shipment_id} Коментар

27.6. Dashboard

Очікуваний результат data={ 5. | Архів, чернетки. | style="background:#ffcc80;" | Помаранчевий
Повернуто RETURNED - ApiError API повернув помилку.
 method: str,

POST /api/v1/ukrposhta/integrations/{integration_id}/check-connection
! |}

Python Status Sync Worker

 "external_order_id": "K2-ORDER-2026-000123",
!== 5. Базовий workflow створення відправлення ==
label_base_url: str | None = None
- external_order_id varchar - Delivery Order - Створення клієнта - base_url varchar - Mapping Layer style="background:#c8e6c9;" | Норма
Ярлики надруковано - printed_at timestamp Перевести в NEEDS_CORRECTION. * інтернет-магазинів; * CRM; * ERP; * WMS; * складів; * служб доставки; * торгових компаній; * дистриб'юторів; * компаній, які створюють багато поштових відправлень; * компаній, які хочуть контролювати доставку прямо з K2 ERP. | style="background:#eeeeee;" | Сірий
Очікує створення PENDING_CREATE Статус змінюється на LABEL_PRINTED. |} - Label / Sticker Idempotency key і перевірка external_order_id. Значення style="background:#bbdefb;" | Блакитний
Прибуло ARRIVED Відправлення прибуло у відділення або точку видачі. Очікуваний результат

18.3. Графік оновлення версій довідників

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

щоб платформа автоматизовано створила відправлення без ручного введення в кабінеті або іншій системі. | Статус стає DELIVERED і підсвічується зеленим. class UkrposhtaSettings(BaseSettings):