# PRRO.cloud — Документація API > REST API сервісу PRRO.cloud: реєстрація чеків, керування змінами, білінг і вебхуки. Джерело правди — специфікація OpenAPI 3.1; цю сторінку згенеровано з неї під час збірки, тож довідник не розходиться з контрактом. Базова адреса: `https://app.prro.cloud` (OpenAPI v0.2.2). Усі шляхи на цій сторінці — відносні до базової адреси. Тіла запитів і відповідей — JSON (`application/json`), кодування UTF-8. ## Автентифікація Машинні запити автентифікуються довгоживучим Bearer-токеном (JWT). Випустіть його в кабінеті PRRO.cloud у розділі токенів — значення показується **рівно один раз**, збережіть його одразу. Токен передається в заголовку `Authorization: Bearer `; відкликання в кабінеті набирає чинності на всіх репліках протягом ~2 секунд. Перевірити токен можна запитом: ```sh curl -H "Authorization: Bearer $PRRO_TOKEN" \ "$BASE_URL/api/v1/whoami" ``` ## Швидкий старт Разовий виклик, щоб узяти id каси, і три запити фіскального циклу — перший чек зареєстровано. На касі в режимі `TEST` цей цикл безкоштовний і не потребує реєстрації в податковій. 1. **Візьміть id каси.** Токен показує ті каси, на які він діє. `id` з відповіді — те саме значення, що далі йде у `cash_register_id` чека і в шляхи `/cash-registers/{id}`; фіскальний номер для цього не годиться. Виклик разовий — збережіть id у налаштуваннях інтеграції. ```sh curl -H "Authorization: Bearer $PRRO_TOKEN" \ "$BASE_URL/api/v1/cash-registers" ``` 2. **Відкрийте зміну.** Якщо каса не в режимі `shift_mode: manual`, цей крок можна пропустити — перший чек відкриє зміну сам. ```sh curl -X POST "$BASE_URL/api/v1/cash-registers/$REGISTER_ID/shifts" \ -H "Authorization: Bearer $PRRO_TOKEN" \ -H "Idempotency-Key: shift-2026-07-14" \ -H "Content-Type: application/json" \ -d '{"cashier": "Каса самообслуговування"}' ``` 3. **Зареєструйте чек.** Суми — десяткові рядки, а не числа. У синхронному режимі (за замовчуванням) фіскальний номер — одразу у відповіді, а поруч із ним — посилання на чек для покупця. ```sh curl -X POST "$BASE_URL/api/v1/receipts" \ -H "Authorization: Bearer $PRRO_TOKEN" \ -H "Idempotency-Key: order-10412" \ -H "Content-Type: application/json" \ -d '{ "cash_register_id": "'$REGISTER_ID'", "type": "sale", "items": [ { "name": "Кава американо", "quantity": "1", "price": "65.00", "tax_letters": "А" } ], "payments": [ { "type": "card", "sum": "65.00" } ] }' ``` 4. **Закрийте день.** Z-звіт і закриття зміни — одна операція (або налаштуйте `shift_close_times` на касі, і день закриватиметься сам). ```sh curl -X DELETE "$BASE_URL/api/v1/cash-registers/$REGISTER_ID/shifts/current" \ -H "Authorization: Bearer $PRRO_TOKEN" \ -H "Idempotency-Key: close-2026-07-14" ``` ## Ключові механіки - **Ідемпотентність.** Заголовок `Idempotency-Key` обовʼязковий для всіх фіскальних операцій. Повтор запиту з тим самим ключем повертає оригінальну задачу, а не другий чек — мережеві збої та ретраї безпечні. Той самий ключ з іншою операцією — `409`. - **Sync та async.** За замовчуванням запит тримає зʼєднання до відповіді ДПС (до 30 с); якщо не встигли — `202` із задачею для опитування. `mode=async` повертає `202` одразу, а результат приходить через `GET /api/v1/tasks/{id}` та/або вебхук. - **Гроші — рядки.** Усі суми — десяткові рядки (`"259.90"`), ніколи не float. Кількість — до 3 знаків після коми, ціни — до 2. - **Помилки.** Єдиний конверт `{code, message, details}`: `code` — машинний код для обробки, `message` — людський текст. `422` — помилка валідації або відхилення операції (немає відкритої зміни, відмова ДПС). - **Баланс.** Сервіс передплатний: коли баланс перетинає мʼякий ліміт, нові чеки відповідають `402`, доки баланс не поповнено. Операції зі змінами при цьому доступні. Перед тим приходить вебхук `client.balance_low` — єдине попередження, що кошти добігають кінця: у `data` баланс, мʼякий ліміт, ціна чека і скільки чеків лишилося. - **Час продажу.** Якщо ваша інтеграція дійшла до нас пізніше за касу (автомат, що годину тримав замовлення в черзі), передайте `sold_at` — і на чеку зʼявиться окремий рядок «Продаж від 03.09.2026 18:11», перед приміткою `comment`, якщо вона є. Фіскальним часом документа він не стає: ДПС приймає його лише в межах хвилини від власного годинника, тож документ завжди позначено моментом подання. Час у майбутньому або старіший за 31 день — `422`. - **Форма оплати й засіб.** `payments[].type` — одна з форм, закритих законом (`cash`, `card`, `certificate`, `bank_transfer`, `direct_debit`); фіскальний код і назву за неї підставляє сервіс. Коли надрукувати треба точніше — «ПЕРЕКАЗ З КАРТКИ», талон, сертифікат мережі — назву задає `payments[].means`, а код форми лишається за `type`, тож лічильник готівки та розбивка Z-звіту не розходяться з чеком. Реквізити еквайрингу (ідентифікатор і податковий номер еквайра, платіжний пристрій, код авторизації, комісія) — у `payments[].card`. ## Чек для покупця Відповідь на фіскалізацію несе не лише фіскальний номер: у `result.receipt` поруч із ним лежать два посилання — наша копія чека і той самий документ у кабінеті ДПС. Це все, що потрібно надіслати покупцеві листом чи в месенджер або показати QR-кодом на екрані каси — рендерити чек самотужки не треба. ```json { "task_id": "0197a2c1-…", "type": "receipt", "status": "succeeded", "result": { "receipt": { "document_id": "0197a2c3-…", "local_number": 42, "fiscal_number": "7466800082", "register_fiscal_number": "4001063533", "receipt_url": "https://r.prro.cloud/aB3xK9pQvT2mNr7c", "tax_url": "https://cabinet.tax.gov.ua/cashregs/check?fn=4001063533&id=7466800082&date=20260803&time=010754&sm=65.00" } } } ``` - **`receipt_url` — копія чека.** Сторінка відкривається **без авторизації**: 16-символьний код і є доступом, як паперовий чек у кишені. Подання обирає параметр `?format=`: `html` (типово), `png` (сам чек картинкою завширшки 576 px — це растрова ширина стрічки 80 мм, тож на термопринтер вона йде як є, разом із QR) і `qr` (PNG з адресою цієї ж сторінки). Назовні віддається лише людиночитаний чек — ні XML, ні CMS, ні квитанції ДПС. Невідомий код і документ, який не можна показати, відповідають однаково — `404`. - **`tax_url` — незалежна перевірка.** Той самий документ у кабінеті платника податків — підтвердження, яке покупець читає, не довіряючи нам. Доказ фіскалізації — це `fiscal_number` і `tax_url`; `receipt_url` лише показує чек. - **Офлайн-чек.** У документа з `offline: true` фіскальний номер обчислено локально (`..`), тож `tax_url` зʼявиться лише після того, як пакет сесії прийме фіскальний сервер. `receipt_url` є одразу — копія віддається з нашого журналу. - **`register_fiscal_number` — ФН ПРРО.** Фіскальний номер каси, на якій видано документ, — той самий «ФН ПРРО», що друкується на чеку. Присутній завжди й однаковий у будь-якому режимі, на відміну від `fiscal_number`. Це те, за чим інтеграція зіставляє свої записи з касою: діставати номер із параметра `fn=` посилання `tax_url` не треба — саме його в офлайн-документа й немає. - **Тільки розрахункові документи.** Z-звіт, відкриття та закриття зміни друкованої форми не мають, тож посилань у їхніх `DocResult` не буде. - **Посилання не протухають.** Код зберігається разом із документом, а не перераховується, тож ротація ключів сервісу не ламає адрес, які вже в руках у покупців. Сторінку не індексують пошукові системи. ## Вебхуки Замість опитування задач підпишіться на події: зареєструйте endpoint через `POST /api/v1/webhooks` — і сервіс сам постукає у ваш бекенд. - **Події.** Завдання — `task.completed` і `task.failed`. Зміни — `shift.opened` і `shift.closed`. Ключ КЕП — `key.expiring` (раз на добу про сертифікат, що спливає протягом 30 днів). Стан каси — `register.offline` і `register.online`, `register.offline_limit` (наближення до законних меж офлайн-сесії, 36 і 168 годин), `register.remediated` (сервіс сам усунув розбіжність із ДПС) і `register.needs_attention` (виправлення не тримаються — на касу має поглянути людина). Баланс — `client.balance_low` (передплачених коштів лишилося менше ніж на поріг чеків); ця подія стосується клієнта, а не каси, тож `cash_register_id` у ній немає. - **Конверт доставки.** POST на ваш URL з тілом `{delivery_id, event, attempt, occurred_at, data}`; у `data` — корисне навантаження події. - **Підпис.** Заголовок `X-Signature: sha256=` — HMAC-SHA256 від тіла запиту під секретом endpoint'а. Секрет видається один раз при створенні; перевіряйте підпис перед обробкою. - **Гарантії.** Доставка at-least-once — дедуплікуйте за `delivery_id`; події однієї каси приходять по порядку. Невдалі доставки ретраяться, вичерпані потрапляють у DLQ (`status=dead`) і можуть бути повторені вручну через replay. ```http POST https://example.com/prro-hook X-Signature: sha256=2b7e9f… { "delivery_id": "0197a2c4-…", "event": "task.completed", "attempt": 1, "occurred_at": "2026-07-14T10:15:04Z", "data": { "task_id": "0197a2c1-…", "status": "succeeded" } } ``` ## Довідник ендпоінтів Згенеровано зі специфікації OpenAPI. Кабінетні ендпоінти (cookie-сесія панелі) сюди не входять — інтеграції працюють лише з машинним API. ### Сервісні #### GET /api/v1/version Версія збірки сервісу Відповіді: - `200` — Версія, зашита у збірку. Тіло: див. нижче. Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `version` | string | так | Тег збірки: dev у локальній збірці, інакше версія релізу. | #### GET /api/v1/whoami Дізнатися, що стоїть за наданим машинним токеном _(Bearer-токен обовʼязковий)_ Відповіді: - `200` — Клієнт, дозволи (scopes) та обмеження за касами. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `client_id` | string (uuid) | так | Клієнт, від імені якого діє токен. | | `scopes` | array | так | Дозволи, видані токену. | | `all_cash_registers` | boolean | так | true — токен діє на всі каси клієнта (поточні й майбутні); false — лише на перелічені у cash_registers. | | `cash_registers` | array | — | Присутнє лише для обмеженого токена — перелік uuid кас, до яких він прив'язаний. Відсутнє, коли all_cash_registers. | | `jti` | string (uuid) | так | Ідентифікатор самого токена — за ним його відкликають у кабінеті. | | `expires_at` | string (date-time) | — | Коли токен спливає; у безстрокового відсутнє. | #### GET /system/dps Поточний режим роботи з ДПС (онлайн/офлайн) _(Bearer-токен обовʼязковий)_ Той самий знімок доступності, доступний будь-якій автентифікованій інтеграції: клієнт може показувати «ДПС офлайн» власним операторам. Відповіді: - `200` — Знімок стану доступності. Тіло: `DPSStatus` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). ### Фіскальні операції #### POST /api/v1/receipts Зареєструвати чек (реалізація/повернення/сторно або рух готівки) _(Bearer-токен обовʼязковий)_ Реєструє розрахунковий документ: продаж (sale), повернення (return), сторно (storno) або рух готівки повз продаж (service_in — службове внесення, service_out — інкасація). Усі вони — DOCTYPE 0 і проходять однаковий шлях. Повний фіскальний цикл: локальний номер, XML за check01, підпис КЕП (CAdES-T), надсилання до ДПС, квитанція. Синхронний режим (типовий) чекає на результат до 30 секунд, інакше віддає 202 і номер завдання для GET /tasks/{id}; mode=async віддає 202 одразу. Idempotency-Key обов'язковий: повтор із тим самим ключем повертає те саме завдання, а не реєструє другий чек. Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `Idempotency-Key` | header | string | так | Ключ операції, який обирає клієнт. Повтор запиту з тим самим ключем поверне початкове завдання, а не виконає фіскальну операцію вдруге. | | `mode` | query | string | — | Режим доставки результату; має перевагу над однойменним полем у тілі. sync (типовий) чекає на результат у межах синхронного очікування; async одразу віддає 202 і номер завдання. | Тіло запиту (application/json): `ReceiptInput` (див. «Схеми даних») Відповіді: - `200` — Повтор за тим самим Idempotency-Key; завдання вже завершене. Тіло: `Task` (див. «Схеми даних»). - `201` — Зареєстровано в межах синхронного очікування. Тіло: `Task` (див. «Схеми даних»). - `202` — Ще виконується; статус — через GET /tasks/{id}. Тіло: `Task` (див. «Схеми даних»). - `400` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `402` — Баланс опустився нижче порога: нові чеки заблоковано до поповнення. Операції зі змінами лишаються доступними. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `409` — Цей Idempotency-Key уже використано для іншої операції. Тіло: `Error` (див. «Схеми даних»). - `422` — Не пройшла валідація або завдання завершилося помилкою (немає відкритої зміни, відмова ДПС тощо). Тіло: `Error` (див. «Схеми даних»). #### GET /api/v1/tasks/{id} Статус і результат операції (опитування) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор завдання з відповіді на фіскальну операцію. | Відповіді: - `200` — Завдання в поточному стані. Тіло: `Task` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### GET /api/v1/cash-registers Каси, доступні цьому токену (звідки інтегратор бере cash_register_id) _(Bearer-токен обовʼязковий)_ Каси, на які діє наданий токен: повний бачить усі каси клієнта, обмежений — лише свої. Звідси інтегратор бере cash_register_id для решти маршрутів. Тільки реквізити впізнавання й адресації; поточний стан — у GET /cash-registers/{id}. Відповіді: - `200` — Каси в межах токена, від найстаріших. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `cash_registers` | array | так | Каси в межах токена, від найстаріших. | #### GET /api/v1/cash-registers/{id} Стан реєстратора (зміна, режим, лічильники) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | Відповіді: - `200` — Поточний стан реєстратора. Тіло: `CashRegisterState` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### POST /api/v1/cash-registers/{id}/shifts Відкрити зміну (DOCTYPE 100; семантика завдання така сама, як у чеків) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | | `Idempotency-Key` | header | string | так | Ключ операції, який обирає клієнт. Повтор запиту з тим самим ключем поверне початкове завдання, а не виконає фіскальну операцію вдруге. | | `mode` | query | string | — | Режим доставки результату; має перевагу над однойменним полем у тілі. sync (типовий) чекає на результат у межах синхронного очікування; async одразу віддає 202 і номер завдання. | Тіло запиту (application/json, необовʼязкове): | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `cashier` | string | — | Ім'я касира, яке друкують у документі відкриття зміни. | | `mode` | string | — | Режим доставки результату; параметр запиту ?mode= має перевагу над цим полем. Значення: sync, async. | Відповіді: - `201` — Зміну відкрито. Тіло: `Task` (див. «Схеми даних»). - `202` — Ще виконується; статус — через GET /tasks/{id}. Тіло: `Task` (див. «Схеми даних»). - `400` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### DELETE /api/v1/cash-registers/{id}/shifts/current Закрити поточну зміну (Z-звіт і повідомлення про закриття однією операцією) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | | `Idempotency-Key` | header | string | так | Ключ операції, який обирає клієнт. Повтор запиту з тим самим ключем поверне початкове завдання, а не виконає фіскальну операцію вдруге. | | `mode` | query | string | — | Режим доставки результату; має перевагу над однойменним полем у тілі. sync (типовий) чекає на результат у межах синхронного очікування; async одразу віддає 202 і номер завдання. | Відповіді: - `201` — Зміну закрито; у результаті — і Z-звіт, і документ закриття. Тіло: `Task` (див. «Схеми даних»). - `202` — Ще виконується; статус — через GET /tasks/{id}. Тіло: `Task` (див. «Схеми даних»). - `400` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### POST /api/v1/cash-registers/{id}/offline-session/close Примусово закрити активну офлайн-сесію (документ завершення сесії потрапляє до журналу одразу, а пакети досилаються у фоні) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | | `Idempotency-Key` | header | string | так | Ключ операції, який обирає клієнт. Повтор запиту з тим самим ключем поверне початкове завдання, а не виконає фіскальну операцію вдруге. | | `mode` | query | string | — | Режим доставки результату; має перевагу над однойменним полем у тілі. sync (типовий) чекає на результат у межах синхронного очікування; async одразу віддає 202 і номер завдання. | Тіло запиту (application/json, необовʼязкове): | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `cashier` | string | — | Ім'я касира, яке друкують у документі завершення сесії. | | `mode` | string | — | Режим доставки результату; параметр запиту ?mode= має перевагу над цим полем. Значення: sync, async. | Відповіді: - `201` — Сесію закрито; у результаті — документ завершення. Тіло: `Task` (див. «Схеми даних»). - `202` — Ще виконується; статус — через GET /tasks/{id}. Тіло: `Task` (див. «Схеми даних»). - `400` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### POST /api/v1/cash-registers/{id}/offline-session/retry Відновити зупинене надсилання офлайн-пакетів (сервіс зупинив сесію після повторюваних непоправних відмов — спершу усуньте причину) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | Відповіді: - `200` — Скільки сесій повернуто до надсилання. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `resumed_sessions` | integer | так | Скільки сесій повернуто до надсилання; 0 — зупинених не було. | #### DELETE /api/v1/cash-registers/{id}/attention Зняти позначку «потребує уваги» з реєстратора _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | Відповіді: - `200` — Чи справді було знято позначку. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `cleared` | boolean | так | false означає, що позначки й не було. | #### PUT /api/v1/cash-registers/{id}/cash-balance Заявити, скільки готівки насправді в касі _(Bearer-токен обовʼязковий)_ Переставляє лічильник готівки на перераховану суму: для каси, яка приєдналася до сервісу з непорожнім ящиком, або коли лічильник розійшовся з фактом. Нічого фіскального не відбувається: заявлений залишок не потрапляє в жоден документ і не змінює підсумків зміни. Готівку, яка справді рухається, реєструють чеком service_in або service_out. Заявлений залишок не може бути від'ємним. Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор каси — uuid із GET /api/v1/cash-registers. | Тіло запиту (application/json): | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `amount` | CashAmount | так | Перерахований залишок; не може бути від'ємним. | Відповіді: - `200` — Лічильник після заяви. Тіло: `CashBalanceDeclaration` (див. «Схеми даних»). - `400` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). ### Білінг #### GET /api/v1/billing/usage Передплачений баланс і підсумок тарифікації за період _(Bearer-токен обовʼязковий)_ Суми — копійки десятковим рядком. Типовий період — поточний календарний місяць за UTC, межа `to` не включається; період понад 366 днів — 422. Тарифікація асинхронна, тож підсумок може відставати від останнього чека на кілька секунд. Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `from` | query | string (date) | — | Початок періоду, включно (дата за UTC); типово — перше число поточного місяця. | | `to` | query | string (date) | — | Кінець періоду, не включно; типово — перше число наступного місяця. Понад 366 днів — 422. | Відповіді: - `200` — Баланс і використання за період. Тіло: `BillingUsage` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### GET /api/v1/invoices Рахунки клієнта, від найновішого періоду _(Bearer-токен обовʼязковий)_ Рахунок — підсумок одного розрахункового періоду, а не окремий платіж: один рядок на період. Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `limit` | query | integer | — | Скільки рахунків повернути: 1–200, типово 50. | | `offset` | query | integer | — | Скільки рахунків пропустити — посторінковий обхід. | Відповіді: - `200` — Рахунки клієнта. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `invoices` | array | так | Рахунки, від найновішого періоду. | ### Вебхуки #### GET /api/v1/webhooks Перелік вебхуків клієнта (без секретів) _(Bearer-токен обовʼязковий)_ Відповіді: - `200` — Точки доставки клієнта. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `webhooks` | array | так | Точки доставки клієнта; секрети не повертаються. | #### POST /api/v1/webhooks Зареєструвати вебхук (секрет HMAC показують рівно один раз) _(Bearer-токен обовʼязковий)_ Доставка — POST з тілом {delivery_id, event, attempt, occurred_at, data} і заголовком X-Signature вигляду "sha256=", порахованим на секреті цієї точки доставки. Гарантія — «щонайменше один раз»: приймач має відкидати повтори за delivery_id. Події одного реєстратора приходять по порядку. Тіло запиту (application/json): | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `url` | string | так | Абсолютний http(s)-URL приймача. | | `events` | array | — | Події, на які підписані; порожній список або відсутнє поле означає всі події. Значення: task.completed, task.failed, shift.opened, shift.closed, key.expiring, register.offline, register.online, register.offline_limit, register.remediated, register.needs_attention, client.balance_low. | | `secret` | string | — | Секрет HMAC; якщо не вказати, згенерує сервер. | Відповіді: - `201` — Створено; секрет повертається рівно один раз. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `201`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `id` | string (uuid) | так | Ідентифікатор вебхука. | | `url` | string | так | Абсолютний http(s)-URL приймача. | | `events` | array | так | Порожній список означає підписку на всі події. Значення: task.completed, task.failed, shift.opened, shift.closed, key.expiring, register.offline, register.online, register.offline_limit, register.remediated, register.needs_attention, client.balance_low. | | `active` | boolean | так | Доставка ввімкнена; false призупиняє її, не втрачаючи черги. | | `created_at` | string (date-time) | так | Коли вебхук створено. | | `updated_at` | string (date-time) | так | Коли його востаннє змінювали. | | `secret` | string | так | Отримати повторно неможливо. | #### PATCH /api/v1/webhooks/{id} Змінити URL, підписку або ознаку активності (часткове оновлення) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор вебхука. | Тіло запиту (application/json): | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `url` | string | — | Новий абсолютний http(s)-URL приймача. | | `events` | array | — | Новий перелік подій; порожній список означає всі. Значення: task.completed, task.failed, shift.opened, shift.closed, key.expiring, register.offline, register.online, register.offline_limit, register.remediated, register.needs_attention, client.balance_low. | | `active` | boolean | — | false призупиняє доставку, не втрачаючи черги. | Відповіді: - `200` — Оновлено. Тіло: `WebhookEndpoint` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### DELETE /api/v1/webhooks/{id} Видалити точку доставки (недоставлену чергу буде відкладено) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор вебхука. | Відповіді: - `204` — Видалено. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). #### GET /api/v1/webhooks/{id}/deliveries Історія доставок, від найновішої (status=dead — черга невдалих) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор вебхука. | | `status` | query | string | — | Показати лише доставки в цьому стані. | | `limit` | query | integer | — | Скільки доставок повернути: 1–200, типово 50. | Відповіді: - `200` — Доставки. Тіло: див. нижче. - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `422` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). Тіло відповіді `200`: | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `deliveries` | array | так | Доставки, від найновішої. | #### POST /api/v1/webhooks/{id}/deliveries/{deliveryId}/replay Повернути доставку в чергу з новим запасом спроб (зазвичай — невдалу) _(Bearer-токен обовʼязковий)_ Параметри: | Параметр | Де | Тип | Обовʼязковий | Опис | |---|---|---|---|---| | `id` | path | string (uuid) | так | Ідентифікатор вебхука. | | `deliveryId` | path | string (uuid) | так | Ідентифікатор доставки з історії. | Відповіді: - `200` — Повернуто в чергу; пізніші події того самого реєстратора зачекають на неї — порядок зберігається й після повтору. Тіло: `WebhookDelivery` (див. «Схеми даних»). - `401` — Немає облікових даних, або вони недійсні, протерміновані чи відкликані. Тіло: `Error` (див. «Схеми даних»). - `404` — Конверт помилки. Тіло: `Error` (див. «Схеми даних»). - `409` — Саме зараз триває спроба доставки. Тіло: `Error` (див. «Схеми даних»). ## Схеми даних Обʼєкти, на які посилаються ендпоінти довідника. Обовʼязкові поля позначено «так». ### Error (object) Єдиний конверт помилки: машинний код, текст для людини і подробиці, якщо вони є. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `code` | string | так | Стабільний машинний код помилки — саме на нього реагує інтеграція. | | `message` | string | так | Пояснення для людини; покладатися на його текст програмно не можна. | | `details` | any | — | Подробиці помилки, коли вони є, — наприклад перелік полів, які не пройшли валідацію. | ### CashRegisterState (object) Поточний стан реєстратора: у якому він режимі, що зі зміною, готівкою та офлайном. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `id` | string (uuid) | так | Ідентифікатор каси в цьому API — те саме значення, що cash_register_id чека. | | `fiscal_number` | string | так | Фіскальний номер ПРРО, присвоєний ДПС, — «ФН ПРРО» на чеку. | | `local_number` | string | так | CASHDESKNUM: власний номер каси у клієнта. | | `mode` | string | так | production — бойовий режим; test — документи позначені як тестові. Значення: production, test. | | `state` | string | так | closed — зміна закрита; opened — відкрита; offline — триває офлайн-сесія. Значення: closed, opened, offline. | | `offline_ready` | boolean | — | Чи має реєстратор видані ДПС офлайн-реквізити (приходять із квитанцією на відкриття зміни). | | `shift_mode` | ShiftMode | — | Як керують змінами реєстратора. `manual` — клієнт відкриває і закриває їх сам. `round_the_clock` — зміна закривається в кожен із shift_close_times, наступний чек відкриває нову. `working_hours` — денне вікно, задане двома межами у shift_close_times. В обох керованих режимах зміну відкриває перший же чек. | | `shift_close_times` | ShiftCloseTimes | — | Час щоденного закриття зміни за київським часом; порожній рівно тоді, коли shift_mode — `manual`. Часи прив'язані до годинника, а не до моменту відкриття зміни, тож точка закриття не повзе. Потрібно щонайменше два значення з проміжком не більше 20 годин (рахуючи через опівніч). `round_the_clock` приймає два або більше за зростанням; `working_hours` — рівно два, початок і кінець дня саме в цьому порядку, щоб вікно через опівніч ("08:00", потім "02:00") зберігало напрямок. | | `cash_balance` | CashBalance | — | Скільки готівки в касі реєстратора. Це лічильник, а не налаштування і не фіскальна величина: він стартує з нуля при створенні реєстратора і бачить лише документи, що пройшли через цей сервіс. Рухають його готівкові рядки оплат — додають на реалізації, віднімають на поверненні та сторно — і службові документи; безготівкові форми не рухають нічого. Береться `sum` рядка оплати, тож решта вже врахована. Лічильник живе на реєстраторі, а не на зміні: готівка переживає Z-звіт. Значення може бути від'ємним — це означає, що в касі було більше, ніж бачив сервіс. Переставити лічильник на справжню суму: PUT .../cash-balance. | | `current_shift` | object | — | Зміна, з якою каса працює зараз; після закриття поле зникає. | | `current_shift.id` | string (uuid) | — | Ідентифікатор зміни. | | `current_shift.number` | integer (int64) | — | Наскрізний номер зміни в межах каси («Зміна №147»). Присвоюється локально: ДПС номера зміни не видає. | | `current_shift.status` | string | — | opening і closing — операція ще в роботі; opened і closed — завершена. Значення: opening, opened, closing, closed. | | `current_shift.testing` | boolean | — | Зміну відкрито на касі в режимі test — усі її документи тестові. | | `current_shift.opened_at` | string (date-time) | — | Коли зміну відкрито. | | `current_shift.documents` | integer | — | Скільки документів створила зміна — усіх видів, не лише розрахункових. Відсутнє, якщо порахувати не вдалося. | | `shift_totals` | ShiftTotals | — | Поточні підсумки відкритої зміни — те саме накопичення, з якого буде побудований Z-звіт; сервіс складає його чек за чеком у тій самій транзакції, що реєструє документ. Сторно віднімається з боку реалізації, а не додається до повернень. Службові внесення й видачі не належать до жодного боку. Розкладу за податковими літерами тут немає — він належить Z-звіту. | | `offline_session` | object | — | Присутня, поки реєстратор працює офлайн. | | `offline_session.id` | string (uuid) | — | Ідентифікатор сесії в сервісі. | | `offline_session.dps_session_id` | integer (int64) | — | Номер сесії, виданий ДПС; входить у фіскальний номер офлайн- документа. | | `offline_session.started_at` | string (date-time) | — | Початок сесії — від нього рахують 36-годинну межу. | | `offline_session.documents` | integer (int64) | — | Скільки документів видано в цій сесії. | | `offline_session.last_significant_at` | string (date-time) | — | Останній документ, що продовжує сесію; за ним рахують витрачений місячний час. | | `offline_limits` | object | так | Законодавчі межі офлайн-роботи в секундах: 36 годин на одну сесію і 168 годин на календарний місяць. Витрачене рахують від offline_session.started_at і offline_month_used_seconds. | | `offline_limits.session_seconds` | integer (int64) | так | Межа однієї сесії — 36 годин у секундах. | | `offline_limits.month_seconds` | integer (int64) | так | Межа на календарний місяць — 168 годин у секундах. | | `offline_month_used_seconds` | integer (int64) | — | Час, відпрацьований офлайн у цьому календарному місяці (за київським часом). | | `attention` | object | — | Присутня, коли реєстратор позначено як такий, що потребує уваги (див. CashRegister.attention_reason). Знімається через DELETE .../attention; зупинене надсилання офлайн-пакетів додатково відновлюють через POST .../offline-session/retry. | | `attention.reason` | string | так | recurring_remediation — розбіжності з ДПС усуваються знову і знову; offline_submission_paused — надсилання офлайн-пакетів зупинено; auto_close_failing — не вдається автоматичне закриття зміни. Значення: recurring_remediation, offline_submission_paused, auto_close_failing. | | `attention.since` | string (date-time) | — | Коли позначку поставлено. | ### ShiftMode (string) Як керують змінами реєстратора. `manual` — клієнт відкриває і закриває їх сам. `round_the_clock` — зміна закривається в кожен із shift_close_times, наступний чек відкриває нову. `working_hours` — денне вікно, задане двома межами у shift_close_times. В обох керованих режимах зміну відкриває перший же чек. Значення: `manual`, `round_the_clock`, `working_hours`. ### ShiftCloseTimes (array) Час щоденного закриття зміни за київським часом; порожній рівно тоді, коли shift_mode — `manual`. Часи прив'язані до годинника, а не до моменту відкриття зміни, тож точка закриття не повзе. Потрібно щонайменше два значення з проміжком не більше 20 годин (рахуючи через опівніч). `round_the_clock` приймає два або більше за зростанням; `working_hours` — рівно два, початок і кінець дня саме в цьому порядку, щоб вікно через опівніч ("08:00", потім "02:00") зберігало напрямок. ### CashRegisterListItem (object) Каса так, як її показує перелік токена: чим її впізнає людина (фіскальний і локальний номер, точка) і чим її адресує машина (id). | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `id` | string (uuid) | так | Ідентифікатор каси в цьому API — те саме значення, що йде в cash_register_id чека і в {id} решти маршрутів. | | `fiscal_number` | string | так | Фіскальний номер ПРРО, присвоєний ДПС; за ним касу впізнає людина. | | `local_number` | string | так | CASHDESKNUM: власний номер каси у клієнта. | | `org_name` | string | — | Назва суб'єкта господарювання. | | `point_name` | string | — | Назва господарської одиниці — точки продажу. | | `point_address` | string | — | Адреса господарської одиниці. | | `mode` | string | так | production — бойовий режим; test — документи позначені як тестові. Значення: production, test. | | `state` | string | так | closed — зміна закрита; opened — відкрита; offline — триває офлайн-сесія. Значення: closed, opened, offline. | ### Task (object) Одиниця роботи фіскального конвеєра: у неї перетворюється кожен запит, що йде до ДПС. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `task_id` | string (uuid) | так | Ідентифікатор завдання — за ним опитують GET /api/v1/tasks/{id}. | | `type` | string | так | Операція завдання: receipt — розрахунковий документ; open_shift і close_shift — зміна; close_offline_session — завершення офлайн-сесії; verify_key — перевірка ключа КЕП; sync_register — звіряння з ДПС; dps_objects — запит об'єктів власника ключа. Значення: receipt, open_shift, close_shift, close_offline_session, verify_key, sync_register, dps_objects. | | `status` | string | так | pending — у черзі; processing — виконується; succeeded і failed — завершено, результат у result або fault. Значення: pending, processing, succeeded, failed. | | `created_at` | string (date-time) | так | Коли завдання створено. | | `finished_at` | string (date-time) | — | Коли завдання завершилося; поки воно в роботі — відсутнє. | | `error` | string | — | Текст помилки завдання; структурований опис того самого збою — у fault. | | `fault` | Fault | — | Структурований опис збою завдання: стабільний код із простором імен (dps.* — відмова фіскального сервера, fiscal.* — валідація документа, signer.* — рівень КЕП, state.* — стан реєстратора), клас реакції, параметри для підстановки, повідомлення мовою з Accept-Language (типово українською), дослівний текст ДПС і застосовані автоматичні виправлення. | | `result` | TaskResult | — | Фіскальні поля (prro_id/shift_id/testing/…) стосуються завдань на чек, зміну та офлайн-сесію; key_verification — єдиний результат завдання verify_key. | ### Fault (object) Структурований опис збою завдання: стабільний код із простором імен (dps.* — відмова фіскального сервера, fiscal.* — валідація документа, signer.* — рівень КЕП, state.* — стан реєстратора), клас реакції, параметри для підстановки, повідомлення мовою з Accept-Language (типово українською), дослівний текст ДПС і застосовані автоматичні виправлення. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `code` | string | так | Стабільний ідентифікатор, напр. dps.check_local_number_invalid. | | `class` | string | так | Що може зарадити: resync — звірити стан із ДПС; config — виправити налаштування реєстратора; precursor — виконати пропущений попередній крок; user_action — потрібне рішення людини; transient — тимчасова недоступність, допоможе повтор; request — виправити запит; internal — збій сервісу. Значення: resync, config, precursor, user_action, transient, request, internal. | | `params` | object | — | Значення для підстановки в message. | | `message` | string | — | Текст для людини, локалізований із каталогу помилок. | | `upstream_message` | string | — | Дослівне повідомлення фіскального сервера. | | `remediation` | array | — | Автоматичні виправлення, застосовані під час обробки завдання. Значення: local_number_synced, shift_adopted, shift_abandoned, zreport_recovered, register_config_filled. | ### TaskResult (object) Фіскальні поля (prro_id/shift_id/testing/…) стосуються завдань на чек, зміну та офлайн-сесію; key_verification — єдиний результат завдання verify_key. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `prro_id` | string (uuid) | — | Каса, на якій виконано завдання. | | `shift_id` | string (uuid) | — | Зміна, у межах якої видано документи завдання. | | `shift_number` | integer (int64) | — | Наскрізний номер зміни в межах каси. Присвоюється локально: ДПС номера зміни не видає (у квитанції такого поля немає). | | `testing` | boolean | — | Документи завдання тестові — каса в режимі test. | | `receipt` | DocResult | — | Розрахунковий документ, який видало завдання receipt. | | `shift_open` | DocResult | — | Документ відкриття зміни. | | `zreport` | DocResult | — | Z-звіт, яким закрито зміну. | | `shift_close` | DocResult | — | Документ закриття зміни. | | `offline_end` | DocResult | — | Документ завершення офлайн-сесії. | | `key_verification` | KeyVerificationResult | — | Вердикт перевірки ключа КЕП — результат завдання verify_key. | | `key_password_check` | KeyPasswordCheckResult | — | Наслідок швидкої локальної перевірки пароля контейнера, яку кабінет проганяє синхронно під час завантаження ключа: контейнер лише розшифровується, без CMP і без мережі. Завдання вважається успішним і при ok=false — воно дійшло до вердикту. Інфраструктурні збої (БД, KEK, слот підпису) вердиктом не є: там завдання повторюється. | | `reconcile` | ReconcileReport | — | Підсумок звіряння реєстратора з ДПС (sync_register): який стан побачили на боці сервера і що виправили в себе. | | `dps_objects` | array | — | Господарські одиниці власника ключа — результат завдання dps_objects. | ### ReconcileReport (object) Підсумок звіряння реєстратора з ДПС (sync_register): який стан побачили на боці сервера і що виправили в себе. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `fiscal_number` | string | так | Реєстратор, який звіряли. | | `dps_shift_opened` | boolean | так | Чи вважає ДПС зміну відкритою. | | `dps_next_local_number` | integer (int64) | так | Локальний номер, якого ДПС чекає від наступного документа. | | `dps_testing` | boolean | — | Чи вважає ДПС реєстратор тестовим. | | `counter_old` | integer (int64) | — | Наш лічильник локальних номерів до звіряння. | | `counter_new` | integer (int64) | — | Наш лічильник після звіряння. | | `shift_adopted` | boolean | — | Ми прийняли як свою зміну, відкриту на боці ДПС. | | `shift_abandoned` | boolean | — | Ми закрили в себе зміну, якої на боці ДПС немає. | | `cash` | object | — | Скільки готівки зрушила поточна зміна за нашим підрахунком і за підсумками зміни на боці ДПС. Присутнє лише тоді, коли на сервері справді триває зміна. Це довідка, автоматично за нею нічого не виправляється: показник ДПС охоплює одну зміну, а cash_balance — усе життя реєстратора, тож розбіжність не каже, чия сторона помиляється. | | `cash.ours` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `cash.dps` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `cash.match` | boolean | так | Чи збіглися обидва підрахунки. | | `skipped` | string | — | Чому нічого не чіпали (офлайн-сесію звіряння не торкається). Значення: offline_session. | ### DPSTaxObject (object) Одна господарська одиниця власника ключа (dps_objects). | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `name` | string | так | Назва господарської одиниці. | | `address` | string | — | Адреса господарської одиниці. | | `tin` | string | так | Податковий номер власника — ЄДРПОУ або РНОКПП. | | `ipn` | string | — | Індивідуальний податковий номер платника ПДВ. | | `org_name` | string | так | Назва суб'єкта господарювання. | | `registrars` | array | так | ПРРО, зареєстровані за цією господарською одиницею. | ### DPSRegistrar (object) Один ПРРО, зареєстрований за господарською одиницею. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `fiscal_number` | string | так | Фіскальний номер ПРРО, присвоєний ДПС. | | `local_number` | string | так | Локальний номер ПРРО у власника. | | `name` | string | — | Назва ПРРО з реєстрації. | | `closed` | boolean | — | ПРРО скасовано в ДПС. | ### KeyPasswordCheckResult (object) Наслідок швидкої локальної перевірки пароля контейнера, яку кабінет проганяє синхронно під час завантаження ключа: контейнер лише розшифровується, без CMP і без мережі. Завдання вважається успішним і при ok=false — воно дійшло до вердикту. Інфраструктурні збої (БД, KEK, слот підпису) вердиктом не є: там завдання повторюється. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `signing_key_id` | string (uuid) | так | Ключ, пароль якого перевіряли. | | `ok` | boolean | так | Пароль підійшов — контейнер розшифровано. | | `verify_code` | string | — | Присутній завжди при ok=false (напр. wrong_password). | | `verify_error` | string | — | Дослівна помилка бібліотеки підпису. | ### KeyVerificationResult (object) Вердикт повної перевірки ключа КЕП: чи можна ним підписувати документи ПРРО і чий він. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `signing_key_id` | string (uuid) | так | Вказує, який ключ перевіряли. Якщо deleted істинне, цей ідентифікатор більше ні на що не вказує — запис видалено. | | `status` | string | так | active — ключем можна користуватися; invalid — відхилено, причина у verify_code. Значення: active, invalid. | | `verify_code` | string | — | Причина відхилення. not_prro можна перекрити через POST /cabinet/signing-keys/{id}/activate. Значення: wrong_password, cert_not_found, cert_expired, not_prro, verify_failed, ca_unreachable. | | `verify_error` | string | — | Дослівна помилка перевірки. | | `key_type` | string | — | Тип власника, визначений із сертифіката. Значення: individual, legal. | | `prro_capable` | boolean | так | Сертифікат придатний для підпису документів ПРРО. | | `cert_subject` | string | — | Поле subject сертифіката, як його видав АЦСК. | | `org_name` | string | — | Назва організації (або ім'я особи) власника з сертифіката. | | `edrpou` | string | — | ЄДРПОУ юридичної особи з сертифіката, лише цифри. | | `drfo` | string | — | РНОКПП (ДРФО) фізичної особи з сертифіката, лише цифри. | | `deleted` | boolean | — | Запис ключа остаточно видалено — так буває при будь-якому відхиленні, крім not_prro. | ### DocResult (object) Документ, який видало завдання: його номери в журналі та в ДПС і посилання для покупця. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `document_id` | string (uuid) | так | Ідентифікатор документа в сервісі. | | `local_number` | integer | так | Наскрізний номер документа в межах каси (ORDERNUM). | | `fiscal_number` | string | так | Присвоєний фіскальним сервером ДПС. | | `register_fiscal_number` | string | так | Фіскальний номер ПРРО, на якому видано документ, — «ФН ПРРО» на чеку (CASHREGISTERNUM). Це номер каси, а не документа: він однаковий у будь-якому режимі, на відміну від fiscal_number. Присутнє завжди. | | `offline` | boolean | — | Документ підписано в межах офлайн-сесії: його фіскальний номер обчислено локально (..), і на фіскальному сервері він з'явиться лише після надсилання пакета сесії. | | `receipt_url` | string (uri) | — | Копія чека для покупця на короткому домені сервісу (https://r.prro.cloud/<код>) — те, що інтеграція пересилає листом або перетворює на QR. Сторінка відкривається без авторизації: код і є доступом. Формат задає параметр запиту: ?format=html (типово), png (сам чек картинкою 576 px — растрова ширина стрічки 80 мм, друкується на термопринтері як є, з QR усередині) або qr (PNG з адресою цієї ж сторінки). Є лише в розрахункових документів — тільки вони мають друковану форму, — і працює одразу, в офлайн-сесії теж: копію віддає наш журнал, а не фіскальний сервер. Це подання чека, а не доказ фіскалізації: доказ — fiscal_number і tax_url. | | `tax_url` | string (uri) | — | Той самий документ у кабінеті платника податків — незалежне підтвердження. Відсутнє, доки документ не потрапив на фіскальний сервер: у офлайн-чека до надсилання пакета сесії є лише локально обчислений номер. | ### ReceiptInput (oneOf) Чек буває двох форм, які розрізняє поле `type`: розрахунок за товари несе позиції та оплати, рух готівки — лише суму. Поля чужої форми не ігноруються, а відхиляються з 422. Одна з форм: `SettlementReceiptInput`, `ServiceReceiptInput` (розрізняє поле `type`). ### SettlementReceiptInput (object) Розрахунок за товари — реалізація, повернення або сторно. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `cash_register_id` | string (uuid) | — | Реєстратор. Обов'язковий для POST /api/v1/receipts. Кабінетний маршрут бере реєстратор з URL: там поле або відсутнє, або збігається з ним, інакше 422. | | `type` | string | так | sale — реалізація; return — повернення; storno — сторно. Значення: sale, return, storno. | | `cashier` | string | — | Ім'я касира, яке друкують у чеку (CASHIER); без нього рядка на чеку не буде. | | `comment` | string | — | Вільна примітка, яку друкують на самому документі (CHECKHEAD/COMMENT) — наприклад номер замовлення. | | `sold_at` | string (date-time) | — | Коли продаж справді відбувся, якщо інтеграція дійшла до нас пізніше за касу. Це не фіскальний час документа: ДПС приймає ORDERDATE/ORDERTIME лише в межах приблизно хвилини від власного годинника, тож документ завжди позначено моментом подання. Поле лише друкує на документі окремий рядок «Продаж від 03.09.2026 18:11» — перед приміткою з `comment`, якщо вона є. Час у майбутньому та старіший за 31 день — 422. | | `mode` | string | — | Режим доставки результату; параметр запиту ?mode= має перевагу над цим полем. Значення: sync, async. | | `original` | object | — | Зв'язок із початковим чеком; обов'язковий для повернення та сторно. | | `original.fiscal_number` | string | так | Фіскальний номер початкового чека. | | `original.register_fiscal_number` | string | — | Для повернень, оформлених на іншому реєстраторі. | | `original.date` | string (date) | — | У форматі РРРР-ММ-ДД. | | `items` | array | так | Позиції чека; щонайменше одна. | | `payments` | array | так | Форми оплати чека; щонайменше одна. | | `rounding_step` | string | — | Крок заокруглення готівки десятковим рядком ("0.10" за правилами НБУ); без цього поля заокруглення не застосовується. | ### ServiceReceiptInput (object) Готівка, що проходить через касу повз продаж: `service_in` — службове внесення (DOCSUBTYPE 2), `service_out` — службова видача, тобто інкасація (DOCSUBTYPE 4). Це так само розрахунковий документ, тож шлях звичайний: автоматичне відкриття зміни в керованих режимах, офлайн-сесія, журнал і тарифікація як за чек. У підсумках зміни сума йде окремо в service_input/service_output і потрапляє до ZREPBODY Z-звіту; залишок готівки (cash_balance) зсувається на всю суму. Підтип 3 (отримання підкріплення) не підтримується: це валютний документ (DOCTYPE 2) обмінних пунктів і ПТКС. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `cash_register_id` | string (uuid) | — | Реєстратор. Обов'язковий для POST /api/v1/receipts. Кабінетний маршрут бере реєстратор з URL: там поле або відсутнє, або збігається з ним, інакше 422. | | `type` | string | так | service_in — службове внесення; service_out — службова видача (інкасація). Значення: service_in, service_out. | | `cashier` | string | — | Ім'я касира, яке друкують у документі (CASHIER); без нього рядка не буде. | | `comment` | string | — | Вільна примітка, яку друкують на документі (CHECKHEAD/COMMENT). Для руху готівки це єдине місце, де сказано, за що гроші: «Інкасація», «Розмінна монета». | | `sold_at` | string (date-time) | — | Коли продаж справді відбувся, якщо інтеграція дійшла до нас пізніше за касу. Це не фіскальний час документа: ДПС приймає ORDERDATE/ORDERTIME лише в межах приблизно хвилини від власного годинника, тож документ завжди позначено моментом подання. Поле лише друкує на документі окремий рядок «Продаж від 03.09.2026 18:11» — перед приміткою з `comment`, якщо вона є. Час у майбутньому та старіший за 31 день — 422. | | `mode` | string | — | Режим доставки результату; параметр запиту ?mode= має перевагу над цим полем. Значення: sync, async. | | `sum` | string | так | Сума руху — додатний десятковий рядок, до 2 знаків після коми. Це весь документ: підсумовувати тут нічого, позицій немає. | ### ReceiptItem (object) Грошові величини — десяткові рядки ("259.90"); кількість допускає до 3 знаків після коми, ціни — до 2. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `code` | string | — | Внутрішній код товару. | | `barcode` | string | — | Штрихкод товару. | | `uktzed` | string | — | Код УКТЗЕД; взаємовиключний з dkpp. | | `dkpp` | string | — | Взаємовиключний з uktzed. | | `name` | string | так | Назва позиції, як її друкують у чеку. | | `unit_code` | integer | — | Код одиниці виміру (UNITCD). | | `unit_name` | string | — | Назва одиниці виміру: «шт», «кг». | | `quantity` | string | так | Кількість — десятковий рядок, до 3 знаків після коми. | | `price` | string | так | Ціна за одиницю — десятковий рядок, до 2 знаків після коми. | | `tax_letters` | string | — | Податкові літери з tax_rates реєстратора, напр. "А" або "АГ". Порожнє значення застосовує default_tax_letter реєстратора (а якщо типової літери немає — позиція лишається без податку); "-" примусово робить позицію неоподаткованою. | | `discount` | object | — | Знижка на позицію. | | `discount.percent` | string | — | Позначає відсоткову знижку; суму все одно вказують у sum. | | `discount.sum` | string | так | Сума знижки десятковим рядком — її вказують і для відсоткової знижки. | | `excise_labels` | array | — | Коди марок акцизного податку. | | `comment` | string | — | Примітка до позиції. | ### PaymentType (string) Форма оплати; фіскальний код і назву, які потраплять у чек, визначає сервіс: `cash` — 0 ГОТІВКА, `card` — 301 КАРТКА, `certificate` — 305 СЕРТИФІКАТ, `bank_transfer` — 306 ПЕРЕКАЗ З ПОТОЧНОГО РАХУНКУ, `direct_debit` — 100000 ПРЯМИЙ ДЕБЕТ. Залишок готівки реєстратора рухає лише `cash`. Значення: `cash`, `card`, `certificate`, `bank_transfer`, `direct_debit`. ### ReceiptPayment (object) Одна оплата чека: форма, сума і — для картки — реквізити еквайрингу. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `type` | PaymentType | так | Форма оплати; фіскальний код і назву, які потраплять у чек, визначає сервіс: `cash` — 0 ГОТІВКА, `card` — 301 КАРТКА, `certificate` — 305 СЕРТИФІКАТ, `bank_transfer` — 306 ПЕРЕКАЗ З ПОТОЧНОГО РАХУНКУ, `direct_debit` — 100000 ПРЯМИЙ ДЕБЕТ. Залишок готівки реєстратора рухає лише `cash`. | | `sum` | string | так | Сума, віднесена на цю форму оплати. | | `provided` | string | — | Отримано готівкою; решта = provided − sum. | | `means` | string | — | Засіб оплати — чим саме внесено кошти. Положення № 13 (розд. II п.2, рядок 19) вимагає його окремо від форми оплати. Словник — той самий, що в прикладах ДПС: «Картка», «Переказ з поточного рахунку», «Подарунковий сертифікат», «Попередня оплата», «Прямий дебет»; сюди ж те, чого немає в `type`: «ПЕРЕКАЗ З КАРТКИ», «ТАЛОН», «ЖЕТОН». Заміняє лише назву, що друкується (PAYFORMNM); фіскальний код форми (PAYFORMCD) визначає `type`. Для `cash` не приймається. | | `card` | object | — | Реквізити еквайрингу (рядки 12–17). Усі три поля `acquirer_*` описують еквайра торговця, а не самого торговця. | | `card.system_name` | string | — | Назва платіжної системи (рядок 17). | | `card.acquirer_id` | string | — | Ідентифікатор еквайра (рядок 12). | | `card.acquirer_tax_id` | string | — | Податковий номер еквайра (рядок 12). | | `card.acquirer_name` | string | — | Найменування еквайра (рядок 12). | | `card.transaction_date` | string (date-time) | — | Дата й час транзакції на платіжному пристрої (POSTRANSDATE). | | `card.transaction_number` | string | — | Номер транзакції на платіжному пристрої (POSTRANSNUM). | | `card.device_id` | string | — | Ідентифікатор платіжного пристрою (рядок 13). | | `card.epz_details` | string | — | Замаскований номер картки. | | `card.auth_code` | string | — | Код авторизації (рядок 17). | | `card.commission` | string | — | Сума комісійної винагороди еквайра за цим платежем — рядок 14 форми ФКЧ-1, «у разі наявності». У звичайному продажу лишається порожнім: комісію еквайра платить продавець, а не покупець. Заповнюють там, де її справді платить платник — приймання коштів для подальшого переказу та видача готівки держателям карток (розділи VI і VII Положення № 13). Нуль означає, що комісії немає, і рядок не друкується. | ### WebhookEvent (string) task.completed і task.failed — про кожне завершене завдання; shift.opened і shift.closed — життєвий цикл зміни; key.expiring — раз на добу про сертифікат ключа, що спливає протягом 30 днів; register.offline, register.online, register.offline_limit — офлайн-сесії та законні межі їх тривалості (36 і 168 годин); register.remediated — автоматичне усунення розбіжності з ДПС; register.needs_attention — виправлення не тримаються, на реєстратор має поглянути людина; client.balance_low — передплачений баланс добігає кінця (лишилося менше за поріг чеків), єдине попередження перед тим, як чеки почнуть відхилятися з 402. Значення: `task.completed`, `task.failed`, `shift.opened`, `shift.closed`, `key.expiring`, `register.offline`, `register.online`, `register.offline_limit`, `register.remediated`, `register.needs_attention`, `client.balance_low`. ### WebhookEndpoint (object) Точка доставки: куди слати події й на які саме. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `id` | string (uuid) | так | Ідентифікатор вебхука. | | `url` | string | так | Абсолютний http(s)-URL приймача. | | `events` | array | так | Порожній список означає підписку на всі події. Значення: task.completed, task.failed, shift.opened, shift.closed, key.expiring, register.offline, register.online, register.offline_limit, register.remediated, register.needs_attention, client.balance_low. | | `active` | boolean | так | Доставка ввімкнена; false призупиняє її, не втрачаючи черги. | | `created_at` | string (date-time) | так | Коли вебхук створено. | | `updated_at` | string (date-time) | так | Коли його востаннє змінювали. | ### WebhookDelivery (object) Одна доставка події: що слали, чим це скінчилося і що буде далі. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `id` | string (uuid) | так | Ідентифікатор доставки — його ж передають у replay. | | `event` | string | так | Тип події доставки. Крім значень WebhookEvent, доставка може нести зарезервовані типи, на які не можна підписатися: webhook.ping (тестова відправка) і system.dps_* (події доступності ДПС). | | `status` | string | так | pending — у черзі; delivering — триває спроба; delivered — доставлено; failed — спроба невдала, буде повтор; dead — спроби вичерпано. Значення: pending, delivering, delivered, failed, dead. | | `attempts` | integer | так | Скільки спроб уже зроблено. | | `cash_register_id` | string (uuid) | — | Каса, якої стосується подія; у подій рівня клієнта відсутня. | | `data` | any | так | Корисне навантаження події (поле data конверта). | | `last_error` | string | — | Чим завершилася остання невдала спроба. | | `next_attempt_at` | string (date-time) | — | Коли буде наступна спроба; у завершених відсутнє. | | `created_at` | string (date-time) | так | Коли подію поставлено в чергу. | | `delivered_at` | string (date-time) | — | Коли приймач відповів успіхом. | ### Money (string) Копійки десятковим рядком (numeric(14,4)); ніколи не число з рухомою комою. ### CashAmount (string) Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). ### CashBalance (object) Скільки готівки в касі реєстратора. Це лічильник, а не налаштування і не фіскальна величина: він стартує з нуля при створенні реєстратора і бачить лише документи, що пройшли через цей сервіс. Рухають його готівкові рядки оплат — додають на реалізації, віднімають на поверненні та сторно — і службові документи; безготівкові форми не рухають нічого. Береться `sum` рядка оплати, тож решта вже врахована. Лічильник живе на реєстраторі, а не на зміні: готівка переживає Z-звіт. Значення може бути від'ємним — це означає, що в касі було більше, ніж бачив сервіс. Переставити лічильник на справжню суму: PUT .../cash-balance. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `amount` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `as_of` | string (date-time) | — | Коли залишок рухався востаннє. Null — його ще ніщо не рухало, тобто нуль означає «ще нічого не бачили», а не «каса порожня». | ### ShiftTotalsSide (object) Один бік підсумків зміни — реалізація або повернення: скільки розрахунків прийнято і на яку суму, з розкладом за засобами оплати. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `count` | integer | так | Кількість розрахункових документів цього боку. | | `sum` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `pay_forms` | array | — | Накопичено за засобами оплати. code/name — це пара PAYFORMCD / PAYFORMNM, яка піде в Z-звіт; масиву немає, поки бік порожній. | | `pay_forms.code` | integer | так | PAYFORMCD — фіскальний код форми оплати. | | `pay_forms.name` | string | так | PAYFORMNM — назва форми оплати, як її друкують. | | `pay_forms.sum` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | ### ShiftTotals (object) Поточні підсумки відкритої зміни — те саме накопичення, з якого буде побудований Z-звіт; сервіс складає його чек за чеком у тій самій транзакції, що реєструє документ. Сторно віднімається з боку реалізації, а не додається до повернень. Службові внесення й видачі не належать до жодного боку. Розкладу за податковими літерами тут немає — він належить Z-звіту. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `realiz` | ShiftTotalsSide | так | Один бік підсумків зміни — реалізація або повернення: скільки розрахунків прийнято і на яку суму, з розкладом за засобами оплати. | | `return` | ShiftTotalsSide | так | Один бік підсумків зміни — реалізація або повернення: скільки розрахунків прийнято і на яку суму, з розкладом за засобами оплати. | | `service_in` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `service_out` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | ### CashBalanceDeclaration (object) Скільки лічильник показував, скільки показує тепер і поправка між ними. Саме поправка й показує, наскільки підрахунок розійшовся з касою. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `amount` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `previous` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | | `adjustment` | CashAmount | так | Гривні з копійками десятковим рядком — у тій самій формі, що й суми в чеках (на відміну від Money, який рахує копійки і належить тарифікації). | ### BillingUsage (object) Скільки грошей на балансі й скільки з них з'їв період. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `balance` | Money | так | Копійки десятковим рядком (numeric(14,4)); ніколи не число з рухомою комою. | | `soft_limit` | Money | так | Нижня межа балансу: поки balance < soft_limit, чеки заблоковані. | | `blocked` | boolean | так | Чеки зараз заблоковано — балансом або рішенням оператора. | | `period` | object | так | Період, за який пораховано підсумок. | | `period.from` | string (date) | так | Включно. | | `period.to` | string (date) | так | Не включно. | | `receipts` | integer (int64) | так | Кількість тарифікованих чеків за період. | | `charged` | Money | так | Копійки десятковим рядком (numeric(14,4)); ніколи не число з рухомою комою. | | `tariff` | object | так | Тариф, за яким рахували. | | `tariff.plan_id` | string (uuid) | так | Ідентифікатор тарифного плану. | | `tariff.price_per_receipt` | Money | так | Копійки десятковим рядком (numeric(14,4)); ніколи не число з рухомою комою. | ### Invoice (object) Рахунок за один розрахунковий період. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `id` | string (uuid) | так | Ідентифікатор рахунка. | | `period_start` | string (date) | так | Включно. | | `period_end` | string (date) | так | Включно. | | `amount` | Money | так | Копійки десятковим рядком (numeric(14,4)); ніколи не число з рухомою комою. | | `currency` | string | так | Валюта рахунка за ISO 4217 — UAH. | | `status` | string | так | draft — чернетка; issued — виставлено; paid — оплачено; overdue — прострочено. Значення: draft, issued, paid, overdue. | | `created_at` | string (date-time) | так | Коли рахунок сформовано. | ### DPSStatus (object) Знімок супервізора доступності ДПС плюс агрегати парку. Ефективний режим (effective) — це відповідь, на яку реагує конвеєр. | Поле | Тип | Обовʼязкове | Опис | |---|---|---|---| | `verdict` | string | так | Думка детектора незалежно від override. Значення: online, degraded, offline. | | `override` | string | так | Ручний режим оператора. Значення: none, forced_offline, forced_online. | | `effective` | string | так | Підсумковий операційний режим (override переважає вердикт). Значення: online, offline. | | `manual` | boolean | так | Чи діє зараз ручний override. | | `since` | string (date-time) | так | Відколи діє поточний effective-режим. | | `override_reason` | string | — | Чому оператор увімкнув ручний режим. | | `override_by` | string | — | Хто увімкнув ручний режим. | | `override_expires` | string (date-time) | — | Коли TTL override повертає режим у auto (якщо заданий). | | `last_probe_at` | string (date-time) | — | Остання перевірка доступності ДПС. | | `last_ok_at` | string (date-time) | — | Остання успішна відповідь ДПС. | | `last_error` | string | — | Помилка останньої невдалої перевірки. | | `flap_count` | integer | так | Переходи у поточному вікні flap-damping. | | `probe_latency_ms` | integer (int64) | — | Тривалість останньої перевірки, мс. | | `clock_drift_ms` | integer (int64) | — | Розбіжність нашого годинника з годинником ДПС, мс. | | `tunables` | object | — | Пороги, за якими судять числа вище (те саме, що у DPSPulse): ширина вікна, поріг degraded і крок перевірок. | | `tunables.window_seconds` | integer (int64) | — | Ширина вікна детектора, с. | | `tunables.degraded_latency_ms` | integer (int64) | — | Затримка, від якої відповідь вважають повільною, мс. | | `tunables.probe_interval_seconds` | integer (int64) | — | Крок перевірок, с. | | `window` | object | так | Вікно детектора цієї репліки (по реальних викликах ДПС). | | `window.samples` | integer | так | Скільки викликів у вікні. | | `window.failures` | integer | так | Скільки з них невдалих. | | `window.degraded` | boolean | так | Вікно визнано повільним. | | `window.latency_ms` | integer (int64) | так | Затримка викликів у вікні, мс. | | `window.by_class` | object | — | Скільки викликів вікна дав кожен клас результату. | | `offline_registers` | integer | так | Кас, що зараз в офлайн-сесії. | | `oldest_offline_age_seconds` | integer (int64) | так | Вік найдавнішої з відкритих зараз офлайн-сесій, с. |