API для партнерів
Версія v1. Для агрегаторів доставки, сайтів, програм лояльності й бухгалтерії. Ключ видає власник закладу в кабінеті ATOM → ⚙️ Заклад → 🔌 API.
Основи
Адреса: https://posatom.online/v/<заклад>/api/v1/ — ідентифікатор закладу показано в кабінеті поруч із ключем.
Ключ передається в заголовку Authorization: Bearer atk_… (або X-Api-Key). Ключ має права: menu, orders, sales, stock. Тримайте його лише на своєму сервері, не в браузері чи мобільному застосунку.
Ліміт: 60 запитів на хвилину на ключ (далі 429). Опитувати нас не потрібно: про зміни статусів, меню й стоп-листа ми самі повідомляємо через webhook.
Формат: JSON, UTF-8, суми — у гривнях (цілі), час — ISO 8601.
curl https://posatom.online/v/demo-cafe/api/v1/ping \
-H "Authorization: Bearer atk_1a2b3c4d_…"
🧪 Пісочниця
Спробувати API без договору й без справжніх грошей — на демо-закладі «Все за 500». Ключ публічний, усі права, ліміт 30 запитів на хвилину з однієї IP-адреси. Дані демо-закладу щоночі повертаються до початкових.
Адреса: https://posatom.online/v/atom-demo/api/v1/
Ключ: atk_00000000_5a4db0c55a4db0c55a4db0c55a4db0c5
Замовлення в пісочниці «рухаються» самі: щохвилини наступний статус (new → acc → cook → ready → road → done, для самовивозу без road). Щоб отримувати order.status, додайте в замовлення поле "webhook": "https://…"; підпис — секретом whs_sandbox. Використовуйте унікальний ext_id: ключ спільний для всіх.
Натисніть кнопку — тут буде відповідь сервера.
curl https://posatom.online/v/atom-demo/api/v1/menu \
-H "Authorization: Bearer atk_00000000_5a4db0c55a4db0c55a4db0c55a4db0c5"
Для свого закладу ключ видає власник у кабінеті; ключ пісочниці там не працює.
Методи
| Метод | Право | Що робить |
|---|---|---|
GET ping | — | Перевірка ключа: заклад, назва ключа, права |
GET menu | menu | Меню з цінами й наявністю (available: false — у стоп-листі). Підтримує ETag / If-None-Match → 304 |
POST orders | orders | Нове замовлення на доставку або самовивіз |
GET orders/<id> | orders | Статус свого замовлення |
GET sales?from=YYYY-MM-DD&to=YYYY-MM-DD | sales | Закриті чеки за період (до 31 дня): суми, оплати, знижки, чайові, позиції |
GET stock | stock | Залишки продуктів: кухня, бар, разом, собівартість за одиницю, мінімум, штрихкоди |
GET receipts?from=YYYY-MM-DD&to=YYYY-MM-DD | stock | Надходження (накладні) за період (до 31 дня): постачальник, номер, сума, оплата, рядки |
Нове замовлення
POST /v/demo-cafe/api/v1/orders
{
"ext_id": "GL-100245", // ваш номер — повтор не створить дубль
"type": "delivery", // delivery | pickup
"customer": { "name": "Олена", "phone": "0671234567" },
"address": "вул. Свободи 5, кв. 12",
"entrance": "під'їзд 2, домофон 12",
"time": "18:30", // необовʼязково; порожньо — якнайшвидше
"payment": "prepaid", // cash | card | prepaid
"paid_sum": 540, // для prepaid — скільки сплачено у вас
"items": [ { "id": "carbonara", "qty": 2 }, { "id": "lemonade", "qty": 1, "variant": "0.5" } ],
"comment": "без цибулі",
"cutlery": 2
}
Відповідь: { "ok": true, "id": "3f9a1c0b7e", "ext_id": "GL-100245", "no": "Д-12", "total": 540, "status": "new", "prep_min": 30 }. Ціни рахує заклад за своїм меню; страви, яких немає або в стоп-листі, пропускаються.
Помилки: closed_for_orders, closed_now, below_minimum, no_valid_items, customer, address, excise (алкоголь не продається зараз).
Статуси
| status | Значення |
|---|---|
new | Прийшло, чекає підтвердження закладу |
acc | Прийнято |
cook | Готується |
ready | Готово до видачі |
road | Курʼєр у дорозі (courier — імʼя) |
done | Видано, чек закрито |
rej | Відхилено або скасовано закладом |
Webhook
Якщо для ключа вказано адресу webhook (лише https), ATOM сам надсилає POST, коли щось змінилось. Тип події — у полі event і заголовку X-Atom-Event.
| event | Право | Коли |
|---|---|---|
order.status | orders | Змінився статус вашого замовлення (зазвичай за 1–2 хв) |
stop.changed | menu | Страва потрапила в стоп-лист або повернулась у продаж (за ~30 с) |
menu.changed | menu | Змінились ціни, страви чи категорії — заберіть menu з новим etag |
order.status
{ "event": "order.status", "venue": "demo-cafe",
"order": { "id": "3f9a1c0b7e", "ext_id": "GL-100245", "status": "road", "no": "Д-12", "courier": "Андрій" },
"sent_at": "2026-10-21T15:04:05.000Z" }
stop.changed
{ "event": "stop.changed", "venue": "demo-cafe", "etag": "\"m4f1c…\"",
"stopped": ["carbonara"], // щойно в стоп-листі
"available": ["lemonade"], // знову в продажу
"stop_list": ["carbonara", "tiramisu"], // повний стоп-лист зараз
"sent_at": "2026-10-21T15:04:05.000Z" }
menu.changed
{ "event": "menu.changed", "venue": "demo-cafe", "etag": "\"m9a2d…\"", "sent_at": "…" }
Кілька змін поспіль приходять одним сповіщенням. Перше сповіщення приходить лише після першої зміни: на старті заберіть меню запитом GET menu.
Відповідайте кодом 2xx. Якщо ні — повтор через 1, 5, 30 і 120 хвилин. Тестове сповіщення з кабінету має "event": "ping".
Перевірка підпису
Заголовок X-Atom-Signature — HMAC-SHA256 тіла запиту секретом whs_… (видається разом із ключем), у hex.
// Node.js
const crypto = require('crypto');
const ok = crypto.timingSafeEqual(
Buffer.from(req.headers['x-atom-signature'], 'hex'),
crypto.createHmac('sha256', process.env.ATOM_WHS).update(rawBody).digest());
Коди відповідей
200 — успіх · 304 — меню не змінилось · 400 — помилка в даних (поле error) · 401 — немає або невірний ключ · 403 — у ключа немає права · 404 — не знайдено · 429 — ліміт запитів.
Питання щодо інтеграції — підтримка ATOM у Telegram (посилання на головній сторінці).