Идеология сервиса
Смартомато предоставляет возможность рестораторам любого уровня открыть онлайн-ресторан, заполнить меню и организовать логистику онлайн-заказов. Витрина ресторана может быть построена на основе одной из предоставляемых сервисом тем или работать на внешнем сайте через виджет Смартомато.
Центральным понятием в Смартомато является Организация (Organization) — зарегистрированный в системе ресторан, который обладает витриной и может иметь несколько филиалов, которые в терминах Смартомато называются Ресторанами (Restaurants). Каждый ресторан может иметь одну или несколько зон доставки, позволяющие задать особые условия доставки вокруг филиала. Кроме того, в организацию входят сотрудники (StaffMembers), выполняющие различные роли в бизнес-процессе (всегда есть хотя бы один сотрудник — администратор Организации). Организация также может иметь штат Курьеров (Courier), которые доставляют заказы и могут иметь доступ в мобильное курьерское приложение.
Меню организации наполняется администратором и подлежит публикации для формирования витрины. Публикация подразумевает, что изменение блюд выполняется сначала на уровне черновиков (drafts), которые только после выполнения публикации становятся доступными для продажи. Каждое черновое блюдо (DraftDish) содержится в черновой категории меню (DraftCategory).
Формат данных
Формат данных, который используется при взаимодействии с сервером Смартомато, частично соответствует стандарту JSON API. Этот стандарт основан на принципе REST и накладывает жесткие ограничения на формат данных при запросах для множественных или сингулярных ресурсов.
Рассмотрим пример. Предложим, что имеется ресурс Posts
(доступный по URL /posts
), который представляет коллекцию постов в блоге. Тогда запрос GET /posts
вернет коллекцию всех постов в следующем формате:
{
"posts": [
{ "id": 1, "text": "My first blog post" },
{ "id": 2, "text": "My second blog post" }
]
}
При этом запрос информации о конкретном посте GET /posts/:id
вернет данные в формате (следует обратить внимание
на единственное число слова post
):
{
"post": {
"id": 1,
"text": "My first blog post"
}
}
Аналогичный формат используется для обновления полей конкретного поста посредством запроса PUT /posts/:id
(часть
полей, которые не подлежат обновлению, может отсутствовать).
Запросы на чтение могут снабжаться фильтрами, которые передаются через query parameters, а также мета-информацией. Например, для получения всех постов конкретного автора может использоваться следующий запрос GET /posts?author_id=9
:
{
"posts": [
{ "id": 3, "name": "Stand by Me", "author_id": 9 },
{ "id": 5, "name": "From a Buick 8", "author_id": 9 }
],
"meta": {
"count": 2,
"total": 100
}
}
Кроме того, запросы на чтение могут содержать данные связанных ресурсов для экономии количества запросов (sideloading). К примеру, каждый пост может быть написан от лица пользователя, который представлен ресурсом Authors
. Тогда запрос GET /posts/1
будет возвращать:
{
"post": {
"id": 1,
"text": "My first blog post",
"author_id": 12
},
"authors": [
{ "id": 12, name: "Stephen King"}
]
}
Стоит отметить, что не всегда действия над ресурсами, которые выполняются через API, можно вписать в схему REST. Примером может служить действие like, добавляющее пост в избранное. Такие действия обычно представляются в виде
отдельного запроса вида PUT /:resource/:id/:action
, то есть в данном случае PUT /posts/1/like
.
Передача параметров
Параметры в методы API могут переданы: посредством query-string параметров (например, /api/method?param=value&other_param=other_value
) или
через тело HTTP-запроса. API Смартомато использует первый способ преимущественно для обработки фильтров при получении списков данных
(пример: GET /api/orders?client_id=13
) или передачи дополнительных опций (например, для отключения отправки СМС-уведомлений при смене статуса заказа).
Часть методов принимают данные в формате JSON, в этом случае обязательным является заголовок Content-Type: application/json
, а
данные передаются в виде сериализованной JSON-строки в тело HTTP-запроса.
Пример работы с API
В качестве быстрого старта предлагаем ознакомиться с примером скрипта на языке PHP, который демонстрирует работу с API Смартомато. Он показывает процедуру получения токена через авторизацию и создание нового чернового блюда в меню.
<?php
/*
* Авторизация: POST /api/session с параметрами: login, password
*/
$auth_url = "http://smartomato.ru/api/session";
$auth_data = array(
"login" => "...",
"password" => "..." );
$curl = curl_init($auth_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $auth_data);
echo "=> Sending POST {$auth_url}\n";
$curl_response = curl_exec($curl);
if ($curl_response === false) {
$error = curl_error($curl);
$info = var_export( curl_getinfo($curl), true );
curl_close($curl);
die("An error occured during authorization: " . $error . "\nAdditional info:\n" . $info);
}
echo "<= {$curl_response}\n";
/*
* Ответ содержит информацию о пользователе и токен для доступа
* { ... "meta": { "token": <TOKEN> } }
*/
$json_resp = json_decode( $curl_response, true );
$auth_token = $json_resp['meta']['token'];
$organization_id = $json_resp['staff_members'][0]['organization_id'];
echo "[+] Obtained auth token {$auth_token} {$organization_id}\n";
/*
* Создадим тестовое новое блюдо через API
*/
$api_url = "http://smartomato.ru/api/draft_dishes";
// Сериализуем JSON в строку
$new_dish_data = json_encode( array(
"draft_dish" => array(
"name" => "Грандиозный фалафель с кунжутом",
"price" => 250,
"organization_id" => $organization_id,
"draft_category_id" => 3
)
));
$curl = curl_init($api_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $new_dish_data);
// Выставляем необходимые заголовки
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
// Передаем токен, который получили при авторизации
"Authorization: Token token=\"" . $auth_token . "\"",
// Этот заголовок необходим для передачи JSON
"Content-Type: application/json"
));
echo "=> Sending POST {$api_url}\n {$new_dish_data}\n";
$curl_response = curl_exec($curl);
if ($curl_response === false) {
$error = curl_error($curl);
$info = var_export( curl_getinfo($curl), true );
curl_close($curl);
die("An error occured during api call: " . $error . "\nAdditional info:\n" . $info);
}
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
echo "<= Status: {$httpcode}";
Авторизация
Исполнение методов API (за исключением публичных методов, работающих с корзиной заказа) в Смартомато происходит в рамках сессии. Создание сессии происходит от лица пользователя API (ApiUser
). Конкретный ApiUser
однозначно определяется парой логин-пароль (они же используются при инициации новой сессии) или ключом ApiKey
. Кроме того, каждый ApiUser
имеет привязанный аккаунт, который определяет множество действий в API, доступных данному пользователю.
На текущий момент доступны следующие типы аккаунтов:
Dispatcher
диспетчер Смартомато, занимающийся логистикой заказов тех ресторанов, которые не используют собственных курьеров (ему доступны фактически все заказы системы).StaffMember
менеджер конкретного филиала некого ресторана. Занимается логистикой заказов, относящихся к конкретному ресторану, редактированием зон доставки и доступности меню.Courier
курьер. Может видеть и принимать только те заказы, которые на него назначены.
Для вызова метода API необходимо снабдить запрос HTTP-заголовком вида Authorization: Token token="<TOKEN>"
, где <TOKEN>
— привязанный к сессии API-ключ.
Токен можно также передать посредством query-параметра token: /api/orders?token=<TOKEN>
.
POST /api/session
Выполняет создание новой сессии для доступа к API через параметры login
и password
. Пример POST /api/session?login=user@example.com&password=password
:
{
"staff_members": [
{
"id": 1,
"role": "admin",
"organization_id": 1,
"restaurant_ids": [ 1 ]
}
],
"api_user": {
"id": 1,
"login": "user@example.com",
"name": "Steve Buschemi",
"phone": "2-12-85-06",
"avatar": {
"original": "http://smartomato.ru/api_user/avatar/1/user.png",
"small": "http://smartomato.ru/api_user/avatar/1/small_user.png",
"medium_square": "http://smartomato.ru/api_user/avatar/1/medium_square_user.png",
"medium": "http://smartomato.ru/api_user/avatar/1/medium_user.png"
},
"account": {
"type": "staff_member",
"id": 1
}
},
"meta": {
"token": "3505a86b5b3f0206cd29062529f88b1e"
}
}
Полученный параметр token
используется для формирования авторизационного заголовка.
GET /api/session
Получает состояние текущей сессии.
DELETE /api/session
Выполняет выход из текущей сессии. Использованный ранее token
становится неактуальным.
Ресурс Оrganization
Сущность представляет собой зарегистрированную в Смартомато организацию.
GET /api/organizations/:id
{
"organization": {
"id": 1,
"name": "Setters Brew Bar",
"host": "setters.smartomato.ru",
"social_network": {
"vk": "http://vk.com/settersbrewbar"
},
"about": "Самый лучший кофе на свете!",
"phone": "+7 (905) 341-35-88",
"accept_cashless": true
}
}
Описание полей модели Organization:
name
— название организации.host
— адрес витрины организации, предоставляемой Смартомато.social_network
— хеш, содержащий ссылки на группы организации в социальных сетях. Доступные ключи:vk
,facebook
,twitter
,instagram
.about
— краткое описание (слоган) организации.phone
— телефон организации.accept_cashless
— принимает ли безналичные платежи.
GET /api/organizations
Возвращает список организаций, к которым данный пользователь имеет доступ. В случае аккаунта StaffMember
список
содержит ровно одну организацию. Поддержка многих организаций доступна для участников партнерской программы.
PUT /api/organizations/:id
Обновляет данные организации. Доступные для редактирования поля: name
, social_network
, about
, phone
.
POST /api/organizations/:id/publish
Публикует меню заданной организации.
Ресурс Restaurants
Ресурс представляет рестораны, к которым авторизованный пользователь имеет доступ. В Смартомато ресторан является одни из филиалов конкретной организации и может соответствовать физическим пунктам выдачи заказов.
GET /api/restaurants/:id
Возвращает информацию о ресторане по идентификатору.
{
"restaurants": [
{
"id": 1,
"name": "Setters Brew Bar",
"phone": "2-33-01-20",
"address": "ул. Максима Горького, 151",
"organization_id": 1
}
]
}
GET /api/restaurants
Возвращает список доступных данному пользователю ресторанов. Возможна фильтрация ресторанов через параметр organization_id
.
PUT /api/restaurants/:id
Обновляет атрибуты ресторана. Доступны для редактирования name
, phone
, address
.
Ресурс DraftCategory
Ресурс представляет черновой вариант категории меню организации, в которую входят блюда.
GET /api/draft_categories/:id
Получает информацию о заданной категории.
{
"draft_category": {
"id": 1,
"name": "Альтернативный кофе",
"menu_order": 0,
"photo": {
"original": "http://smartomato.dev/1.png",
"small_square": "http://smartomato.dev/small_square_1.png",
"medium_square": "http://smartomato.dev/medium_square_1.png",
"large": "http://smartomato.dev/large_1.png"
},
"draft_dish_ids": [ 1, 12, 2, 13 ],
"organization_id": 1
}
}
Описание полей:
name
— название категории.menu_order
— числовое поле, представляющее порядок категории на витрине Смартомато.photo
— хеш, содержащий разные версии фоновой фотографии категории.draft_dish_ids
— массив идентификаторов блюд, которые содержатся в данной категории.organization_id
— идентификатор организации.
GET /api/draft_categories
Получает список категорий меню, к которым авторизованный пользователь имеет доступ. Доступна фильтрация по параметру organization_id
.
PUT /api/draft_categories/:id
Обновляет поля заданной категории.
DELETE /api/draft_categories/:id
Удаляет категорию и все содержащиеся в ней блюда. Удаление категории с витрины произойдет после публикации меню.
PUT /api/draft_categories/:id/photo
Обновляет фотографию категории. Ожидает тип mutlipart/form-data с атрибутом file.
Ресурс DraftDish
Ресурс представляет собой черновой (еще не опубликованный) вариант блюда, которое входит в меню.
GET /api/draft_dishes/:id
Возвращает черновое блюдо по идентификатору.
{
"draft_dish": {
"id": 1,
"is_hidden": false,
"name": "Кофе из кемекса",
"description": "Вкуснейший кофе из кемекса",
"menu_order": 0,
"price": "100.0",
"photo": {
"original": "http://smartomato.ru/test.jpg",
"small_square": "http://smartomato.ru/small_square_test.jpg",
"medium_square": "http://smartomato.ru/medium_square_test.jpg",
"medium": "http://smartomato.ru/medium_test.jpg",
"large": "http://smartomato.ru/large_test.jpg"
},
"weight": "50",
"ingredients": "Кофе",
"can_zoom": false,
"is_next_day": false,
"external_id": "",
"options": null,
"draft_category_id": 1,
"organization_id": 1
}
Описание полей:
is_hidden
— скрыто ли блюдо на витрине.name
— название блюда.description
— описание блюда.menu_order
— целое, показывающее порядок блюда внутри категории.price
— цена блюда.photo
— хеш, содержащий разные версии фотографии блюда.weight
— вес блюда в граммах.ingredients
— строковое описание состава блюда.is_next_day
— показывает, что доставка блюда возможна только на следующий день.external_id
— строковый внешний идентификатор. Используется при интеграции виджета Смартомато на внешнем сайте.options
— хеш, представляющий конфигуратор блюда (возможность использования добавок во время покупки). См. раздел «Формат конфигуратора».draft_category_id
— идентификатор категории, к которой принадлежит блюдо.organization_id
— идентификатор организации, к которой принадлежит блюдо.
GET /api/draft_dishes
Возвращает список всех черновиков блюд, к которым авторизованный пользователь имеет доступ. Доступны фильтры по следующим атрибутам: organization_id
, draft_category_id
.
DELETE /api/draft_dishes/:id
Удаляет блюдо. Удаление блюда с витрины произойдет после публикации.
PUT /api/draft_dishes/:id
Изменяет атрибуты конкретного блюда.
POST /api/draft_dishes/
Создает новое блюдо. Поля draft_category_id
, organization_id
, price
, name
являются обязательными.
PUT /api/draft_dishes/:id/photo
Обновляет фотографию блюда. Ожидает тип mutlipart/form-data с атрибутом file.
Формат конфигуратора
Параметр options
позволяет задать конфигуратор блюда, с помощью которого возможен выбор разных вариантов
добавок. Выбранные во время покупки добавки формируют окончательную цену блюда в соответствии с форматом
конфигуратора. Приведем пример формата конфигуратора блюда:
"options": [
{
"items": [
{
"name": "Эфиопия Фуджи",
"price": "20"
},
{
"name": "Арабика",
"price": "30"
},
{
"name": "Nescafe Gold",
"price": 0
}
],
"max": 1,
"min": 1,
"multiple": false,
"name": "Сорт кофе"
},
{
"items": [
{
"name": "Взбитые сливки",
"price": "10"
},
{
"name": "Ореховая стружка",
"price": "15"
},
{
"name": "Корица",
"price": "10"
}
],
"max": "3",
"min": "0",
"multiple": true,
"name": "Сладкие добавки"
}
]
Конфигуратор состоит из массива хешей, каждый из которых описывает отдельный вид добавки. Название вида добавки
содержится в параметре name
. Возможные варианты для выбора представлены параметром items
, каждый вариант обладает названием name
и добавочной ценой price
.
Кроме того, существует возможность задать максимальное и минимальное количество выбираемых вариантов. Параметр multiple
определяет, можно ли выбирать несколько вариантов или необходимо выбрать одно и только одну опцию. В случае, если multiple
имеет значение true
, параметры min
и max
определяют минимальное и максимальное количество опций соответственно.
Ресурс DeliveryZones
Ресурс DeliveryZones
предоставляет методы для работы с зонами доставки — сущностями, которые
определяют условия доставки (время доставки, цену, режим работы) в зависимости от адреса.
Каждая зона принадлежит ресторану, в который в последствии поступает заказ.
Принадлежность адреса доставки определенной зоне определяется полигоном.
GET /api/delivery_zones/:id
Получение информации о заданной зоне доставке.
{
"id": 2,
"name": "Центр Ростова",
"delivery_time": 30,
"price": 50,
"timezone": "Europe/Moscow",
"free_delivery_count": null,
"free_delivery_price": null,
"minimal_order_price": null,
"area": "POLYGON ((39.692910354492184 47.22123047559831, 39.71290890490714 47.236197896650225, 39.67093769824215 47.228130049589005))",
"restaurant_id": 1,
"organization_id": 1,
"timetables": [
{
"id": 8,
"open_at": "2000-01-01T00:00:00Z",
"close_at": "2000-01-01T14:00:00Z",
"day": 0,
"date": null,
"is_working": true
},
...
]
}
Описание полей:
name
— название зоны доставки.delivery_time
— время доставки в минутах.price
— цена доставки.timezone
- часовой пояс зоны.free_delivery_count
— минимальное количество блюд, после которого доставка бесплатная.free_delivery_price
— цена, после которой доставка бесплатная.minimal_order_price
— минимальная цена заказа в этой зоне.area
— геометрия зоны, заданная в формате WKT. Должна быть представлена односвязной областью без самопересечений.restaurant_id
— ресторан, к которому принадлежит зона. Заказы в этой зоне будут попадать в этот ресторан.organization_id
— организация, к которой принадлежит зона.timetables
— расписание работы, массив объектов, которые представляют временные промежутки, в которые эта зона работает. Формат:open_at
— начало промежутка (учитывается только время)close_at
— конец промежутка (учитывается только время)day
— номер дня неделиdate
— специальная дата, задает время работы только в определенный день. Может отсутствовать.is_working
— в значенииfalse
данный промежуток не будет учитываться при построении расписания.
GET /api/delivery_zones
Запрос возвращает все зоны доставки организаций, к которым авторизованный пользователь имеет доступ. Доступна фильтрация через параметр organization_id
.
POST /api/delivery_zones
Создание новой зоны достаки. Обязательными являются параметры: organization_id
, restaurant_id
, name
.
PUT /api/delivery_zones/:id
Обновление полей заданной организации.
Ресурс Orders
Заказы в доступных данному пользователю организациях и ресторанах.
GET /orders/:id
Получает информацию о заданном заказе по идентификатору. Формат ответа:
{
"restaurants": [
{
"id": 1,
"name": "Setters Brew Bar",
"phone": "2-33-01-20",
"is_running": true,
"address": "ул. Максима Горького, 151",
"is_delivery": false,
"organization_id": 1
}
],
"couriers": [
{
"id": 3,
"name": "Джек Николсон",
"phone": "+7 (904) 231-23-23",
"avatar": {
"original": "http://smartomato.ru/av.jpg",
"small": "http://smartomato.ru/small_av.jpg",
"medium_square": "http://smartomato.ru/medium_square_av.jpg",
"medium": "http://smartomato.ru/medium_av.jpg"
},
"organization_id": 1,
"last_known_position": null,
"comment": "Классно сыграл в том самом фильме.",
"partnership_id": null
}
],
"payments": [],
"order": {
"id": 65,
"number": "1-14",
// Предполагаемое полное время доставки в минутах
// (с момента приготовления блюда до момента получения клиентом)
"delivery_time": 60,
// Предполагаемое время доставки из ресторана клиенту
"transportation_time": 25,
// Предполагаемое время приготовления
"cooking_time": 15,
// Контактный телефон и имя клиента
"contact_phone": "+7 (904) 571-25-42",
"contact_name": "John Doe",
// Комментарий клиента
"description": "Привезите скорее, пожалуйста!",
// Нужна сдача с суммы
"change": 5000,
// Статус доставки заказа
"status": "complete",
// Время создания заказа
"created_at": "2015-02-21T21:08:39+03:00",
// Время подтверждения курьером
"courier_confirmed_at": "2015-07-13T16:50:57+03:00",
// Время подтверждения рестораном
"restaurant_confirmed_at": null,
// Доставить как можно скорее
"delivery_asap": true,
// Время, к которому необходимо доставить заказ
"delivery_at": "2015-02-21T21:38:39+03:00",
// Координаты места назначения в формате WKT и
// в виде широты/долготы
"coordinates": "POINT (39.714285 47.226894)",
"latitude": 47.226894,
"longitude": 39.714285,
// Город
"city": "Россия, Ростов-на-Дону",
// Адреc: включает улицу и дом
"address": "улица Максима Горького, 151",
"apartment": "18", // Квартира/офис
"staircase": "1й", // Подъезд
"floor": "5", // Этаж
"doorphone": "18B", // Код домофона
// Полный адрес, сформированный на основе вышеперечисленных полей
// Удобен для использования в интерфейсах
"address_text": "улица Максима Горького, 151, 1й подъезд, 5 этаж, кв. 18, код домофона 18B",
// Предпочтительное время забора заказа из ресторана
"pick_up_at": "2015-06-23T22:35:00+03:00",
// Источник оплаты заказа:
// cash наличные
// card картой
// courier_card картой курьеру
"payment_source": "cash",
// Полная стоимость заказа с учетом доставки и всех надбавок
"final_sum": 365,
// Цена доставки
"delivery_price": "50.0",
// Полная стоимость всех блюд
"total": "315.0",
"restaurant_id": 1,
// id клиента в организации
"client_id": 1,
// id назначенного на заказ курьера
"courier_id": 3,
// id модели Payment
// (присутствует при безналичном типе оплаты)
"payment_id": null,
// URL для получения состава заказа и участников заказа
"links": {
"buddies": "/api/orders/65/buddies",
"items": "/api/orders/65/items"
},
}
}
GET /orders
Получает список заказов, к которым пользователь имеет доступ. Доступны следующие параметры:
page
— показать заданную страницу списка.per_page
— количество заказов на странице.restaurant_id
— показать только заказы из заданных ресторанов (может быть массивом).courier_id
— показать только заказы, назначенные на заданных курьеров (может быть массивом).client_id
- показать только заказы определенного клиента ресторана (может быть массивом).status
— показывать только заказы с определенным статусом.sort_by
— определяет поле, по которому происходит сортировка.
Данные о количестве страниц отдаются в виде мета-информации:
{
"orders": [ ... ],
"meta": {
"page": 1,
"page_count": 3,
"per_page": 25,
"count": 68
}
}
GET /orders/:id/receipt{.pdf|.html}
Возвращает печатную выписку заказа в заданном формате (HTML или PDF).
PUT /orders/:id
Запрос необходим для редактирования следующих полей заказа: courier_id
, status
, contact_name
, contact_phone
, description
, delivery_at
, delivery_price
.
PUT /orders/:id/confirm
Запрос необходим для подтверждения заказа курьером или рестораном. Тип подтверждения определяется на основе текущей учетной
записи. В результате операции будут обновлены поля restaurant_confirmed_at
или courier_confirmed_at
, которые показывают
время подтверждения рестораном или курьером соответственно.
PUT /orders/:id/status?status=VALUE
Метод доступен курьеру и необходим для выставления текущего статуса заказа. Доступные значения параметра status
для курьера:
delivery
заказ получен и доставляетсяcomplete
заказ доставлен
Методы импорта
API Смартомато позволяет выполнять пакетный импорт данных, таких как меню, заказы, из внешних систем. Ключевым параметром
при импорте является внешний идентификатор (external_id
), то есть идентификатор сущности в рамках внешней системы, это может
быть, например, идентификатор блюда в CMS, на которой построен сайт, подключенный к Смартомато посредством виджета.
Импорт меню
Для ресторанов с уже готовым сайтом существует возможность быстрого импорта меню. Для этого может
быть использован метод API POST /api/organizations/:id/import/menu
. Импорт подразумевает полную замену меню ресторана и поддерживает
разные форматы описания связи блюд с категориями.
Замечание #1: импорт меню работает с полной заменой текущего меню организации. Это означает, что для дополнения меню новыми блюдами необходимо
передавать уже существующие блюда (через external_id
) наряду с новыми.
Замечание #2: импорт меню выполняется асинхронно. Это значит, что ответ от сервера может быть получен до момента, когда импорт завершится. Одновременно может происходить лишь один импорт меню в организации, поэтому новый импорт не будет выполнен, если в данный момент еще не завершена предыдущая операция. Ответ от сервера в этом случае содержит информацию о текущей задаче и ходе ее выполнения:
{
"status": "busy",
"job_id": "5c1e1e79a0582b969cd9d4d0",
"job_status": "working",
"job_message": "Importing dish Muscovado Crunch",
"job_percent": 8.51063829787234
}
Ответ в случае успешного начала импорта:
{
"status": "queued",
"job_id": "5c1e1e79a0582b969cd9d4d0"
}
Запросить статус текущего импорта в любой момент времени можно с помощью метода GET /api/organizations/:id/import/menu
.
Рекомендуется использовать именно этот метод для мониторинга состояния импорта после его начала.
Входные данные для метода импорта (используйте заголовок Content-Type: application/json
):
{
// Список категорий может отсутствовать. В таком случае категории для блюд
// создаются автоматически. Для привязки блюд одним и тем же категориям
// можно также использовать `category_name` блюда.
"categories": [
{
// Название категории
"name": "Пончики",
// Порядок в меню (может отсутствовать)
"menu_order": 0,
// Ссылка на фотографию категории
"remote_photo_url": "http://goo.gl/IqZ4hE",
// Строковый внешний идентификатор для связки блюда и категории
"external_id": "ponchiki"
}
],
"dishes": [
{
"name": "Ультра-Шоколад",
"price": 140.50,
"weight": 200.00,
"menu_order": 0,
"description": "Необычайно вкусный пончик с двойной шоколадной начинкой",
// Список конфигураторов, может быть null
"modifiers": [
{
"name": "Экстра-Добавки",
"items": [
{ "name": "Марцепан", "price": 15 },
{ "name": "Орехи", "price": 25 }
],
"min": 1,
"max": 2,
"multiple": false
}
],
// Карта доступности блюда в ресторанах, опционально
// Доступные значения поля "status"
// "available" - по-умолчанию, блюдо доступно в ресторане
// "not_available" - блюдо недоступно в ресторане
// "call" - заказ можно совершить, но наличие блюда стоит уточнить
//
// Если массив availability указан, блюдо получает статус "available"
// во всех неперечисленных ресторанах
"availability": [
{ "restaurant_id": 1, "status": "call" },
{ "restaurant_id": 12, "status": "not_available"}
],
// Ссылка на фотографию блюда
"remote_photo_url": "http://goo.gl/IqZ4hE",
// Привязка к категории может осуществляться двумя способами:
// 1. Через внешний идентификатор категории (категория должна быть
// представлена в массиве categories)
"category_external_id": "ponchiki",
// 2. Через имя категории (в случае отсутствия категории в categories,
// она создается автоматически)
"category_name": "Пончики",
// Опциональный внешний идентификатор
"external_id": "ultra-choko"
}
],
// Опциональный конфигуратор импорта
"config": {
// Позволяет полностью заменить текущее меню импортируемым. По-умолчанию: false
"destroy_menu": true,
// Публикация меню сразу после завершения импорта. По-умолчанию: false
"publish_menu": true
}
}
Внешние идентификаторы external_id
блюд и категорий могут быть использованы для:
- Интеграции виджета с сайтом ресторана (см. Размещение виджета на стороннем сайте).
- Связи импортируемых категорий и блюд (через указание
category_external_id
). - Поддержки итеративного импорта: обновленное меню можно импортировать без потери статистики в
Смартомато. Наличие при импорте ранее импортированного блюда
external_id
гарантирует, что блюдо будет сохранять идентификатор в системе Смартомато.
Импорт клентов
Импорт клиентов производится аналогично импорту номенклатуры меню. Процесс также является асинхронным, поэтому для импорта доступны
два метода GET /api/organizations/:id/import/clients
и POST /api/organizations/:id/import/clients
c идентичным форматом для
описания текущей задачи в очереди.
Формат данных для импорта клиентов:
{
"clients": [
{
// Внешний идентификатор
"external_id": "fa860",
"email": "bulkin@smartomato.ru",
// male или female
"gender": "male",
// Дата рождения в формате дд/мм/гггг
"birthdate": "15/01/1978",
// Дата регистрации
"registered_at": "2009-02-09T21:00:00.000Z",
"name": "Виталий Булкин",
// Комментарий к клиенту (не виден клиенту)
"comment": "будьте осторожны с этим парнем, не платит за заказ!",
"addresses": [
"ул. Пресненский вал д.8 под.2 эт.2 кв.41"
],
"phone_numbers": [
"+7 (926) 152-65-21"
],
// Список тегов
"tags": [
"не платит",
"новый гость"
],
// В черном списке?
"is_blacklisted": true
}
]
}
Иницирирование импорта может сопровождаться переданным query-параметром from_scratch=true, в таком случае ранее созданные клиенты будут удалены перед импортом.
Пакетный импорт и создание заказов
Загрузка существующей истории заказов, а также создание новых заказов возможно при помощи метода POST /api/organizations/:id/import/orders
.
Query-параметр existing
позволяет задать стратегию для обновления уже импортированных заказов (посредством external_id
). Доступны следующие режимы:
- update обновить заказ, если он уже был импортирован
- ignore пропустить заказ в случае повторного импорта. Данный режим используется по-умолчанию, если параметр
existing
не задан.
Важно: метод не предоставляет возможность валидации параметров заказов, таких как время доставки и режим работы, содержимое заказа (возможен импорт элементов, которым не соответствуют блюда в Смартомато) и стоп-листы. Единственным валидируемым параметром на данный момент является адрес и зона доставки, см. формат данных для более подробного описания.
На вход метода поступает массив заказов в следующем формате:
{
"orders": [
{
"external_id": "d35592e1-c85d-4ec3-b069-cfcfdf3cf1ba",
"city": "Москва",
"address": "Чертаново Северное микрорайон 6",
"comment": "сдача с 1000",
"change": 1000,
// Время размещения заказа
"published_at": "...",
"delivery_at": "...",
"total": 1000,
// Сумма, оплаченная бонусами
"used_bonuses": 100,
// (!) Импорт заказов в статусе "новый" приведет
// к отсылке СМС и e-mail уведомлений о новом заказе
"status": "pending",
// Адрес обязательно необходимо указать в координатах,
// иначе заказ не сможет быть привязан к нужному ресторане
// и зоне
"latitude": 55.634126,
"longitude": 37.590515,
// В противном случае, ресторан и зону можно
// указать вручную
"restaurant_id": 12,
"delivery_zone_id": 102,
// Варианты для передачи клиента:
// через client_external_id
// => будет присвоен клиент, который найдется по
// external_id, если не найден, он создается
// в качестве имени используется contact_name
// через client_id
// => будет присвоен конкретный клиент Смартомато,
// если он найден, если не найден, ошибка
"client_external_id": "d35592e1-c85d-4ec3-b069-cfcfdf3cf1ba",
"contact_phone": "...",
"contact_name": "...",
"payment_source": "cash",
// Источник заказа
"source": "board",
"delivery_asap": true,
"takeaway": false,
"buddies": [
{
"id": "16521630-6ea1-4756-a4b7-21e118754a3b",
"name": "Максим",
"items": [
{
// Блюдо может быть передано через:
// dish_external_id и dish_id
// (см. импорт меню)
"amount": 2,
"config": null,
"name": "Котлета мясная в томатном соусе ",
"price": 210,
// Цена одного элемента
"item_price": 105,
"comment": "Больше соуса"
}
]
}
]
}
]
}
В ответе содержится массив статусов импорта для каждого из переданных заказов:
{
"organization_import": [
{
"external_id": "2345de2a-bcfc-483e-bfc4-27fb3d9cb11a",
"status": "imported",
"imported_at": "2015-10-28T17:35:14.472Z"
},
{
"external_id": "6f2a60e9-08f0-4bcc-aa1c-049dbb2f14c0",
"status": "ignored"
},
{
"external_id": "a311efcb-2826-4f93-9e18-ea1a9734c607",
"status": "error",
"errors": [ ... ]
}
]
}