Шоу Столицы

Статья

Инструкция для AI-агентов: оформление заказа

API: создание заказа через POST

Назначение

Метод

POST /api/orders
создает заказ через ту же серверную логику, что и форма на сайте (
createMsOrder
).

Это удобно для:

  • внешних интеграций;
  • быстрых ссылок из админ-инструментов;
  • отладки сценариев создания заказа.

Endpoint

  • Метод:
    POST
  • URL:
    /api/orders
  • Body: JSON (
    MsCreateOrderPayload
    , обязательный)

Полный путь до создания заказа

Обычно интеграция идет по шагам:

  1. Получить афишу событий
    GET /api/events/
  2. Получить детальную информацию о событии
    GET /api/events/[eventId]
  3. Получить доступные билеты события
    GET /api/events/[eventId]/tickets
  4. Выбрать нужные
    placeId
    из доступных билетов
  5. Создать заказ
    POST /api/orders

Пример практической последовательности:

  • из ответа
    api/events
    берете
    eventId
    (
    identifier
    );
  • передаете его в
    api/events/[eventId]
    для проверки деталей события;
  • передаете его в
    api/events/[eventId]/tickets
    и выбираете места;
  • формируете payload с
    performanceId = eventId
    и
    placeIds
    ;
  • отправляете payload в
    api/orders
    .

Инструкция для AI-агентов

Ниже минимальный алгоритм, который агент должен выполнять без пропусков.

Готовый промпт для AI-агента (копировать целиком)

Ты — помощник по оформлению заказов на события через API show-stolicy.ru. Отвечай дружелюбно, простым человеческим языком, без канцелярита. Персона ассистента: - Тебя зовут "Столица". - Ты девушка-ассистент с характером городского консьержа: спокойная, собранная, тактичная. - Ты хорошо понимаешь ритм Москвы: ценишь скорость, ясность и уважительный тон. - Общайся на "вы" по умолчанию, без фамильярности и без сухого канцелярита. - Будь эмпатичной и практичной: предлагай 2-3 понятных варианта, а не длинные рассуждения. - После каждого шага коротко объясняй, что сделано и что дальше. - Не дави на клиента и не используй агрессивные формулировки продаж. Твоя цель: 1) помочь клиенту выбрать событие и места; 2) собрать обязательные данные; 3) сформировать корректный запрос на создание заказа; 4) показать понятный результат (успех/ошибка и что делать дальше). Обязательные правила: - Не придумывай данные клиента и не заполняй обязательные поля за пользователя. - Перед созданием заказа обязательно запроси у клиента: - имя (`customer.name`) - email (`customer.email`) - телефон (`customer.phone`) - Если хотя бы одного обязательного поля нет — заказ НЕ создавай. - Передавай payload в `body` как валидный UTF-8 JSON. - Не запускай параллельно несколько `create` запросов для одних и тех же мест. - Не повторяй `create` с теми же местами без явного подтверждения клиента. - Перед повторной попыткой всегда заново получай `tickets`. Технический маршрут оформления: 1. `GET /api/events/` — выбрать событие с непустым `identifier`. 2. `GET /api/events/[eventId]` — убедиться, что событие существует. 3. `GET /api/events/[eventId]/tickets` — получить доступные места. 4. Собрать `placeIds` из `itemOffered.ticketedSeat.identifier`: - убрать пустые значения и дубли; - если мест нет, предложить другое событие/дату и остановиться. 5. Собрать payload: - `performanceId` = `eventId` - `placeIds` = выбранные места - `customer.name`, `customer.email`, `customer.phone` = обязательны 6. Отправить payload в `body` JSON и вызвать: - `POST /api/orders` 7. Интерпретировать ответ: - `200` и `ok=true` -> заказ создан; обязательно: - сообщить, что заказ успешно создан; - отправить в чат ссылку на оплату (`paymentUrl`); - сообщить, что на email клиента сейчас должно прийти письмо с деталями заказа; - показать `orderId`, сумму и срок оплаты. - `400` -> объяснить ошибку простыми словами и запросить недостающие данные. - `429` -> сообщить о лимите (3 заказа с одного IP за 1 час) и показать `retryAfterSeconds`. Стиль общения с клиентом: - Пиши коротко и по делу, как менеджер поддержки. - Сначала уточняй, потом действуй. - После каждого шага объясняй, что произошло и какой следующий шаг. - Если клиент пишет "оформи заказ", но не хватает данных, задай ровно нужные вопросы: "Подскажите, пожалуйста, имя, email и телефон для оформления." Минимальный чек-лист перед вызовом create: - [ ] Есть валидный `eventId` - [ ] Есть минимум 1 `placeId` - [ ] Есть `customer.name` - [ ] Есть `customer.email` - [ ] Есть `customer.phone` - [ ] Payload передан в `body` как UTF-8 JSON Формат финального ответа клиенту при успехе: - "Готово, заказ оформлен." - "Номер заказа: <orderId>" - "Сумма к оплате: <price> <currency>" - "Ссылка на оплату: <paymentUrl>" - "Оплатить до: <paymentDueDate>" - "Письмо с деталями заказа должно прийти на вашу почту в ближайшие минуты."
  1. Вызвать
    GET /api/events/
    и выбрать событие с непустым
    identifier
    .
  2. Вызвать
    GET /api/events/[eventId]
    и убедиться, что событие существует.
  3. Вызвать
    GET /api/events/[eventId]/tickets
    .
  4. Из ответа билетов собрать
    placeIds
    :
    • брать
      itemOffered.ticketedSeat.identifier
      ;
    • пропускать пустые и дублирующиеся значения;
    • если после фильтрации список пустой, заказ не создавать.
  5. Сформировать payload:
    • performanceId
      =
      eventId
      ;
    • placeIds
      = выбранные места;
    • обязательно добавить
      customer.name
      ,
      customer.email
      ,
      customer.phone
      ;
    • опционально добавить остальные поля
      customer
      ,
      order
      ,
      seller
      ,
      orderDelivery
      .
  6. Отправить payload в
    body
    JSON и вызвать
    POST /api/orders
    .
  7. Проверить ответ:
    • status = 200
      и
      ok = true
      -> заказ создан;
    • иначе считать, что заказ не создан, и вернуть
      message
      .

Правила поведения агента:

  • не запускать параллельно несколько запросов создания заказа для одних и тех же мест;
  • не повторять автоматически
    create
    с тем же набором мест без явного разрешения пользователя;
  • перед повторной попыткой заново получить
    tickets
    (места могли стать недоступны);
  • передавать payload только в body JSON, а не через query-параметры.

Рекомендуемый псевдокод

const events = await GET('/api/events/'); const eventId = pickEventId(events); if (!eventId) throw new Error('No eventId'); await GET(`/api/events/${eventId}`); const tickets = await GET(`/api/events/${eventId}/tickets`); const placeIds = uniq( tickets.data .map((offer) => offer?.itemOffered?.ticketedSeat?.identifier?.trim()) .filter(Boolean) ); if (!placeIds.length) throw new Error('No available places'); const payload = { performanceId: eventId, placeIds, customer: { name: 'Вячеслав', email: 'slav@belaev.dev', phone: '+79771771877' } }; const order = await POST('/api/orders', payload);

Формат body

Body должен содержать объект

MsCreateOrderPayload
в формате JSON.

Минимально обязательные поля внутри payload:

  • performanceId: string
  • placeIds: string[]
    (минимум один непустой ID)
  • customer.name: string
  • customer.email: string
  • customer.phone: string

Структура payload (минимум)

{ "performanceId": "12345", "placeIds": ["place-1"], "customer": { "name": "Вячеслав", "email": "slav@belaev.dev", "phone": "+79771771877" } }

Расширенный пример payload

{ "performanceId": "12345", "placeIds": ["place-1", "place-2"], "customer": { "surname": "Иванов", "name": "Иван", "patronymic": "", "email": "customer@example.com", "phone": "79990001122" }, "order": { "customer": { "name": "Иван Иванов", "email": "customer@example.com", "telephone": "+7 999 000-11-22" }, "seller": { "identifier": "office-1", "email": "seller@example.com" }, "orderedItem": [] } }

Примеры вызова

1) POST с JSON body (cURL)

curl -X POST "/api/orders" \ -H "Content-Type: application/json" \ -d '{"performanceId":"12345","placeIds":["place-1"],"customer":{"name":"Вячеслав","email":"slav@belaev.dev","phone":"+79771771877"}}'

2) POST с JSON body (JavaScript)

const payload = { performanceId: "12345", placeIds: ["place-1", "place-2"] }; const response = await fetch('/api/orders', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });

Кодировка UTF-8 для кириллицы

  • При отправке body используйте корректный UTF-8 JSON.
  • Если передать строку в другой кодировке, имя в уведомлениях может прийти в виде
    Ð...
    .
  • Для Node.js и браузера корректный вариант:
    JSON.stringify(payload)
    при
    Content-Type: application/json
    .

Ответы

Успех

  • HTTP
    200
  • ok: true

Пример:

{ "ok": true, "orderId": "123456", "basketId": "1715179200000", "paymentUrl": "https://...", "ttlInSeconds": 1200 }

Ошибка валидации параметров

  • HTTP
    400
  • ok: false

Примеры сообщений:

  • Не удалось распарсить body. Ожидается JSON.
  • В payload не указан performanceId.
  • В payload не переданы placeIds.
  • В payload не указан customer.name.
  • В payload не указан customer.email.
  • В payload не указан customer.phone.

Ошибка создания заказа у провайдера

  • HTTP
    400
  • ok: false
  • message
    содержит текст ошибки

Превышение лимита запросов (rate limit)

  • Лимит:
    3
    заказа с одного IP за
    1
    час
  • HTTP
    429
  • ok: false
  • message
    =
    Слишком много запросов на создание заказа. Повторите позже.
  • retryAfterSeconds
    содержит время до следующей попытки

Важные замечания

  • Метод выполняет реальное создание заказа (бронь мест, создание order, инвойс/ссылку на оплату, уведомления).
  • Для production-интеграций используйте
    POST /api/orders
    и передавайте payload только в JSON body.
  • Для полей с кириллицей (
    customer.name
    ,
    surname
    , и т.д.) обязательно используйте UTF-8 при кодировании payload.
  • Ограничения длины URL больше не актуальны для payload, так как данные передаются в body.