API · OpenAPI 3.1

Открытый REST API для бронирований.

Все операции в ЗалПлан доступны через JSON REST API. JWT-аутентификация, multi-tenant изоляция, идемпотентность, webhook-доставка, машиночитаемая спецификация OpenAPI 3.1.

Быстрый старт

# 1. Получить токен
curl -X POST https://zalplan.ru/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","password":"..."}'

# 2. Запрос с токеном
TOKEN="..."
curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/locations

Принципы

Календарь — ICS sync

ЗалПлан говорит на iCalendar (RFC 5545) в обе стороны. Подписывайте Google / Apple / Outlook на наши фиды и импортируйте чужие календари — события становятся блоками доступности.

Экспорт (outbound)

# 1. Создать подписанный фид
curl -X POST https://zalplan.ru/api/v1/calendar-feeds \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Все бронирования","scope_type":"account"}'
# → {"id": "cf_...", "public_url": "https://zalplan.ru/api/v1/calendar/feed/<slug>/<token>.ics"}

# 2. Подпишите Google / Apple / Outlook на public_url
# Подтверждённые бронирования стримятся VEVENT-ами с UID=booking-<slug>@zalplan.ru

# 3. Прокатить токен (старый URL станет 404)
curl -X POST https://zalplan.ru/api/v1/calendar-feeds/<slug>/rotate \
  -H "Authorization: Bearer $TOKEN"

Импорт (inbound)

# 1. Подписаться на удалённый ICS (Google, Outlook, кастомный)
curl -X POST https://zalplan.ru/api/v1/external-calendars \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Google зала","url":"https://calendar.google.com/.../basic.ics","space_id":"spc_...","sync_mode":"read_only_blocking"}'

# 2. Синхронизировать (по расписанию через Celery beat или вручную)
curl -X POST https://zalplan.ru/api/v1/external-calendars/<slug>/sync \
  -H "Authorization: Bearer $TOKEN"
# → {"added": 3, "updated": 1, "removed": 0}

# 3. Импортированные события с blocks_availability=true теперь блокируют /v1/availability/check
# Конфликты возвращаются с kind="external"

Платежи — онлайн-эквайринг

Принимайте оплату прямо в виджете. Поддерживаются ЮKassa, Тинькофф, CloudPayments и Stripe. По каждому подтверждённому платежу автоматически выпускается чек по 54-ФЗ через Атол ОФД.

1. Какие провайдеры включены

# Виджет или ваше приложение спрашивают платформу,
# какие эквайринги настроены на сервере:
curl https://zalplan.ru/api/v1/public/payment-providers
# → {"providers": ["yookassa", "tinkoff"]}

2. Создать чекаут для бронирования

curl -X POST https://zalplan.ru/api/v1/public/checkout \
  -H 'Content-Type: application/json' \
  -d '{
    "booking_slug": "bk_01H...",
    "provider": "yookassa",
    "return_url": "https://example-venue.ru/booking?zp_intent=PENDING"
  }'
# → {
#   "id": "pmt_01H...",
#   "provider": "yookassa",
#   "confirmation_url": "https://yoomoney.ru/checkout/payments/v2/...",
#   "status": "pending"
# }
# Перенаправьте браузер на confirmation_url. После оплаты пользователь
# вернётся на return_url; ваше приложение может опросить
# /v1/public/checkout/{id} для актуального статуса.

3. Webhook от эквайринга

# Каждый провайдер шлёт server-to-server:
POST https://zalplan.ru/api/v1/webhooks/payments/{provider}

# ЮKassa: IP allow-list, тело { "event": "payment.succeeded", "object": {...} }
# Тинькофф: SHA-256 Token в теле, шифрует все верхнеуровневые scalar-поля + Password
# CloudPayments: HMAC-SHA256 в заголовке Content-HMAC (base64)
# Stripe: t=…,v1=… в заголовке Stripe-Signature (HMAC-SHA256 c защитой от replay 5 мин)

# ЗалПлан мэтчит provider_payment_id → PaymentIntent, обновляет статус,
# зеркалит на booking.payment_status / invoice.paid_cents, и фаерит
# исходящий webhook 'payment.received' и Celery-таску фискализации.

4. Админ — рефанд

# Полный или частичный возврат
curl -X POST https://zalplan.ru/api/v1/payment-intents/pmt_01H.../refund \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"amount_cents": 50000, "reason": "Клиент отменил"}'
# → PaymentIntent { status: "partial_refund", refunded_cents: 50000, ... }

Промокоды и подарочные карты

Маркетинговые скидки, спец-тарифы, подарочные карты с балансом. Применяются на этапе бронирования — в админке и через виджет.

1. Создать промокод

# Через REST (или просто в админке: «Промокоды» → «Создать промокод»)
curl -X POST https://zalplan.ru/api/v1/promo-codes \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "code": "NEWYEAR2026",
    "discount_type": "percent",
    "discount_value": 1500,
    "min_spend_cents": 500000,
    "valid_until": "2026-12-31T23:59:00+03:00",
    "max_redemptions": 100,
    "first_time_only": true,
    "stack_mode": "exclusive"
  }'

# Типы скидок:
#   percent       — процент (значение в base points: 1500 = 15%)
#   fixed         — фиксированная сумма (cents/копейки)
#   override_rate — спец. почасовой тариф (cents/час)
#   free_addon    — бесплатная услуга/доп (значение = price addon в cents)
#
# Режим стека (stack_mode):
#   exclusive  — нельзя комбинировать с другими промокодами
#   stackable  — суммируется со всеми «совместимыми»
#   best_only  — применяется только если даёт бóльшую скидку, чем сумма stackable

2. Валидация на стороне клиента (виджет)

# Открытый эндпоинт — виджет вызывает его при нажатии «Применить промокод»:
curl -X POST https://zalplan.ru/api/v1/public/promo-codes/validate \
  -H "Content-Type: application/json" \
  -d '{
    "code": "NEWYEAR2026",
    "space_id": "spc_…",
    "booking_total_cents": 1200000,
    "client_email": "anna@example.com"
  }'

# Ответ:
{
  "valid": true,
  "discount_cents": 180000,
  "applied_promos": [{"code":"NEWYEAR2026","amount_cents":180000,"discount_type":"percent"}],
  "applied_gift_cards": [],
  "errors": []
}

3. Применение при бронировании

# Виджет (и админка) передаёт promo_code в POST /bookings — backend сам
# выполняет валидацию, списывает discount с total_price_cents, добавляет
# отрицательную строку в price_breakdown, инкрементит redemption_count
# и пишет аудит-запись в promo_redemptions.

curl -X POST https://zalplan.ru/api/v1/bookings \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "space_id": "spc_…",
    "start_time": "2026-12-31T19:00+03:00",
    "end_time":   "2027-01-01T04:00+03:00",
    "client_email": "anna@example.com",
    "promo_code": "NEWYEAR2026"
  }'

4. Подарочные карты

# Выпустить одну карту:
curl -X POST https://zalplan.ru/api/v1/gift-cards \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "initial_balance_cents": 1000000,
    "issued_to_email": "gift-recipient@example.com",
    "expires_at": "2027-12-31T23:59+03:00",
    "sold_for_cents": 800000
  }'

# Сгенерировать партию (с автоматическим CSV-экспортом в админке):
curl -X POST https://zalplan.ru/api/v1/gift-cards/bulk-generate \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{ "count": 50, "initial_balance_cents": 500000, "prefix": "NY26-" }'

# Карты применяются тем же полем promo_code в POST /bookings. Сначала
# списывается промо-скидка (если есть), затем gift card дебитуется
# с оставшейся суммы. Аудит — в /gift-cards/{slug}/redemptions.

Услуги и оборудование

Площадки зарабатывают не только на аренде зала. ЗалПлан хранит каталог услуг (кейтеринг, декор, A/V, персонал), инвентарь оборудования с учётом запасов и список внешних поставщиков. Любая услуга или оборудование добавляется к бронированию как строка с количеством и ценой — общая сумма пересчитывается автоматически.

1. Категории и услуги

# Создать категорию
curl -X POST https://zalplan.ru/api/v1/service-categories \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{ "name": "Кейтеринг", "icon": "utensils" }'

# Создать услугу внутри категории
curl -X POST https://zalplan.ru/api/v1/service-items \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "category_id": "svccat_…",
    "name": "Фуршет на 50 гостей",
    "unit": "per_person",
    "price_cents": 250000,
    "vat_percent": 2000
  }'

# Единицы измерения: per_hour | per_event | per_person | per_unit
# vat_percent — basis points (2000 = 20% НДС). Категории можно сортировать
# через POST /service-categories/reorder со списком slug-ов.

2. Оборудование с учётом запасов

curl -X POST https://zalplan.ru/api/v1/equipment-items \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "location_id": "loc_…",
    "name": "Микрофон беспроводной Shure",
    "total_stock": 6,
    "rental_price_cents": 50000,
    "rental_unit": "per_event",
    "serial_numbers": ["SN-001","SN-002","SN-003"]
  }'

# Состояния (maintenance_status):
#   operational   — работает, доступно для бронирования
#   maintenance   — на обслуживании
#   broken        — сломано (никогда не доступно)

# Проверка доступности на интервал:
curl -X POST https://zalplan.ru/api/v1/equipment-items/check-availability \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "equipment_id": "equip_…",
    "start_time": "2026-06-01T10:00+03:00",
    "end_time":   "2026-06-01T18:00+03:00",
    "requested_quantity": 4
  }'

3. Добавление к бронированию

# Добавить позицию: услугу ИЛИ оборудование (не оба сразу).
curl -X POST https://zalplan.ru/api/v1/bookings/bk_…/line-items \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "equipment_item_id": "equip_…",
    "quantity": 4,
    "unit_price_cents": 50000
  }'

# Бэкенд проверяет, что для оборудования суммарное количество по всем
# активным бронированиям в этом окне не превысит total_stock. При нехватке —
# 409 conflict с деталями {already_reserved, total_stock, requested}.
#
# При каждом добавлении/удалении/изменении quantity backend
# пересчитывает booking.total_price_cents и обновляет price_breakdown:
# добавляет строки type="line_item" с amount_cents = subtotal_cents.

4. Поставщики

curl -X POST https://zalplan.ru/api/v1/vendors \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "name": "Кейтеринг «Премьера»",
    "contact_name": "Иван Иванов",
    "email": "i@premiera.ru",
    "phone": "+7 495 123 4567",
    "service_areas": ["catering","decor"],
    "contract_url": "https://drive.example.com/contract.pdf"
  }'

# Любая услуга или оборудование может ссылаться на vendor_id —
# в админке и отчётах увидите, кто стоит за каждой позицией каталога.

Документы и e-подпись

Генерируйте договоры, акты, оферты и NDA из markdown-шаблонов с подстановкой {{переменных}} бронирования, клиента и площадки. ЗалПлан сразу отдаёт PDF на DejaVu Cyrillic, а ссылка /sign позволяет клиенту подписать документ — мы фиксируем имя, email, время, IP и SHA-256 исходного PDF.

1. Шаблон документа

# Создать шаблон
curl -X POST https://zalplan.ru/api/v1/document-templates \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "name": "Договор оказания услуг",
    "doc_type": "contract",
    "requires_signature": true,
    "content_markdown": "# Договор No {{booking.number}}\n\nИсполнитель: {{account.legal_name}} (ИНН {{account.inn}}).\n\nЗаказчик: {{client.legal_name}} (ИНН {{client.inn}}).\n\n## Сроки\n\nС {{booking.start_date}} {{booking.start_time}} по {{booking.end_date}} {{booking.end_time}}.\n\n## Стоимость\n\nИтого: {{booking.total_rub}} ₽."
  }'

# Получить каталог доступных переменных:
curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/document-templates/variables
# → {"data": [{"key": "account.name", "label": "..."}, ...]}

2. Создать документ из шаблона

curl -X POST https://zalplan.ru/api/v1/documents \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "template_id": "doctmpl_…",
    "booking_id": "bk_…"
  }'
# →  {
#       "id": "doc_…",
#       "title": "Договор оказания услуг",
#       "status": "draft",
#       "pdf_url": "https://zalplan.ru/api/v1/uploads/<acc_id>/doc_doc_….pdf",
#       "rendered_markdown": "...",
#       "document_hash": "…sha256…",
#       "version": 1
#    }

# Mail-merge подставит:
#   {{account.name}} {{account.legal_name}} {{account.inn}} {{account.address}}
#   {{client.name}} {{client.email}} {{client.phone}} {{client.legal_name}} {{client.inn}}
#   {{booking.slug}} {{booking.number}} {{booking.start_date}} {{booking.end_date}}
#   {{booking.duration_hours}} {{booking.total_rub}} {{booking.total_kopecks}}
#   {{location.name}} {{location.address}} {{space.name}} {{space.capacity}}
#   {{today}} {{today_rus}}

3. Отправить клиенту на подпись

curl -X POST https://zalplan.ru/api/v1/documents/doc_…/send \
  -H "Authorization: Bearer $TOKEN"
# → {
#     "status": "sent",
#     "signing_url": "https://zalplan.ru/sign?d=doc_…&t=<token>",
#     "sign_token_expires_at": "2026-06-25T…"
#   }

# Отправьте signing_url клиенту — он откроет страницу /sign, прочитает документ,
# введёт ФИО + email и нажмёт "Подписать". Бэкенд:
#   1. запишет событие "signed" с IP и user-agent в document_signature_events
#   2. перегенерирует PDF с финальной страницей-сертификатом (имя, время, IP,
#      SHA-256 исходного документа)
#   3. вернёт signed_pdf_url и переведёт документ в статус "signed"
#   4. одноразовый sign_token будет инвалидирован

4. Аудит подписей

curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/documents/doc_…/events
# → {"data": [
#     {"event": "sent",   "created_at": "…", "actor_name": "Менеджер"},
#     {"event": "viewed", "created_at": "…", "actor_ip": "…"},
#     {"event": "signed", "created_at": "…", "actor_name": "Иван Иванов",
#                         "actor_email": "i@example.com", "actor_ip": "…",
#                         "payload": {"signed_pdf_url": "…", "document_hash": "…"}}
#   ]}

Маркетинговые кампании

Авто-рассылки email и SMS: триггеры по событиям бронирования, расписание или ручной запуск. Сегментация по тегам / общему чеку / давности брони / площадке, A/B варианты, трекинг открытий + кликов и one-click отписка.

1. Создать кампанию

curl -X POST https://zalplan.ru/api/v1/campaigns \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "name": "Спасибо за бронь",
    "channel": "email",
    "trigger_type": "event",
    "trigger_event": "booking.confirmed",
    "trigger_delay_minutes": 30,
    "audience_filter": {
      "min_total_spend_cents": 50000,
      "last_booking_within_days": 90,
      "tags": ["VIP"]
    },
    "subject_template": "{{client.name}}, спасибо за бронирование!",
    "body_template": "Здравствуйте, {{client.name}}!\n\nЖдём вас {{booking.start_date}} в {{booking.start_time}}.\n\nПолучите 5% скидку: [Забронировать снова](https://zalplan.ru/book?promo=COMEBACK5)",
    "status": "active"
  }'
# → {"id": "camp_…", "status": "active", ...}

2. Триггеры

3. Фильтр аудитории

Все ключи объединяются по AND. Пустой фильтр — вся база клиентов.

4. A/B варианты

curl -X PATCH https://zalplan.ru/api/v1/campaigns/camp_… \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "variants": [
      {"key": "A", "subject": "Скидка 10% на следующее бронирование",
       "body": "Дорогой {{client.name}}, ..."},
      {"key": "B", "subject": "Спасибо за выбор {{account.name}}",
       "body": "Здравствуйте, {{client.name}}, ..."}
    ]
  }'

# Распределение варианта детерминированное:
# variant = variants[ sha256(client_id + ":" + campaign_id) % len(variants) ]
# Один клиент всегда получит один и тот же вариант — отчёты по A/B стабильны.

5. Трекинг и отписка

При отправке email-кампании сервер автоматически:

6. Статистика и журнал

# Сводная статистика
curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/campaigns/camp_…/stats
# → {
#     "totals": {"total": 312, "sent": 280, "opened": 152, "clicked": 47,
#                "bounced": 8, "suppressed": 24, "pending": 0},
#     "by_variant": {"A": {"sent": 142, "opened": 78, "clicked": 25},
#                    "B": {"sent": 138, "opened": 74, "clicked": 22}},
#     "open_rate": 0.543, "ctr": 0.168
#   }

# Полный журнал отправок
curl -H "Authorization: Bearer $TOKEN" \
  "https://zalplan.ru/api/v1/campaign-sends?campaign_id=camp_…&status=clicked"

# Список адресов-отписок аккаунта
curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/suppression-entries

Отзывы и рейтинг

Сбор пост-ивентовых отзывов через подписанную ссылку, модерация в админке, агрегированный рейтинг и список последних отзывов в виджете площадки. Авто-приглашение уходит клиенту через 24 часа после booking.end_time — каждый час Celery-beat сметает завершённые брони и создаёт новые ReviewRequest.

1. Жизненный цикл отзыва

2. Модерация — Admin API

# Список pending-отзывов одной площадки
curl -H "Authorization: Bearer $TOKEN" \
  "https://zalplan.ru/api/v1/reviews?status=pending&location_id=loc_…"

# Опубликовать отзыв
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"status":"published"}' \
  https://zalplan.ru/api/v1/reviews/rev_…/status

# Ответить от имени площадки
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"reply":"Спасибо за тёплые слова! Ждём вас снова."}' \
  https://zalplan.ru/api/v1/reviews/rev_…/reply

# Сводный рейтинг площадки
curl -H "Authorization: Bearer $TOKEN" \
  https://zalplan.ru/api/v1/reviews/-/summary/loc_…
# → {"location_id":"loc_…","average_rating":4.7,"count":23,"distribution":{"1":0,"2":1,"3":2,"4":5,"5":15}}

3. Публичный поток сбора отзыва

# 1. Открыть форму
curl https://zalplan.ru/api/v1/public/reviews/submit/{token}
# → {"token":"…","booking":{…},"location":{…},"space":{…},"client_name":"Иван"}

# 2. Отправить отзыв (1-5 звёзд, текст и имя — необязательны)
curl -X POST https://zalplan.ru/api/v1/public/reviews/submit/{token} \
  -H 'Content-Type: application/json' \
  -d '{"rating":5,"text":"Отличная площадка!","reviewer_name":"Иван"}'
# → {"id":"rev_…","status":"pending","message":"Спасибо за отзыв! …"}

4. Публичная отдача для виджета

# Сводка
curl https://zalplan.ru/api/v1/public/locations/loc_…/reviews/summary
# → {"location_id":"loc_…","average_rating":4.7,"count":23,"distribution":{…}}

# Последние 10 опубликованных
curl "https://zalplan.ru/api/v1/public/locations/loc_…/reviews?limit=10"
# → {"data":[{"id":"rev_…","rating":5,"text":"…","reviewer_name":"Гость","reply":null,"reply_at":null,"created_at":"…"}]}

5. Ручное приглашение (без ожидания 24 ч)

# Создать токен сразу после завершения брони
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"booking_id":"bk_…"}' \
  https://zalplan.ru/api/v1/reviews/-/requests
# → {"id":"rreq_…","token":"…","review_link":"https://zalplan.ru/review?t=…","existing":false}

Публичный каталог (SP-18)

SEO-витрина на https://zalplan.ru/venues/ — Airbnb-style карточки, индексируемые Google. Astro собирает страницы детального просмотра на этапе билда из публичного API; sitemap.xml генерируется динамически.

1. Бэкенд: эндпоинты catalog-public

# Список площадок с фильтрами (city, q, type, capacity_min/max, skip/limit)
curl "https://zalplan.ru/api/v1/public/venues?city=Москва&capacity_min=50&limit=12"

# Полная карточка одной площадки (фото, залы, отзывы, FAQ)
curl "https://zalplan.ru/api/v1/public/venues/loc_…"

# Города с количеством площадок — для фильтра
curl https://zalplan.ru/api/v1/public/venues/cities

# Слаги для sitemap.xml
curl https://zalplan.ru/api/v1/public/sitemap

2. Astro: статика на build-time

3. JSON-LD на странице площадки

4. Admin: FAQ-таб на странице площадки

# Список / создание / правка / удаление вопросов
curl https://zalplan.ru/api/v1/locations/loc_…/faq
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"question":"Можно ли пронести свой алкоголь?","answer":"Да, пробковый сбор 500 ₽."}' \
  https://zalplan.ru/api/v1/locations/loc_…/faq

curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"answer":"…"}' https://zalplan.ru/api/v1/locations/loc_…/faq/faq_…

# Перетягивание мышью в UI → POST /faq/-/reorder с массивом слагов
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"order":["faq_A","faq_C","faq_B"]}' \
  https://zalplan.ru/api/v1/locations/loc_…/faq/-/reorder

Касса и продажи (SP-19)

Walk-in продажи через стойку: кофейни, бары, библиотеки-кафе. Кассир открывает смену с начальным остатком наличных, пробивает позиции из каталога услуг (SP-13), принимает оплату наличными / картой / смешанной, в конце дня закрывает смену с пересчётом денежного ящика и Z-отчётом.

1. Жизненный цикл кассовой смены

2. Продажа за стойкой

# Открыть смену
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"location_id":"loc_…","opening_balance_cents":500000}' \
  https://zalplan.ru/api/v1/cashier-shifts/open

# Пробить чек с двумя позициями
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"shift_id":"shift_…","payment_method":"cash",
       "lines":[
         {"service_item_id":"svc_espresso","quantity":2},
         {"service_item_id":"svc_croissant","quantity":1}
       ]}' \
  https://zalplan.ru/api/v1/counter-sales

# Возврат продажи
curl -X POST -H "Authorization: Bearer $TOKEN" \
  https://zalplan.ru/api/v1/counter-sales/sale_…/refund

# Закрыть смену
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"closing_balance_cents":555000}' \
  https://zalplan.ru/api/v1/cashier-shifts/shift_…/close

3. Способы оплаты

4. UI кассира

Экспорт в бухгалтерию (SP-24)

Выгрузка финансовых операций в российские учётные системы: 1С Бухгалтерия 8.3 через CommerceML 2.0 XML, МойСклад через REST API, Контур.Эльба через CSV, и универсальный Excel (XLSX) для оффлайн-обработки. Все экспорты создаются как асинхронные задания: POST /v1/exports возвращает ExportJob в статусе pending, Celery worker перебирает данные и через GET /v1/exports/{slug} вы получаете готовый file_url. Параметр async=false переводит на синхронное исполнение для коротких диапазонов.

1. Создать экспорт

# XLSX за май 2026, синхронно — файл готов сразу
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "format": "xlsx",
    "scope": "all",
    "date_from": "2026-05-01T00:00:00Z",
    "date_to": "2026-05-31T23:59:59Z"
  }' \
  "https://zalplan.ru/api/v1/exports?async=false"
# → {"id":"expj_...","status":"completed","file_url":"https://zalplan.ru/api/v1/uploads/…/exp_expj_….xlsx",
#    "row_count":42,"summary":{"invoices":18,"payments":20,"clients":4}}

# 1С CommerceML 2.0 XML, в очередь
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"format":"onec_xml","scope":"invoices","date_from":"2026-05-01T00:00:00Z","date_to":"2026-05-31T23:59:59Z"}' \
  https://zalplan.ru/api/v1/exports
# → {"id":"expj_...","status":"pending",...}

# Опрос статуса
curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/exports/expj_...
# → {"status":"completed","file_url":"..."}

2. Форматы и поля

3. Подключение интеграций

# Сохранить учётные данные МойСклад (Fernet-шифрование на сервере)
curl -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"provider":"moysklad","enabled":true,
       "config":{"api_token":"sk_xxxx","organization_id":"<uuid>"}}' \
  https://zalplan.ru/api/v1/integrations/moysklad

# Получить статус интеграций (значения api_token замаскированы как ****1234)
curl -H "Authorization: Bearer $TOKEN" https://zalplan.ru/api/v1/integrations

# Запустить push в МойСклад (за последние 31 день)
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"scope":"all"}' \
  https://zalplan.ru/api/v1/integrations/moysklad/sync
# → {"status":"completed","summary":{"counterparties_created":3,"invoices_pushed":18,"errors":[]}}

4. Безопасность