← ATOM

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 menumenuМеню з цінами й наявністю (available: false — у стоп-листі). Підтримує ETag / If-None-Match → 304
POST ordersordersНове замовлення на доставку або самовивіз
GET orders/<id>ordersСтатус свого замовлення
GET sales?from=YYYY-MM-DD&to=YYYY-MM-DDsalesЗакриті чеки за період (до 31 дня): суми, оплати, знижки, чайові, позиції
GET stockstockЗалишки продуктів: кухня, бар, разом, собівартість за одиницю, мінімум, штрихкоди
GET receipts?from=YYYY-MM-DD&to=YYYY-MM-DDstockНадходження (накладні) за період (до 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.statusordersЗмінився статус вашого замовлення (зазвичай за 1–2 хв)
stop.changedmenuСтрава потрапила в стоп-лист або повернулась у продаж (за ~30 с)
menu.changedmenuЗмінились ціни, страви чи категорії — заберіть 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 (посилання на головній сторінці).