Checkbox – сервіс програмної реєстрації розрахункових операцій (далі - ПРРО).
Цей документ описує частину аспектів підключення сервісу ПРРО Checkbox для eCommerce порталу або будь-якого іншого додатку, що потребує реалізації функції реєстрації розрахункових операцій (фіскалізації) у вигляді відкритого RESTful API.
Сервіс складається з особистого кабінету, транзакційного процесингу, агентів підпису та фронт-агентів.
Через особистий кабінет виконується реєстрація торговця в системі і управління його точками продажу, касами та касирами.
Транзакційний процессинг забезпечує взаємодію із ДПС, взаємодію із агентами підпису та реалізує API інтерфейс для роботи фронт-агентів через які кінцевий користувач і створює чеки.
Фронт-агентами можуть бути:
В даній статті описано мінімальний необхідний перелік методів, яких буде достатньо для створення інтеграції. З повним переліком методів (без деталізованого опису) ви зможете ознайомитись за посиланнями Swagger та ReDoc.
Із загальною схемою архітектури сервісу ви можете ознайомитись за посиланням.
OPENEDOPENING - будь ласка, зв'яжіться із службою підтримки checkboxDONECANCELLED або ERROR, перевірити причину та усунутиCREATED - будь ласка, зв'яжіться із службою підтримки checkboxDONE)Також радимо ознайомитись із графічною схемою, яка показує принципи, по яким можна побудувати АПІ інтеграцію. Можливо, вона також допоможе розібратися з питаннями, в якості доповнення до цієї документації.
Ніколи не використовуйте бойову касу/касира для цілей тестування, інакше потім вам доведеться, як мінімум, пояснювати податковій, що ви передали некоректні дані та можливо платити штраф.
*.checkbox.ua*.checkbox.in.uae1.o.lencr.orge1.i.lencr.orgocsp.pki.googpki.googХост: https://api.checkbox.ua - єдина адреса (для тестування та фіскальної роботи).
Порт: 443
Тестування - використовуються дані тестового касира та каси з сайту Checkbox (див. Тестування)
Фіскальні дані - для фіскальної роботи використовуються дані бойового касира та каси. (для цього потрібно в ДПС зареєструвати касу та касира - див. Реєстарція)
Будь-який HTTPS-запит починається зі строки METHOD URI, де METHOD — це метод доступу (GET, PUT и т.д.), а URI — адреса запитуваного ресурсу (https://api.checkbox.ua).
З початку запиту йдуть заголовки - текстові рядки виду key: value. Після передається пустий рядок, який означає кінець секції заголовків, після цього - тіло запиту (якщо воно вимагається).
У відповідь прийде рядок з версією HTTPS, кодом та рядковим статусом відповіді, далі - тестові заголовки, пустий рядок, потім тіло відповіді. Кодування для всіх запитів і відповідей — тільки UTF-8. Усі дані, окрім URI та двійкових файлів передаються в форматі JSON. Для рядків використовуються тільки подвійні лапки.
У відповідях 2хх з не пустим тілом та при запиті з тілом обов'язково має бути заголовок:
Content-Type: application/json
Інші можливі заголовки:
Authorization: Bearer <токен авторизації>
X-Client-Name: <назва інтеграції (обов'язкове для заповнення)>
X-Client-Version: <версія інтеграції (опціонально)>
X-Access-Key: <ключ доступу інтеграції (не використовується зараз)>
X-Device-ID: <ID RRO Agent або мобільного пристрою каси (не використовується для API інтеграцій)>
X-License-Key: <ключ ліцензії каси (обов'язкове для заповнення, де вимагається)>
Додаткові параметри вибірки для спискових запитів (фільтрація, сортування, паджинація і тд.), форматуються за правилами HTTPS параметрів params opt.
Якщо успішно, сервер повертає 200 ОК з полями об'єкта в форматі JSON в тілі відповіді (без додаткового оберту в будь-який об'єкт). У випадку, якщо об'єкта із таким UUID не існує, сервер поверне відповідь 404 Not Found.
Якщо успішно, сервер поверне 2хх ОК з масивом об'єкта в форматі JSON в тілі відповіді (тобто починається з [ і закінчується ] ). Якщо масив вийшов пустим, все одно повертається 2хх ОК з пустим масивом в тілі відповіді.
У тілі запиту мають бути перелічені поля об'єкта в форматі JSON без додаткового оберту (тобто {"field1":"value","field2":10}). У випадку успіху сервер має повернути 2хх Created з тілом, аналогічним запиту getByID, з усіма полями зміненого об'єкта.
У запиті мають бути перелічені тільки поля, які мають бути змінені. У випадку успіху сервер поверне 2хх ОК з тілом, аналогічним запиту getByID, з усіма полями зміненого об'єкта.
У випадку успіху повертає 2хх No Data з порожнім тілом, так як повертати немає чого.
Експрес-накладні в системі checkbox - це проект фіскального чека, який повʼязаний із накладною Нової Пошти, Укрпошти, тощо та буде фіскалізовано автоматично після отримання покупцем посилки.
❗️ Важливо: щоб опція створення проектів експрес-накладних стала доступною, спершу активуйте її у вашому особистому кабінеті checkbox за інструкцією.
❗️ Увага: дані методи API checkbox - не створюють саму ТТН в Новій Пошті/Укрпошті. Продавцю необхідно створити окремо або через бізнес-кабінет, або на відділені саму ТТН (ІЗ КОНТРОЛЕМ ОПЛАТИ В ОБОХ ВИПАДКАХ) і після цього вже створювати проект експрес-накладної в системі checkbox.
ТЕСТОВИХ ДАНИХ - НЕ ІСНУЄ.
ПІДКЛЮЧИТИ ТОКЕН НОВОЇ ПОШТИ МОЖЛИВО ТІЛЬКИ НА БОЙОВУ (РЕАЛЬНУ) ФІСКАЛЬНУ КАСУ.
ТЕСТУВАННЯ МОЖЛИВЕ ТІЛЬКИ НА РЕАЛЬНІЙ ФІСКАЛЬНІЙ КАСІ ІЗ РЕАЛЬНОЮ НАКЛАДНОЮ НОВОЇ ПОШТИ.
Розробник інтеграції може або використовувати методи інтеграції checkbox, або може самостійно реалізувати інтеграцію з НП, і вже до checkbox відправляти фіскальний чек після отримання посилки покупцем. Схема роботи при самостійній інтеграціх має виглядати так:

Звіти, які доступні в особистому кабінеті checkbox - частково доступні в глобальному API. Наразі доступні наступні звіти:
Розділ Товарів особистого кабінету також частково доступний по API. Методами API доступне:
Замовлення в системі checkbox - це проект фіскального чека, який необхідно фіскалізувати курʼєру після доставки замовлення покупцеві та його оплати.
Розділ замовлень доступний лише в мобільному додатку checkbox на android та після увімкнення відповідного функціоналу для касира службою технічної підтримки checkbox.
Після увімкнення відповідного функціоналу в мобільному додатку буде доступний розділ Замовлення бокового меню, де відбувається робота із створеними по REST API із зовнішньої системи замовленнями.
Щоб отримувати оновлення в режимі реального часу про сутності (зміни та фіскальні чеки), вам слід правильно налаштувати webhook. У цій інструкції наведено основні методи роботи з webhook.
Вебхуки автоматично видаляються, якщо при надсиланні запиту наш сервіс отримував помилку протягом доби
| Код помилки | HTTP статус-код | Пояснення |
|---|---|---|
| <category>.<code> | 400 | Базовий клас для помилок, які повертає сервіс реєстрації розрахункових операцій. Дані помилки можуть бути як загальним (напр., TimeoutException), так і специфічними для даного сервісу. Такі помилки є ПРРО-специфічними. |
| base.client | 400 | Базовий клас для ClientException - неправильній клієнтський запит до сервера |
| base.not_found | 404 | Базовий клас для помилки NotFoundException - сторінку не знайдено |
| base.rate_limit | 429 | Базовий клас для помилок, які виникають при завеликій кількості запитів |
| base.timeout | 400 | Базовий клас для TimeoutException - перевищено час очікування відповіді від сервера |
| cash_register.<code> | 400 | Базовий клас для помилок, пов'язаних з роботою каси |
| cash_register.ask_codes_in_offline_mode | 400 | Помилка, що виникає при спробі отримання офлайн-кодів в офлайн-режимі |
| cash_register.blocked | 403 | Помилка, що виникає при перевірці статусу каси, якщо касу було заблоковано |
| cash_register.cant_determine | 400 | Помилка, що виникає при спробі отримання офлайн-кодів, якщо передану касу неможливо ідентифікувати в системі |
| cash_register.emergency_foribdden | 400 | Помилка, що виникає при спробі встановити аварійне закриття |
| cash_register.invalid_license_key | 401 | Помилка, що свідчить про невірний ключ ліцензії каси |
| cash_register.is_not_ready | 400 | Помилка, що виникає, якщо каса має незакриті зміни, неопрацьовані транзакції тощо... |
| cash_register.need_to_go_online | 400 | Помилка, що виникає, якщо каса знаходиться в офлайн режимі, коли це заборонено з будь-яких причин |
| cash_register.offline_codes_absent | 400 | Помилка, що виникає перед створенням чека в офлайн-режимі, якщо для каси відсутні офлайн коди |
| cash_register.receipts_limit | 403 | Помилка, що виникає лише для тестових кас, якщо вони перевищують ліміт створення чеків (за замовчуванням - 100 на місяць) |
| cash_register.wrong_fiscal_api_type | 400 | Помилка, що виникає при деяких фіскальних операціях, якщо тип каси - EVPEZ_EXTERNAL |
| cash_register.wrong_type | 400 | Помилка, що виникає, якщо створити чек валютообміну на звичайній касі |
| cashier.<code> | 403 | Базовий клас для помилок, пов'язаних з роботою касира |
| cashier.deactivated | 403 | Помилка, що виникає, якщо деактивований касир намагається здійснити фіскальну дію |
| cashier.invalid_credentials | 403 | Помилка, що виникає, якщо касир намагається авторизуватись невірними даними |
| cashier.invalid_token | 401 | Помилка, що виникає, якщо касир намагається авторизуватись невірним токеном |
| cashier.not_registered | 403 | Помилка, що виникає, якщо касир намагається авторизуватись за допомогою підпису, але даного касиру не існує в системі ПРРО |
| cashier.signature | 403 | Помилка, що виникає, якщо касир має використовувати певний тип підпису, але ключ підпису не налаштований |
| cashier.signature_agent_receipts | 403 | Помилка, що виникає, якщо касир з типом підпису "АГЕНТ" намагається додати зовнішньо-фіскалізований чек |
| cashier.signature_verification_failed | 401 | Помилка, що виникає, якщо касир намагається авторизуватись за допомогою невалідного підпису |
| cashier.test_data | 403 | Помилка, що виникає, якщо реальний касир намагається фіскалізувати дані тестової каси або навпаки |
| currency.<code> | 400 | Базовий клас для помилок, пов'язаних з роботою обміну валют |
| currency.absent_currency | 400 | Помилка, що виникає, якщо при створенні чека валютообміну зазначеної валюти не існує на сервісі ПРРО |
| currency.absent_rate | 400 | Помилка, що виникає, якщо при створенні чека валютообміну курс для валюти не встановлено |
| currency.not_enough_balance | 400 | Помилка при обміні валюти - недостатня кількість готівки в касі |
| currency.not_enough_money | 400 | Помилка, що виникає, якщо при створенні чека валютообміну зазначено недостатню кількість коштів |
| currency.offline_forbidden | 400 | Помилка, що виникає, якщо каса валютообміну намагається створити чек в офлайн-режимі |
| currency.wrong_operation_type | 501 | Помилка, що виникає, якщо при створенні чека внесення/винесення коштів на касі валютообміну зазначено невідомий тип операції |
| data.<code> | 400 | Базовий клас для помилок, пов'язаних з даними (наприклад, такі дані вже існують) |
| data.integrity | 400 | Помилка, пов'язана з дублікацією даних (серверна) |
| database.<code> | 400 | Базовий клас для помилок, пов'язаних з роботою бази даних |
| database.connection_pool_exhausted | 503 | Помилка, що виникає, якщо connection pool бази даних було вичерпано |
| decode.<code> | 422 | Базовий клас для помилок, пов'язаних з декодуванням даних |
| decode.depostisign | 500 | Серверна помилка, яка виникає, якщо ключ підпису DepositSign неможливо зчитати |
| decode.privatbank | 400 | Базовий клас для помилок, пов'язаних з декодуванням даних |
| integration.<code> | 400 | Базовий клас для помилок, які пов'язані з будь-якими інтеграціями сервісу реєстрації розрахункових операцій (ПРРО-специфічна помилка) |
| integration.client_integration_invalid_credentials | 403 | Базовий клас для помилок, які пов'язані з будь-якими інтеграціями сервісу реєстрації розрахункових операцій (ПРРО-специфічна помилка) |
| integration.client_not_implemented | 400 | Базовий клас для помилок, які пов'язані з будь-якими інтеграціями сервісу реєстрації розрахункових операцій (ПРРО-специфічна помилка) |
| integration.server_not_implemented | 501 | Серверна помилка, яка виникає, якщо певну інтеграцію не було налаштовано |
| offline.<code> | 400 | (dev: даний клас є обгорткою для OfflineModeException і використовується як декоратор між новим та старим стилем обробки помилок) Базовий клас для помилок, що свідчать про огріхи в офлайн-роботі ПРРО (ПРРО-специфічна помилка) |
| offline.<code> | 400 | Базовий клас для помилок, що свідчать про огріхи в офлайн-роботі ПРРО (ПРРО-специфічна помилка) |
| offline.code_already_used | 400 | Помилка, яка виникає, коли передається вже використаний фіскальний код |
| offline.reached_limit | 400 | Помилка, яка виникає, коли каса перебуває в офлайні довше дозволеного (наразі не використовується) |
| oms.<code> | 400 | Базовий клас для помилок, які пов'язані з інтеграцією системи керування замовленнями (ПРРО-специфічна помилка) |
| oms.validation | 400 | Помилка системи керування замовленнями, яка виникає, коли система повертає невалідну відповідь |
| online.<code> | 400 | Базовий клас для помилок, що свідчать про огріхи в онлайн-роботі ПРРО (ПРРО-специфічна помилка) |
| online.need_to_go_offline | 409 | Помилка, яка виникає, коли каса потребує переходу в офлайн, але дія проводиться онлайн |
| order.<code> | 400 | Базовий клас для помилок, пов'язаних із замовленнями |
| order.final_status | 400 | Помилка, яка виникає при спробі змінити фіскальний статус чека із вказаним замовленням |
| order.invalid_datetime_range | 400 | Помилка, яка виникає при спробі отримати замовлення в інтервалі >30 днів |
| order.prohibited_delete | 404 | Помилка, яка виникає при спробі видалити замовлення, якого або не існує, або для нього було створено фіскальний чек |
| order.wrong_cashier | 400 | Помилка, яка виникає при спробі отримати замовлення касиром іншої організації |
| order.wrong_organization | 400 | Помилка, яка виникає при спробі отримати замовлення іншої організації |
| organization.<code> | 400 | Базовий клас для помилок, пов'язаних з організацією |
| organization.deactivated | 403 | Помилка, що виникає, якщо організацію було деактивовано |
| organization.goods_integration_disabled | 400 | Помилка, що виникає, якщо організація має використовувати облік товарів, але він не налаштований |
| prepayment.<code> | 400 | Базовий клас для помилок, пов'язаних із чеками передплати |
| prepayment.already_paid | 400 | Помилка, яка виникає, коли при створенні чека післяплати весь ланцюжок вже є сплаченим |
| prepayment.already_processed | 400 | Помилка, яка виникає, коли користувач намагається вчинити фіскальну дію щодо вже опрацьованого ланцюжка чеків передплати |
| prepayment.already_returned | 400 | Помилка, яка виникає, коли при поверненні чека передплати весь ланцюжок вже було повернуто |
| prepayment.daily_limit | 400 | Помилка, яка виникає, коли при поверненні чека передплати готівкою було досягнуто денного ліміту |
| prepayment.daily_limit_return | 400 | Помилка, яка виникає, коли при поверненні чека передплати готівкою було досягнуто денного ліміту |
| prepayment.has_goods_to_return | 400 | Помилка, яка виникає, коли чек передплати містить товари для повернення |
| prepayment.need_to_remove_ettn | 400 | Помилка, яка виникає, коли при поверненні чека передплати було знайдено прив'язану до нього ЕТТН |
| prepayment.relation_id_not_unique | 400 | Помилка, яка виникає, коли при створенні чека передплати користувач передає неунікальний custom_relation_id |
| prepayment.sum_equals_total_sum | 400 | Помилка, яка виникає, коли користувач створює чек передплати із сумою платежів, яка дорівнює сумі всіх чеків ланцюжка |
| prepayment.sum_equals_zero | 400 | Помилка, яка виникає, коли при створенні чека передплати не передають суму платежів (за аналогією зі звичайними чеками) |
| prepayment.sum_too_large | 400 | Помилка, яка виникає, коли при створенні чека передплати сума платежів перевищує максимальне значення |
| receipt.<code> | 400 | Базовий клас для помилок, пов'язаних з фіскальними чеками |
| receipt.already_exists | 400 | Помилка при створенні чека, якщо переданий в запиті ID вже існує |
| receipt.cash_payment_forbidden | 400 | Помилка, яка виникає, якщо відбувається спроба створити інвойс з оплатою готівкою |
| receipt.cash_register_identity | 400 | Чек передплати та післяплати повинні бути створені на касах одного типу |
| receipt.fiscal_codes_identical | 400 | Помилка виникає при спробі замінити фіскальний код на ідентичний |
| receipt.fiscal_date_before_shift_opened | 400 | Помилка, коли фіскальний час чека передує часу відкриття зміни |
| receipt.fiscal_date_in_future | 400 | Помилка, коли фіскальний час чека знаходиться в майбутньому |
| receipt.gambling_taxes | 400 | Помилка, що з'являється, якщо в одному чеку є податки з is_gambling: False, is_gambling: True |
| receipt.goods_already_returned | 400 | Товари чека вже були повністю повернені |
| receipt.goods_to_return | 400 | Помилка виникає, якщо певних товарів в чеку повернення більше, ніж в чеку продажу |
| receipt.included_gambling_taxes | 400 | Помилка, що з'являється, якщо в одному чеку є податок з is_gambling: False, included: True |
| receipt.invalid_good_price | 400 | Помилка, яка виникає, якщо сума товару після розрахунку є неправильною |
| receipt.invalid_sum | 400 | Помилка, яка виникає, якщо сума чека після розрахунку є неправильною |
| receipt.mixed_taxes | 400 | Помилка, що з'являється, якщо в одному чеку є податки з included: False, included: True |
| receipt.not_enough_balance | 400 | Помилка при поверненні готівки - недостатня кількість готівки в касі |
| receipt.payment_negative_sum | 400 | Передано платіж з від'ємною сумою |
| receipt.payment_sum_too_small | 400 | Сума платежів не може бути менше ніж сума чека |
| receipt.previous_id_last_id_differs | 400 | Помилка, яка виникає, якщо в запиті вказаний неправильний previous_receipt_id |
| receipt.related_not_found | 400 | Помилка при передачі related_receipt_id, якого не існує в системі (code=400) |
| receipt.rest | 400 | Помилка, яка пов'язана з рештою (від'ємна решта або решта при оплаті карткою) |
| receipt.return_has_rest | 400 | Помилка при поверненні чека, якщо з'являється залишок до сплати |
| receipt.return_prepayment | 400 | Помилка, коли чек передплати намагаються повернути як звичайний чек |
| receipt.sum_calculation_impossible | 400 | Сума сплати не може бути автоматично розрахована, оскільки сума інших платежів перевищує суму чека |
| receipt.sum_too_large | 400 | Загальна сума чека перевищує максимально допустиме значення |
| receipt.test_cash_register | 400 | Чек був створений на тестовій касі, його можна повертати тільки з такої ж каси |
| receipt.total_sum_negative | 400 | Передано чек з від'ємною сумою до сплати |
| receipt.type_not_supported | 501 | Помилка, що з'являється при спробі додати зовнішній чек з типом, який не підтримується даним ПРРО |
| receipt.used_goods_constraints | 400 | Знижки не можуть бути використані при продажі вживаного товару зі зміненою вартістю |
| receipt.visualization_not_fiscalized | 424 | Помилка, що з'являється при спробі отримати візуалізацію не фіскалізованого чека |
| receipt.wrong_type_fiscal | 400 | Помилка проведення фіскальної операції з нефіскальним чеком |
| receipt.wrong_type_service | 400 | Помилка проведення нефіскальної операції з фіскальним чеком |
| receipt.zero_payment_after_rounding | 400 | Сума сплати після округлення не може бути 0 |
| receipt.zero_payments | 400 | В запиті передано більше одного платежу з нулем |
| recreate_offline.<code> | 400 | Базовий клас для помилок, пов'язаних із перестворенням чека. Опис цих помилок дублює власне текст помилок. |
| recreate_offline.after_go_offline | 400 | Не можна оновити чек після переходу в режим офлайн! |
| recreate_offline.after_go_online | 400 | Не можна оновити чек після переходу в режим онлайн! |
| recreate_offline.current_shift | 400 | Замінити фіскальний код можна тільки в поточній зміні |
| recreate_offline.general | 400 | Помилка, що свідчить про неможливість перестворення чека (не має з'являтись в такому вигляді) |
| recreate_offline.only_last_receipt | 400 | Оновити можна лише останній чек у зміні |
| recreate_offline.opened_shift | 400 | Замінити фіскальний код можна тільки у відкритій зміні |
| recreate_offline.wrong_status | 400 | Чек у будь-якому статусі, окрім DONE, не може бути оновлено |
| reject_last_receipt.<code> | 400 | Базовий клас для помилок, пов'язаних із скасуванням останнього чека. Опис цих помилок дублює власне текст помилок. |
| reject_last_receipt.after_go_offline | 400 | Не можна відмінити чек після переходу в режим офлайн! |
| reject_last_receipt.after_go_online | 400 | Не можна відмінити чек після переходу в режим онлайн! |
| reject_last_receipt.after_service_receipts | 400 | Відмінити можна тільки чек, після якого не було службового внесення/вилучення |
| reject_last_receipt.current_shift | 400 | Відмінити можна тільки чек з поточної зміни |
| reject_last_receipt.general | 400 | Помилка, що свідчить про неможливість скасування останнього чека (не має з'являтись в такому вигляді) |
| reject_last_receipt.only_last_receipt | 400 | Відмінити можна лише останній чек у зміні! |
| reject_last_receipt.opened_shift | 400 | Відмінити чек можна тільки у відкритій зміні |
| reject_last_receipt.prepayment | 400 | Неможливо відмінити чек з передплатою |
| reject_last_receipt.service | 400 | Службовий чек не може бути відмінено |
| reject_last_receipt.wrong_status | 400 | Чек у будь-якому статусі, окрім DONE, не може бути відмінено |
| shift.<code> | 400 | Базовий клас для помилок, пов'язаних із фіскальною зміною |
| shift.already_exists | 400 | Помилка виникає при спробі відкриття зміни з id, який вже існує в системі |
| shift.already_opened | 400 | Помилка виникає при спробі відкриття зміни касою, яка вже має відкриту зміну |
| shift.not_opened | 400 | Помилка виникає при спробі виконання фіскальної дії, якщо фіскальну зміну не відкрито |
| shift.opened_too_long | 400 | Помилка виникає при спробі проведення фіскальної дії в зміні, яку відкрито більше ніж 24 години тому |
| transaction.<code> | 400 | Базовий клас для помилок, пов'язаних з транзакціями |
| transaction.date_in_past | 400 | Помилка, що виникає при спробі переходу в офлайн, якщо вказана дата транзакції менша, ніж дата створення останньої транзакції |
| transaction.queue_is_not_empty | 400 | Помилка, що виникає при скасуванні останнього чека або перестворенні чека в офлайні, якщо знайдено неопрацьовані транзакції |
| validation.custom | 422 | Базовий клас для помилок валідації - передано невалідні дані в запиті |
Якщо у Вас виникли питання, Ви знайшли помилку або хочете запропонувати вказати додаткову інформацію в інструкціях - Ви завжди можете зв'язатись з нами зручним для вас способом.