Введение
Обзор API
REST API MyReviews позволяет программно управлять организациями, площадками отзывов, самими отзывами, тегами и ответами. API подходит для интеграции с CRM, дашбордами аналитики, чат-ботами и любыми другими системами.
Base URL
Все запросы выполняются к единому адресу:
https://myreviews.dev/v1
Протокол и формат
- Только HTTPS
- Тело запросов –
application/json - Все ответы – JSON
- Кодировка – UTF-8
Аутентификация
API использует JWT-токены (JSON Web Tokens). Большинство методов требуют авторизации – исключения отмечены как «публичные».
- Отправьте
POST /v1/user/loginс email и паролем. - В ответе получите поле
data.jwt– это ваш токен. - Передавайте токен в заголовке каждого защищённого запроса:
Authorization: Bearer <jwt>
⚠️ Безопасность
Храните JWT в защищённом месте. Не передавайте токен через URL-параметры и не встраивайте в клиентский JavaScript, доступный пользователям. Если токен скомпрометирован – смените пароль, чтобы выпустить новый.
Формат тела запросов
API построен на Yii2. Большинство POST-эндпоинтов принимают «формы» (LoginForm, RegistrationForm, Firm, Review, ReviewAnswer и т.д.). Тело таких запросов обязательно оборачивается в ключ-имя формы — иначе сервер вернёт 400 «Ошибка загрузки формы.».
JSON
{
"FormName": {
"field1": "value1",
"field2": "value2"
}
}
form-urlencoded / multipart
FormName[field1]=value1
FormName[field2]=value2
Важные моменты:
- Query-параметры (
?id=...&service=...) всегда остаются плоскими — их wrapping не затрагивает. - Эндпоинты с плоскими параметрами (например,
firm/add-service,review/delete-tag,plan/*,idea/create) — явно отмечены в описании. Там wrapping не нужен. - Для загрузки файлов (
firm/create,user/update,review/create) используйтеmultipart/form-data. - Поддерживается
application/jsonиapplication/x-www-form-urlencoded.
❌ Неправильно
curl -X POST "https://myreviews.dev/v1/user/login" \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"..."}'
# => 400 { "message": "Ошибка загрузки формы." }
✅ Правильно
curl -X POST "https://myreviews.dev/v1/user/login" \
-H "Content-Type: application/json" \
-d '{"LoginForm":{"email":"user@example.com","password":"..."}}'
# => 200 { "data": { "jwt": "..." } }
Формат ответов
Успешный ответ содержит три поля:
{
"status": 200,
"message": "Описание результата.",
"data": { }
}
| Поле | Тип | Описание |
|---|---|---|
status | integer | HTTP-код ответа (дублируется для удобства парсинга) |
message | string | Человекочитаемое описание результата на русском языке |
data | object | array | string | null | Полезная нагрузка: объект, массив, строка или null при ошибке |
Коды ошибок
При ошибке API возвращает HTTP-код 4xx/5xx и тело в стандартном формате Yii:
{
"name": "Bad Request",
"message": "Вы ввели неверный адрес электронной почты или пароль.",
"code": 0,
"status": 400
}
| Поле | Тип | Описание |
|---|---|---|
name | string | Техническое название ошибки (Bad Request, Unauthorized, Forbidden, Not Found…) |
message | string | Человекочитаемый текст на русском — показывайте пользователю |
code | integer | Внутренний код (чаще всего 0) |
status | integer | HTTP-статус |
Соответствие HTTP-кодов:
| Код | Значение | Когда возникает |
|---|---|---|
200 | Успех | Запрос выполнен |
400 | Bad Request | Ошибка валидации, отсутствует wrapping формы, неверные параметры |
401 | Unauthorized | Отсутствует или невалидный JWT-токен |
403 | Forbidden | Нет прав на запрашиваемый ресурс (например, чужая организация) |
404 | Not Found | Ресурс с указанным ID не существует |
422 | Unprocessable Entity | Данные формы не прошли валидацию (например, email занят) |
429 | Too Many Requests | Превышен лимит запросов (актуально для user/login) |
500 | Internal Server Error | Внутренняя ошибка сервера — повторите позже |
Пагинация
Методы, возвращающие списки (компании, отзывы), поддерживают пагинацию. Управляйте ей через query-параметры:
| Параметр | Тип | Описание |
|---|---|---|
page | integer | Номер страницы (начиная с 1) |
per-page | integer | Количество элементов на страницу (1–250, по умолчанию 100) |
Метаданные пагинации возвращаются в HTTP-заголовках ответа:
| Заголовок | Описание |
|---|---|
X-Pagination-Total-Count | Общее число записей |
X-Pagination-Page-Count | Общее число страниц |
X-Pagination-Current-Page | Текущая страница |
X-Pagination-Per-Page | Записей на странице |
Лимиты запросов
Для защиты инфраструктуры API применяет ограничение частоты запросов (rate limiting). При превышении лимита сервер вернёт код 429.
Рекомендации
- Кэшируйте ответы, которые меняются редко (справочник площадок, профиль)
- Используйте
per-pageдля получения данных пакетами, а не по одной записи - При получении
429сделайте паузу и повторите запрос через несколько секунд - Для массовых операций лучше использовать вебхуки и уведомления через Telegram
Авторизация
Получите JWT-токен для доступа к защищённым методам API. Токен передаётся в заголовке Authorization: Bearer <jwt>.
/v1/user/login
Авторизация пользователя. Возвращает JWT-токен для последующих запросов.
Параметры запроса
Тело обязательно оборачивайте в ключ LoginForm — см. раздел Формат тела запросов.
| Параметр | Тип | Описание |
|---|---|---|
LoginForm[email]обязательный | string | Email пользователя |
LoginForm[password]обязательный | string | Пароль |
⚠️ Rate limit
Эндпоинт ограничен по IP. После серии неуспешных попыток сервер вернёт 429 Too Many Requests. Делайте паузу перед повторными запросами.
Пример ответа
200 OK{
"status": 200,
"message": "Пользователь авторизован.",
"data": {
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
}
400 Bad Request
{
"name": "Bad Request",
"message": "Вы ввели неверный адрес электронной почты или пароль.",
"code": 0,
"status": 400
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/user/login" \
-H "Content-Type: application/json" \
-d '{
"LoginForm": {
"email": "user@example.com",
"password": "mypassword"
}
}'
# Альтернатива — form-urlencoded:
curl -X POST "https://myreviews.dev/v1/user/login" \
--data-urlencode 'LoginForm[email]=user@example.com' \
--data-urlencode 'LoginForm[password]=mypassword'
import requests
r = requests.post("https://myreviews.dev/v1/user/login",
json={"LoginForm": {"email": "user@example.com", "password": "mypassword"}})
jwt = r.json().get("data", {}).get("jwt")
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'LoginForm' => [
'email' => 'user@example.com',
'password' => 'mypassword',
],
]),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/user/login', false, $ctx),
true
);
$jwt = $data['data']['jwt'] ?? null;
const res = await fetch("https://myreviews.dev/v1/user/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
LoginForm: {
email: "user@example.com",
password: "mypassword"
}
})
});
const { data } = await res.json();
const jwt = data.jwt;
/v1/user/join-by-email
Регистрация нового пользователя по email. После успешной регистрации возвращается JWT-токен.
Параметры запроса
Тело оборачивается в ключ RegistrationForm.
| Параметр | Тип | Описание |
|---|---|---|
RegistrationForm[email]обязательный | string | Email нового пользователя |
RegistrationForm[password]обязательный | string | Пароль (не менее 6 символов) |
RegistrationForm[timezone]опционально | string | Таймзона IANA, например Europe/Moscow |
RegistrationForm[language]опционально | string | Язык интерфейса, например ru |
RegistrationForm[screen]опционально | string | Разрешение экрана для аналитики |
Пример ответа
200 OK{
"status": 200,
"message": "Пользователь зарегистрирован.",
"data": {
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/user/join-by-email" \
-H "Content-Type: application/json" \
-d '{
"RegistrationForm": {
"email": "new@example.com",
"password": "mypassword",
"timezone": "Europe/Moscow",
"language": "ru"
}
}'
r = requests.post("https://myreviews.dev/v1/user/join-by-email",
json={"RegistrationForm": {
"email": "new@example.com",
"password": "mypassword",
"timezone": "Europe/Moscow",
"language": "ru",
}})
jwt = r.json().get("data", {}).get("jwt")
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'RegistrationForm' => [
'email' => 'new@example.com',
'password' => 'mypassword',
'timezone' => 'Europe/Moscow',
'language' => 'ru',
],
]),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/user/join-by-email', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/user/join-by-email", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
RegistrationForm: {
email: "new@example.com",
password: "mypassword",
timezone: "Europe/Moscow",
language: "ru"
}
})
});
const { data } = await res.json();
const jwt = data.jwt;
/v1/user/forgot-password
Восстановление пароля. Без параметра token отправляет письмо со ссылкой; с token и новым паролем — завершает восстановление.
Параметры запроса
Тело оборачивается в ключ ForgotPasswordForm.
| Параметр | Тип | Описание |
|---|---|---|
ForgotPasswordForm[email] | string | Email — для шага «отправить письмо» |
ForgotPasswordForm[token] | string | Токен из письма — для шага «установить новый пароль» |
ForgotPasswordForm[password] | string | Новый пароль — для шага «установить новый пароль» |
Пример запроса
# Шаг 1: отправить письмо с токеном
curl -X POST "https://myreviews.dev/v1/user/forgot-password" \
-H "Content-Type: application/json" \
-d '{"ForgotPasswordForm":{"email":"user@example.com"}}'
# Шаг 2: подтвердить и установить новый пароль
curl -X POST "https://myreviews.dev/v1/user/forgot-password" \
-H "Content-Type: application/json" \
-d '{"ForgotPasswordForm":{"token":"abc123","password":"newpass"}}'
requests.post("https://myreviews.dev/v1/user/forgot-password",
json={"ForgotPasswordForm": {"email": "user@example.com"}})
requests.post("https://myreviews.dev/v1/user/forgot-password",
json={"ForgotPasswordForm": {"token": "abc123", "password": "newpass"}})
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'ForgotPasswordForm' => ['email' => 'user@example.com'],
]),
]]);
file_get_contents('https://myreviews.dev/v1/user/forgot-password', false, $ctx);
await fetch("https://myreviews.dev/v1/user/forgot-password", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
ForgotPasswordForm: { email: "user@example.com" }
})
});
Профиль
Authorization: Bearer <jwt>/v1/user/profile
Получение данных текущего пользователя.
🔒 АвторизацияПример ответа
200 OK{
"status": 200,
"message": "Данные пользователя.",
"data": {
"id": 1,
"email": "user@example.com",
"name": "Иван",
"surname": "Иванов",
"phone": "+79001234567",
"about": "",
"image": null,
"date_reg": "15.02.2024",
"telegram_chat_id": null
}
}
Пример запроса
curl "https://myreviews.dev/v1/user/profile" \
-H "Authorization: Bearer JWT"
r = requests.get("https://myreviews.dev/v1/user/profile",
headers={"Authorization": f"Bearer {jwt}"})
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => "Authorization: Bearer $jwt",
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/user/profile', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/user/profile", {
headers: { Authorization: "Bearer " + jwt }
});
const data = await res.json();
/v1/user/update
Обновление данных профиля пользователя. При загрузке фото используйте multipart/form-data, иначе — JSON или application/x-www-form-urlencoded.
Параметры запроса
Все поля оборачиваются в ProfileForm.
| Параметр | Тип | Описание |
|---|---|---|
ProfileForm[name] | string | Имя |
ProfileForm[surname] | string | Фамилия |
ProfileForm[phone] | string | Телефон |
ProfileForm[about] | string | О себе |
ProfileForm[photo_upload] | file | Фото, передаётся через multipart/form-data |
Пример ответа
200 OK{
"status": 200,
"message": "Данные пользователя отредактированы."
}
Пример запроса
# JSON — без файла
curl -X POST "https://myreviews.dev/v1/user/update" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"ProfileForm":{"name":"Иван","surname":"Иванов"}}'
# multipart/form-data — с фото
curl -X POST "https://myreviews.dev/v1/user/update" \
-H "Authorization: Bearer JWT" \
-F 'ProfileForm[name]=Иван' \
-F 'ProfileForm[surname]=Иванов' \
-F 'ProfileForm[photo_upload]=@/path/to/avatar.jpg'
# JSON — без файла
r = requests.post("https://myreviews.dev/v1/user/update",
headers={"Authorization": f"Bearer {jwt}"},
json={"ProfileForm": {"name": "Иван", "surname": "Иванов"}})
# multipart — с фото
with open("avatar.jpg", "rb") as f:
r = requests.post("https://myreviews.dev/v1/user/update",
headers={"Authorization": f"Bearer {jwt}"},
data={"ProfileForm[name]": "Иван", "ProfileForm[surname]": "Иванов"},
files={"ProfileForm[photo_upload]": f})
$payload = ['ProfileForm' => ['name' => 'Иван', 'surname' => 'Иванов']];
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode($payload),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/user/update', false, $ctx),
true
);
// multipart: используйте curl_setopt с CURLFile
// $ch = curl_init('https://myreviews.dev/v1/user/update');
// curl_setopt($ch, CURLOPT_POSTFIELDS, [
// 'ProfileForm[name]' => 'Иван',
// 'ProfileForm[photo_upload]' => new CURLFile('/path/to/avatar.jpg'),
// ]);
// JSON — без файла
await fetch("https://myreviews.dev/v1/user/update", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({
ProfileForm: { name: "Иван", surname: "Иванов" }
})
});
// multipart — с фото
const fd = new FormData();
fd.append("ProfileForm[name]", "Иван");
fd.append("ProfileForm[surname]", "Иванов");
fd.append("ProfileForm[photo_upload]", fileInput.files[0]);
await fetch("https://myreviews.dev/v1/user/update", {
method: "POST",
headers: { Authorization: "Bearer " + jwt },
body: fd
});
Организации
view, требуют авторизации/v1/firm/list
Список организаций текущего пользователя.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
per-page | int | Количество на странице (по умолчанию 100, макс. 250) |
Пример ответа
200 OK{
"status": 200,
"message": "Организации пользователя.",
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "ООО Рога и копыта",
"address": "Москва, ул. Примерная, 1",
"image": null,
"active": true,
"date_create": "01.01.2024"
}
]
}
Пример запроса
curl "https://myreviews.dev/v1/firm/list?per-page=20" \
-H "Authorization: Bearer JWT"
r = requests.get("https://myreviews.dev/v1/firm/list",
params={"per-page": 20},
headers={"Authorization": f"Bearer {jwt}"})
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => "Authorization: Bearer $jwt",
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/list?per-page=20', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/list?per-page=20", {
headers: { Authorization: "Bearer " + jwt }
});
/v1/firm/view
Данные одной организации. Параметр id – UUID организации.
Параметры запроса
| Параметр | Тип | Описание |
|---|---|---|
idобязательный | string (UUID) | UUID организации |
Пример ответа
200 OK{
"status": 200,
"message": "Данные организации.",
"data": { "..." }
}
Пример запроса
curl "https://myreviews.dev/v1/firm/view?id=550e8400-e29b-41d4-a716-446655440000"
r = requests.get("https://myreviews.dev/v1/firm/view",
params={"id": "550e8400-e29b-41d4-a716-446655440000"})
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/view?id=550e8400-e29b-41d4-a716-446655440000'),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/view?id=550e8400-e29b-41d4-a716-446655440000");
const data = await res.json();
/v1/firm/create
Создание новой организации. При загрузке логотипа — multipart/form-data, иначе JSON.
Параметры запроса
Все поля оборачиваются в Firm.
| Параметр | Тип | Описание |
|---|---|---|
Firm[name]обязательный | string | Название организации |
Firm[address] | string | Адрес |
Firm[type] | int | Тип организации |
Firm[photo_upload] | file | Логотип, передаётся через multipart/form-data |
Пример ответа
200 OK{
"status": 200,
"message": "Организация создана.",
"id": 43
}
Пример запроса
# JSON — без файла
curl -X POST "https://myreviews.dev/v1/firm/create" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"Firm":{"name":"Новая компания","address":"Москва, ул. Новая, 1"}}'
# multipart/form-data — с логотипом
curl -X POST "https://myreviews.dev/v1/firm/create" \
-H "Authorization: Bearer JWT" \
-F 'Firm[name]=Новая компания' \
-F 'Firm[address]=Москва, ул. Новая, 1' \
-F 'Firm[photo_upload]=@/path/to/logo.png'
r = requests.post("https://myreviews.dev/v1/firm/create",
headers={"Authorization": f"Bearer {jwt}"},
json={"Firm": {"name": "Новая компания", "address": "Москва, ул. Новая, 1"}})
$payload = ['Firm' => ['name' => 'Новая компания', 'address' => 'Москва, ул. Новая, 1']];
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode($payload),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/create', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/create", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({
Firm: { name: "Новая компания", address: "Москва, ул. Новая, 1" }
})
});
/v1/firm/update
Обновление данных организации. Параметр id – UUID организации в query-строке.
Параметры запроса
| Параметр | Тип | Описание |
|---|---|---|
idобязательный | string (UUID) | UUID организации (query) |
Firm[name] | string | Название |
Firm[address] | string | Адрес |
Пример ответа
200 OK{
"status": 200,
"message": "Данные организации отредактированы."
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/firm/update?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"Firm":{"name":"Новое название"}}'
r = requests.post("https://myreviews.dev/v1/firm/update",
params={"id": "550e8400-e29b-41d4-a716-446655440000"},
headers={"Authorization": f"Bearer {jwt}"},
json={"Firm": {"name": "Новое название"}})
$payload = ['Firm' => ['name' => 'Новое название']];
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode($payload),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/update?id=550e8400-e29b-41d4-a716-446655440000', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/update?id=550e8400-e29b-41d4-a716-446655440000", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ Firm: { name: "Новое название" } })
});
/v1/firm/delete
Удаление организации. Только для владельца.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
idобязательный | string (UUID) | UUID организации |
Пример ответа
200 OK{
"status": 200,
"message": "Организация удалена."
}
Пример запроса
curl "https://myreviews.dev/v1/firm/delete?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer JWT"
r = requests.get("https://myreviews.dev/v1/firm/delete",
params={"id": "550e8400-e29b-41d4-a716-446655440000"},
headers={"Authorization": f"Bearer {jwt}"})
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => "Authorization: Bearer $jwt",
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/delete?id=550e8400-e29b-41d4-a716-446655440000', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/delete?id=550e8400-e29b-41d4-a716-446655440000", {
headers: { Authorization: "Bearer " + jwt }
});
Площадки отзывов
/v1/firm/services
Список всех доступных площадок для отзывов.
🌐 Публичный методПример ответа
200 OK{
"status": 200,
"message": "Сервисы",
"data": [
{ "id": 1, "name": "Яндекс" },
{ "id": 2, "name": "Google" },
{ "id": 3, "name": "2Gis" }
]
}
Пример запроса
curl "https://myreviews.dev/v1/firm/services"
r = requests.get("https://myreviews.dev/v1/firm/services")
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/services'),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/services");
const data = await res.json();
/v1/firm/add-service
Привязка площадки к организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
idобязательный | string (UUID) | UUID организации (query) |
serviceобязательный | int | ID площадки (body) |
urlобязательный | string | Ссылка на профиль организации на площадке (body) |
Пример ответа
200 OK{
"status": 200,
"message": "Новая площадка добавлена.",
"data": { "..." }
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/firm/add-service?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"service":1,"url":"https://yandex.ru/maps/..."}'
r = requests.post("https://myreviews.dev/v1/firm/add-service",
params={"id": "550e8400-e29b-41d4-a716-446655440000"},
headers={"Authorization": f"Bearer {jwt}"},
json={"service": 1, "url": "https://yandex.ru/maps/..."})
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode([
'service' => 1,
'url' => 'https://yandex.ru/maps/...',
]),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/add-service?id=550e8400-e29b-41d4-a716-446655440000', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/add-service?id=550e8400-e29b-41d4-a716-446655440000", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ service: 1, url: "https://yandex.ru/maps/..." })
});
/v1/firm/delete-service
Отвязка площадки от организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
idобязательный | string (UUID) | UUID организации (query) |
serviceобязательный | int | ID площадки (body) |
Пример ответа
200 OK{
"status": 200,
"message": "Площадка удалена"
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/firm/delete-service?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"service":1}'
r = requests.post("https://myreviews.dev/v1/firm/delete-service",
params={"id": "550e8400-e29b-41d4-a716-446655440000"},
headers={"Authorization": f"Bearer {jwt}"},
json={"service": 1})
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode(['service' => 1]),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/delete-service?id=550e8400-e29b-41d4-a716-446655440000', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/delete-service?id=550e8400-e29b-41d4-a716-446655440000", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ service: 1 })
});
Отзывы
/v1/review/index
Список отзывов с фильтрацией и пагинацией. Если firm_id не указан – отзывы по всем организациям пользователя.
Параметры запроса
| Параметр | Тип | Описание |
|---|---|---|
ReviewSearch[firm_id] | string (UUID) | UUID организации |
ReviewSearch[service] | int | ID площадки |
ReviewSearch[username] | string | Имя автора |
ReviewSearch[date_create] | string | Дата (дд.мм.гггг) |
sort | string | Сортировка: +id, -id, +date_create, -date_create |
page | int | Номер страницы |
per-page | int | Количество на странице (1–250) |
X-Pagination-Total-Count– общее количество записейX-Pagination-Page-Count– количество страницX-Pagination-Current-Page– текущая страницаX-Pagination-Per-Page– записей на странице
Пример запроса
curl "https://myreviews.dev/v1/review/index?ReviewSearch[firm_id]=550e8400-e29b-41d4-a716-446655440000&page=1&per-page=25" \
-H "Authorization: Bearer JWT"
r = requests.get("https://myreviews.dev/v1/review/index",
params={"ReviewSearch[firm_id]": "550e8400-e29b-41d4-a716-446655440000", "page": 1, "per-page": 25},
headers={"Authorization": f"Bearer {jwt}"})
total = r.headers.get("X-Pagination-Total-Count")
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => "Authorization: Bearer $jwt",
]]);
$url = 'https://myreviews.dev/v1/review/index?'
. http_build_query(['ReviewSearch' => ['firm_id' => '550e8400-e29b-41d4-a716-446655440000'], 'page' => 1, 'per-page' => 25]);
$data = json_decode(file_get_contents($url, false, $ctx), true);
const res = await fetch(
"https://myreviews.dev/v1/review/index?ReviewSearch[firm_id]=550e8400-e29b-41d4-a716-446655440000&page=1&per-page=25",
{ headers: { Authorization: "Bearer " + jwt } }
);
const total = res.headers.get("X-Pagination-Total-Count");
const data = await res.json();
/v1/review/create
Создание отзыва об организации. Принимает multipart/form-data — можно приложить до 10 изображений. UUID организации передаётся в query как firm_id.
Параметры запроса
Поля отзыва оборачиваются в Review. Массив изображений image[] передаётся плоско.
| Параметр | Тип | Описание |
|---|---|---|
firm_idобязательный | string (UUID) | UUID организации (query) |
Review[message]обязательный | string | Текст отзыва |
Review[rating]обязательный | int | Оценка от 1 до 5 |
Review[username] | string | Имя автора |
image[] | file[] | Изображения (до 10 файлов, multipart) |
Для отрицательных отзывов (перехват негатива) используйте POST /v1/review/create-negative?firm_id={id} с тем же форматом.
Пример ответа
200 OK{
"status": 200,
"message": "Отзыв создан",
"data": { "id": 1234 }
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/review/create?firm_id=550e8400-e29b-41d4-a716-446655440000" \
-F 'Review[message]=Всё понравилось' \
-F 'Review[rating]=5' \
-F 'Review[username]=Иван' \
-F 'image[]=@/path/to/photo1.jpg' \
-F 'image[]=@/path/to/photo2.jpg'
with open("photo1.jpg", "rb") as f1, open("photo2.jpg", "rb") as f2:
r = requests.post(
"https://myreviews.dev/v1/review/create",
params={"firm_id": "550e8400-e29b-41d4-a716-446655440000"},
data={
"Review[message]": "Всё понравилось",
"Review[rating]": 5,
"Review[username]": "Иван",
},
files=[("image[]", f1), ("image[]", f2)],
)
$ch = curl_init('https://myreviews.dev/v1/review/create?firm_id=550e8400-e29b-41d4-a716-446655440000');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'Review[message]' => 'Всё понравилось',
'Review[rating]' => 5,
'Review[username]' => 'Иван',
'image[0]' => new CURLFile('/path/to/photo1.jpg'),
'image[1]' => new CURLFile('/path/to/photo2.jpg'),
]);
$data = json_decode(curl_exec($ch), true);
const fd = new FormData();
fd.append("Review[message]", "Всё понравилось");
fd.append("Review[rating]", "5");
fd.append("Review[username]", "Иван");
for (const file of files) fd.append("image[]", file);
await fetch(
"https://myreviews.dev/v1/review/create?firm_id=550e8400-e29b-41d4-a716-446655440000",
{ method: "POST", body: fd }
);
Теги
/v1/firm/tags
Облако тегов (ключевые слова) из отзывов организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
idобязательный | string (UUID) | UUID организации |
Пример ответа
200 OK{
"status": 200,
"message": "Теги организации.",
"data": [ "..." ]
}
Пример запроса
curl "https://myreviews.dev/v1/firm/tags?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer JWT"
r = requests.get("https://myreviews.dev/v1/firm/tags",
params={"id": "550e8400-e29b-41d4-a716-446655440000"},
headers={"Authorization": f"Bearer {jwt}"})
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => "Authorization: Bearer $jwt",
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/firm/tags?id=550e8400-e29b-41d4-a716-446655440000', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/firm/tags?id=550e8400-e29b-41d4-a716-446655440000", {
headers: { Authorization: "Bearer " + jwt }
});
const data = await res.json();
/v1/review/create-tag
Добавление тега к отзыву. Только владелец организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
review_idобязательный | int | ID отзыва (query) |
ReviewTag[content]обязательный | string | Текст тега (body) |
Пример ответа
200 OK{
"status": 200,
"message": "Тег создан",
"data": { "..." }
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/review/create-tag?review_id=100" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"ReviewTag":{"content":"отличный сервис"}}'
r = requests.post("https://myreviews.dev/v1/review/create-tag",
params={"review_id": 100},
headers={"Authorization": f"Bearer {jwt}"},
json={"ReviewTag": {"content": "отличный сервис"}})
$payload = ['ReviewTag' => ['content' => 'отличный сервис']];
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode($payload),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/review/create-tag?review_id=100', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/review/create-tag?review_id=100", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ ReviewTag: { content: "отличный сервис" } })
});
/v1/review/delete-tag
Удаление ручного тега. Автоматические теги удалить нельзя.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
tag_idобязательный | int | ID тега |
Пример ответа
200 OK{
"status": 200,
"message": "Тег успешно удален"
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/review/delete-tag" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"tag_id":5}'
r = requests.post("https://myreviews.dev/v1/review/delete-tag",
headers={"Authorization": f"Bearer {jwt}"},
json={"tag_id": 5})
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode(['tag_id' => 5]),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/review/delete-tag', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/review/delete-tag", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ tag_id: 5 })
});
Ответы на отзывы
/v1/review/create-answer
Создание и отправка ответа (или жалобы) на отзыв. Только владелец организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
review_idобязательный | int | ID отзыва (query) |
complainобязательный | int | 0 – ответ, 1 – жалоба (query) |
ReviewAnswer[message]обязательный | string | Текст ответа (body) |
Пример ответа
200 OK{
"status": 200,
"message": "Ответ создан",
"data": {
"id": 1,
"message": "Спасибо!",
"status": 0
}
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/review/create-answer?review_id=100&complain=0" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"ReviewAnswer":{"message":"Спасибо за отзыв!"}}'
r = requests.post("https://myreviews.dev/v1/review/create-answer",
params={"review_id": 100, "complain": 0},
headers={"Authorization": f"Bearer {jwt}"},
json={"ReviewAnswer": {"message": "Спасибо за отзыв!"}})
$payload = ['ReviewAnswer' => ['message' => 'Спасибо за отзыв!']];
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode($payload),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/review/create-answer?review_id=100&complain=0', false, $ctx),
true
);
const res = await fetch(
"https://myreviews.dev/v1/review/create-answer?review_id=100&complain=0",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ ReviewAnswer: { message: "Спасибо за отзыв!" } })
}
);
/v1/review/generate-answer
Генерация текста ответа с помощью ИИ. Только владелец организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
review_idобязательный | int | ID отзыва |
complainобязательный | int | 0 – ответ, 1 – жалоба |
Пример ответа
200 OK{
"status": 200,
"message": "Ответ сгенерирован",
"data": "Сгенерированный текст ответа"
}
Пример запроса
curl "https://myreviews.dev/v1/review/generate-answer?review_id=100&complain=0" \
-H "Authorization: Bearer JWT"
r = requests.get("https://myreviews.dev/v1/review/generate-answer",
params={"review_id": 100, "complain": 0},
headers={"Authorization": f"Bearer {jwt}"})
$ctx = stream_context_create(['http' => [
'method' => 'GET',
'header' => "Authorization: Bearer $jwt",
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/review/generate-answer?review_id=100&complain=0', false, $ctx),
true
);
const res = await fetch(
"https://myreviews.dev/v1/review/generate-answer?review_id=100&complain=0",
{ headers: { Authorization: "Bearer " + jwt } }
);
const data = await res.json();
/v1/review/delete-answer
Удаление ответа на отзыв. Только владелец организации.
🔒 АвторизацияПараметры запроса
| Параметр | Тип | Описание |
|---|---|---|
answer_idобязательный | int | ID ответа |
Пример ответа
200 OK{
"status": 200,
"message": "Ответ успешно удален"
}
Пример запроса
curl -X POST "https://myreviews.dev/v1/review/delete-answer" \
-H "Authorization: Bearer JWT" \
-H "Content-Type: application/json" \
-d '{"answer_id":1}'
r = requests.post("https://myreviews.dev/v1/review/delete-answer",
headers={"Authorization": f"Bearer {jwt}"},
json={"answer_id": 1})
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $jwt\r\nContent-Type: application/json",
'content' => json_encode(['answer_id' => 1]),
]]);
$data = json_decode(
file_get_contents('https://myreviews.dev/v1/review/delete-answer', false, $ctx),
true
);
const res = await fetch("https://myreviews.dev/v1/review/delete-answer", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + jwt
},
body: JSON.stringify({ answer_id: 1 })
});
Справочник площадок
Таблица соответствия числовых ID и названий площадок. Актуальный список можно получить через GET /v1/firm/services.
| ID | Площадка |
|---|---|
1 | Яндекс |
2 | |
3 | 2ГИС |
4 | Zoon |
5 | Yell |
6 | MyReviews |
7 | ПроДокторов |
8 | Flamp |
10 | Otzovik |
12 | Яндекс.Услуги |
13 | Авито |
14 | На Поправку |
15 | Яндекс.Бизнес |
16 | СберЗдоровье |
17 | Т-БАНК |
18 | ВКонтакте |
19 | Trustpilot |
21 | IRecommend |
22 | Перекрёсток |
23 | Metro |
24 | Магнит |