ТапВей API
API проекта ТапВей: онлайн-запись, магазин, заявки, CRM, статистика. Доступно на тарифах «Про» и «Бизнес». Адрес: https://api.tapway.me/v1. Машинное описание: openapi.json (OpenAPI 3.1) — его можно открыть в Postman, Insomnia или сгенерировать клиент.
Ключ работает только с вашего сервера: запросы из браузера посетителя не поддерживаются, и ключ нельзя показывать на страницах сайта.
Ключ и права
Ключ создаёт владелец проекта в кабинете: Настройки → API, с подтверждением пароля. Ключ показывается один раз — сохраните его. Передавайте в заголовке:
curl https://api.tapway.me/v1/me \ -H "Authorization: Bearer tw_live_…"
У ключа есть права — включаются галочками при создании:
| Право | Что даёт |
|---|---|
bookings:read | Онлайн-запись: чтение |
bookings:write | Онлайн-запись: создание и изменение |
leads:read | Заявки и ответы квизов: чтение |
shop:read | Магазин: чтение |
shop:write | Магазин: товары и заказы |
crm:read | CRM: чтение контактов |
crm:write | CRM: контакты и сделки |
stats:read | Статистика: чтение |
Ключ отзывается в кабинете и автоматически — при передаче проекта другому владельцу. Тариф ниже «Про» — ответ 402, ключи заработают снова после продления.
Лимиты
| Тариф | В минуту | В сутки |
|---|---|---|
| Про | 60 | 10 000 |
| Бизнес | 300 | 100 000 |
Остаток — в заголовках X-RateLimit-Remaining-Minute и X-RateLimit-Remaining-Day. Сверх лимита — 429 и Retry-After. Отдельно: фото — 300 в час, пакетная загрузка товаров — 60 пакетов в час.
Ответы и ошибки
Успех — {"data": …}. Ошибка — HTTP-код и тело:
{
"error": {
"code": "slot_unavailable",
"message": "Выбранное время недоступно"
}
}
| Код | Когда |
|---|---|
400 invalid | Неверные поля; в error.fields — какие |
401 unauthorized | Нет ключа, ключ неверный или отозван |
402 tariff / quota | Тариф без API или исчерпан лимит тарифа (товары, контакты) |
403 forbidden | У ключа нет нужного права |
404 not_found | Нет такого объекта в вашем проекте |
| 409 | Конфликт: время занято, запись закрыта, заказ уже отменён |
422 content_rejected | Текст, ссылка или фото не прошли проверку содержания |
429 rate_limited | Слишком много запросов |
| 5xx | Сбой на нашей стороне — повторите позже |
Страницы, id и время
Списки отдают до limit записей (по умолчанию 50, максимум 200) и next_cursor. Передайте его в cursor, чтобы получить следующую страницу; null — страниц больше нет. Для синхронизации используйте updated_since.
Все id — 32 шестнадцатеричных символа и случайны; заказ — по номеру TW…. Время записи (starts_at) — местное, как его видит владелец; служебные отметки (created_at) — ISO 8601 в UTC.
Защита от дублей
Создание записи принимает заголовок Idempotency-Key (8–80 символов, например номер заказа в вашей системе). Повтор того же запроса с тем же ключом в течение суток вернёт первый ответ с заголовком Idempotent-Replayed: true — второй записи не будет. Тот же ключ с другим телом — 422.
Вебхуки
ТапВей отправит POST с JSON на ваш адрес при событиях проекта. Адрес задаётся в кабинете: CRM → Вебхуки (с тарифа «Про»). Только https://; перенаправления не выполняются.
{
"id": "3f0c9a1e-7b2d-4c5e-9f8a-1d2e3f4a5b6c",
"event": "booking.created",
"created_at": "2026-11-13T12:00:00.000Z",
"multi_id": 123,
"payload": {
"appointment": {
"id": 4512,
"client_name": "Мария",
"client_phone": "+79001234567",
"starts_at": "2026-11-20 14:00"
},
"master": "Анна",
"service": "Стрижка"
}
}
Заголовки: X-TapWay-Event, X-TapWay-Event-Id (тот же, что id в теле, не меняется при повторах — по нему отсеивайте дубли), X-TapWay-Timestamp, X-TapWay-Signature-V2: t=…,v1=….
Проверка подписи: HMAC-SHA256 от строки t + "." + сырое тело с секретом вебхука должен совпасть с v1; отклоняйте запросы старше 5 минут.
const crypto = require('crypto');
// rawBody — тело запроса как пришло, до JSON.parse
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // старше 5 минут
const expected = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
return expected.length === parts.v1.length
&& crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}$raw = file_get_contents('php://input');
$p = [];
foreach (explode(',', $_SERVER['HTTP_X_TAPWAY_SIGNATURE_V2'] ?? '') as $kv) {
[$k, $v] = array_pad(explode('=', $kv, 2), 2, '');
$p[$k] = $v;
}
$ok = isset($p['t'], $p['v1'])
&& abs(time() - (int)$p['t']) <= 300
&& hash_equals(hash_hmac('sha256', $p['t'] . '.' . $raw, $secret), $p['v1']);
Ответьте 2xx за 10 секунд. При ошибке сети, 5xx или 429 повторим 6 раз в течение ~21 часа; на другие 4xx не повторяем; на 410 вебхук выключится. Журнал доставок и кнопка «Проверить» — в кабинете.
| Событие | Когда |
|---|---|
form.submit | Заявка с формы |
survey.submit | Ответ на квиз с контактами |
survey.started | Начат квиз |
survey.finished | Завершён квиз |
payment.paid | Оплата по кнопке оплаты |
booking.created | Новая запись |
booking.rescheduled | Запись перенесена |
booking.cancelled | Запись отменена |
booking.completed | Клиент пришёл |
booking.no_show | Клиент не пришёл |
booking.scheduled | Запись снова активна (смена статуса в кабинете) |
booking.synced | Запись перенесена в CRM из кабинета |
order.created | Новый заказ |
order.paid | Заказ оплачен |
order.shipped | Заказ отправлен |
order.cancelled | Заказ отменён |
contact.upsert | Контакт создан или изменён |
deal.created | Сделка создана |
deal.updated | Сделка изменена |
test.ping | Проверка из кабинета |
Основа
GET /v1/ping
Проверка ключа и связи
Ответ 200
{
"data": {
"ok": true,
"time": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/me
Проект, тариф, права и лимиты ключа
Ответ 200
{
"data": {
"project": {
"id": "fe6dee299ccf49369e79d9e18ca741c1",
"name": "Студия Анны",
"address": "mob.bio/studio-anna"
},
"tariff": {
"code": "pro",
"name": "Про"
},
"key": {
"name": "Сайт студии",
"prefix": "tw_live_aKpn",
"scopes": [
"bookings:read",
"bookings:write"
]
},
"rate_limit": {
"per_minute": 60,
"per_day": 10000,
"remaining_minute": 59,
"remaining_day": 9874
}
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
Онлайн-запись
GET /v1/booking/resources
Блоки записи: мастера, ресурсы и услуги · право bookings:read
Ответ 200
{
"data": [
{
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"masters": [
{
"id": "m1",
"name": "Анна",
"kind": "time",
"work_start": "10:00",
"work_end": "20:00",
"services": [
{
"id": "s1",
"name": "Стрижка",
"duration_min": 60,
"price": "1500 ₽",
"capacity": 1,
"max_per_booking": 1,
"start_times": null,
"min_nights": null,
"max_nights": null,
"prepay": null
}
]
}
]
}
]
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/booking/slots
Свободное время на дату · право bookings:read
Для записи по времени — свободные слоты дня. Для посуточных ресурсов — сколько ночей подряд свободно с даты заезда.
| Параметр | Где | Описание |
|---|---|---|
block_id обязательно | запрос | id блока записи |
master_id обязательно | запрос | id мастера или ресурса |
service_id обязательно | запрос | id услуги |
date обязательно | запрос | Дата |
seats | запрос | Сколько мест нужно (для групп) |
Ответ 200
{
"data": {
"kind": "time",
"date": "2026-11-20",
"duration_min": 60,
"slots": [
{
"time": "10:00"
},
{
"time": "11:00"
}
]
}
}
Ошибки
- 400 — Неверные параметры
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Блок, мастер или услуга не найдены
- 409 — Запись закрыта (исчерпан лимит записей тарифа)
GET /v1/booking/appointments
Список записей · право bookings:read
| Параметр | Где | Описание |
|---|---|---|
from | запрос | С даты записи |
to | запрос | По дату записи |
status | запрос | scheduled, completed, cancelled или no_show |
block_id | запрос | Только этот блок |
updated_since | запрос | Только изменённые после этого момента (ISO 8601) |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "9a395e452787c014acb54d98d7549a27",
"status": "scheduled",
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"master": {
"id": "m1",
"name": "Анна"
},
"service": {
"id": "s1",
"name": "Стрижка",
"duration_min": 60
},
"starts_at": "2026-11-20 14:00",
"ends_at": "2026-11-20 15:00",
"date": "2026-11-20",
"time": "14:00",
"nights": null,
"checkout_date": null,
"seats": 1,
"client": {
"name": "Мария",
"phone": "+79001234567",
"email": null
},
"comment": "Из CRM",
"source": "api",
"prepay": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/booking/appointments
Создать запись · право bookings:write
Те же проверки, что у формы на странице: свободное время, места, лимит записей клиента в день, месячный лимит тарифа. Уведомления владельцу, мастеру и клиенту уходят как обычно. Предоплата через API не запрашивается.
| Параметр | Где | Описание |
|---|---|---|
Idempotency-Key | заголовок | Защита от дублей: повтор с тем же ключом (8–80 символов) в течение суток вернёт первый ответ, не создавая второй объект |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
block_id обязательно | string | Публичный id: 32 шестнадцатеричных символа |
master_id обязательно | string | |
service_id обязательно | string | |
date обязательно | string | Дата YYYY-MM-DD |
time | string | HH:MM — для записи по времени |
nights | integer | Для посуточных |
seats | integer | Мест (по умолчанию 1) |
client обязательно | object | |
comment | string | До 1000 символов |
{
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"master_id": "m1",
"service_id": "s1",
"date": "2026-11-20",
"time": "14:00",
"client": {
"name": "Анна",
"phone": "+79001234567"
},
"comment": "Из CRM"
}
Ответ 201
{
"data": {
"id": "9a395e452787c014acb54d98d7549a27",
"status": "scheduled",
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"master": {
"id": "m1",
"name": "Анна"
},
"service": {
"id": "s1",
"name": "Стрижка",
"duration_min": 60
},
"starts_at": "2026-11-20 14:00",
"ends_at": "2026-11-20 15:00",
"date": "2026-11-20",
"time": "14:00",
"nights": null,
"checkout_date": null,
"seats": 1,
"client": {
"name": "Мария",
"phone": "+79001234567",
"email": null
},
"comment": "Из CRM",
"source": "api",
"prepay": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 400 — Неверные поля
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Блок, мастер или услуга не найдены
- 409 — Время занято (slot_unavailable), лимит клиента (client_limit) или запись закрыта (booking_closed)
- 422 — Idempotency-Key уже использован с другим запросом
GET /v1/booking/appointments/{id}
Одна запись · право bookings:read
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id записи |
Ответ 200
{
"data": {
"id": "9a395e452787c014acb54d98d7549a27",
"status": "scheduled",
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"master": {
"id": "m1",
"name": "Анна"
},
"service": {
"id": "s1",
"name": "Стрижка",
"duration_min": 60
},
"starts_at": "2026-11-20 14:00",
"ends_at": "2026-11-20 15:00",
"date": "2026-11-20",
"time": "14:00",
"nights": null,
"checkout_date": null,
"seats": 1,
"client": {
"name": "Мария",
"phone": "+79001234567",
"email": null
},
"comment": "Из CRM",
"source": "api",
"prepay": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
PATCH /v1/booking/appointments/{id}
Сменить статус записи · право bookings:write
completed — пришёл, no_show — не пришёл, cancelled — отмена (клиент получит сообщение, время освободится). Вернуть отменённую запись нельзя — создайте новую.
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id записи |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
status обязательно | string | (scheduled, completed, cancelled, no_show) |
{
"status": "cancelled"
}
Ответ 200
{
"data": {
"id": "9a395e452787c014acb54d98d7549a27",
"status": "cancelled",
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"master": {
"id": "m1",
"name": "Анна"
},
"service": {
"id": "s1",
"name": "Стрижка",
"duration_min": 60
},
"starts_at": "2026-11-20 14:00",
"ends_at": "2026-11-20 15:00",
"date": "2026-11-20",
"time": "14:00",
"nights": null,
"checkout_date": null,
"seats": 1,
"client": {
"name": "Мария",
"phone": "+79001234567",
"email": null
},
"comment": "Из CRM",
"source": "api",
"prepay": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 400 — Неверный статус
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
- 409 — Нельзя вернуть отменённую
POST /v1/booking/appointments/{id}/reschedule
Перенести запись · право bookings:write
Проверяется, свободно ли новое время (сама запись в занятость не считается). Клиент и мастер получат сообщение о переносе.
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id записи |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
date обязательно | string | Дата YYYY-MM-DD |
time | string | HH:MM |
nights | integer | Для посуточных |
{
"date": "2026-11-21",
"time": "15:00"
}
Ответ 200
{
"data": {
"id": "9a395e452787c014acb54d98d7549a27",
"status": "scheduled",
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"master": {
"id": "m1",
"name": "Анна"
},
"service": {
"id": "s1",
"name": "Стрижка",
"duration_min": 60
},
"starts_at": "2026-11-21 15:00",
"ends_at": "2026-11-21 16:00",
"date": "2026-11-21",
"time": "15:00",
"nights": null,
"checkout_date": null,
"seats": 1,
"client": {
"name": "Мария",
"phone": "+79001234567",
"email": null
},
"comment": "Из CRM",
"source": "api",
"prepay": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 400 — Неверные поля
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
- 409 — Время занято или запись не активна
Магазин
GET /v1/shop/categories
Категории · право shop:read
Ответ 200
{
"data": [
{
"id": "b6f79eaadf6c11f19760fa163eb739b5",
"parent_id": null,
"title": "Свечи",
"slug": "svechi",
"description": "Ароматные свечи ручной работы",
"sort_order": 0,
"is_active": true
}
]
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/shop/categories
Создать категорию · право shop:write
Один уровень вложенности: подкатегория кладётся только в категорию верхнего уровня.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title обязательно | string | |
slug | string | |
description | string | |
parent_id | string | null | Публичный id: 32 шестнадцатеричных символа |
sort_order | integer | |
is_active | boolean |
{
"title": "Свечи",
"description": "Ароматные свечи ручной работы"
}
Ответ 201
{
"data": {
"id": "b6f79eaadf6c11f19760fa163eb739b5",
"parent_id": null,
"title": "Свечи",
"slug": "svechi",
"description": "Ароматные свечи ручной работы",
"sort_order": 0,
"is_active": true
}
}
Ошибки
- 400 — Неверные поля
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Родитель не найден
PATCH /v1/shop/categories/{id}
Изменить категорию · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id категории |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title | string | |
slug | string | |
description | string | |
parent_id | string | null | Публичный id: 32 шестнадцатеричных символа |
sort_order | integer | |
is_active | boolean |
{
"title": "Соевые свечи",
"is_active": false
}
Ответ 200
{
"data": {
"id": "b6f79eaadf6c11f19760fa163eb739b5",
"parent_id": null,
"title": "Свечи",
"slug": "svechi",
"description": "Ароматные свечи ручной работы",
"sort_order": 0,
"is_active": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
DELETE /v1/shop/categories/{id}
Удалить категорию · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id категории |
Ответ 200
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"deleted": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
GET /v1/shop/attributes
Характеристики товаров · право shop:read
Ответ 200
{
"data": [
{
"name": "Аромат",
"slug": "aromat",
"is_filter": true
}
]
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/shop/products
Список товаров · право shop:read
| Параметр | Где | Описание |
|---|---|---|
active | запрос | 1 — только показанные, 0 — только скрытые |
sku | запрос | По артикулу |
category_id | запрос | Из категории |
updated_since | запрос | Только изменённые после этого момента (ISO 8601) |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"title": "Свеча «Лаванда»",
"slug": "svecha-lavanda",
"sku": "LAV-1",
"description": "Соевый воск, 40 часов горения",
"price": 990,
"compare_at_price": 1200,
"currency": "RUB",
"stock": 10,
"made_to_order": false,
"lead_days": null,
"weight_g": 300,
"dimensions": null,
"is_active": true,
"is_digital": false,
"vat_code": null,
"sort_order": 0,
"images": [
"https://mob.bio/api/media/s3?key=iteration%2Fshop%2F…jpg"
],
"category_ids": [
"b6f79eaadf6c11f19760fa163eb739b5"
],
"attributes": [
{
"name": "Аромат",
"values": [
"лаванда"
]
}
],
"variants": [
{
"id": "88a3467d6b7aaf2ca805017f59430342",
"title": "200 мл",
"sku": "LAV-1-200",
"price": 990,
"stock": 5,
"is_active": true
}
],
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/shop/products
Создать товар · право shop:write
Название, описание и варианты проверяются на запрещённое содержание, ссылки в описании — по базе опасных адресов. Фото — только загруженные через POST /shop/images.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title | string | До 255 символов |
sku | string | null | Артикул, до 64 символов. По нему пакетная загрузка находит товар |
slug | string | Латиница, цифры, дефис |
description | string | null | До 60 000 символов |
price | number | |
compare_at_price | number | null | |
stock | integer | null | |
made_to_order | boolean | |
lead_days | integer | null | |
weight_g | integer | null | |
dimensions | object | null | |
is_active | boolean | |
is_digital | boolean | |
vat_code | integer | null | |
sort_order | integer | |
images | string[] | Только адреса из POST /shop/images или уже стоящие в товарах проекта. До 20 |
category_ids | string[] | Пустой список снимает все категории |
attributes | object[] | |
variants | object[] | Только при создании. До 100 |
{
"title": "Свеча «Лаванда»",
"sku": "LAV-1",
"price": 990,
"stock": 10,
"images": [
"https://mob.bio/api/media/s3?key=…"
],
"category_ids": [
"b6f79eaadf6c11f19760fa163eb739b5"
],
"variants": [
{
"title": "200 мл",
"price": 990,
"stock": 5
}
]
}
Ответ 201
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"title": "Свеча «Лаванда»",
"slug": "svecha-lavanda",
"sku": "LAV-1",
"description": "Соевый воск, 40 часов горения",
"price": 990,
"compare_at_price": 1200,
"currency": "RUB",
"stock": 10,
"made_to_order": false,
"lead_days": null,
"weight_g": 300,
"dimensions": null,
"is_active": true,
"is_digital": false,
"vat_code": null,
"sort_order": 0,
"images": [
"https://mob.bio/api/media/s3?key=iteration%2Fshop%2F…jpg"
],
"category_ids": [
"b6f79eaadf6c11f19760fa163eb739b5"
],
"attributes": [
{
"name": "Аромат",
"values": [
"лаванда"
]
}
],
"variants": [
{
"id": "88a3467d6b7aaf2ca805017f59430342",
"title": "200 мл",
"sku": "LAV-1-200",
"price": 990,
"stock": 5,
"is_active": true
}
],
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 400 — Неверные поля или чужие фото
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 422 — Текст не прошёл проверку содержания
GET /v1/shop/products/{id}
Один товар · право shop:read
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id товара |
Ответ 200
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"title": "Свеча «Лаванда»",
"slug": "svecha-lavanda",
"sku": "LAV-1",
"description": "Соевый воск, 40 часов горения",
"price": 990,
"compare_at_price": 1200,
"currency": "RUB",
"stock": 10,
"made_to_order": false,
"lead_days": null,
"weight_g": 300,
"dimensions": null,
"is_active": true,
"is_digital": false,
"vat_code": null,
"sort_order": 0,
"images": [
"https://mob.bio/api/media/s3?key=iteration%2Fshop%2F…jpg"
],
"category_ids": [
"b6f79eaadf6c11f19760fa163eb739b5"
],
"attributes": [
{
"name": "Аромат",
"values": [
"лаванда"
]
}
],
"variants": [
{
"id": "88a3467d6b7aaf2ca805017f59430342",
"title": "200 мл",
"sku": "LAV-1-200",
"price": 990,
"stock": 5,
"is_active": true
}
],
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
PATCH /v1/shop/products/{id}
Изменить товар · право shop:write
Передавайте только меняющиеся поля. Варианты меняются своими методами.
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id товара |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title | string | До 255 символов |
sku | string | null | Артикул, до 64 символов. По нему пакетная загрузка находит товар |
slug | string | Латиница, цифры, дефис |
description | string | null | До 60 000 символов |
price | number | |
compare_at_price | number | null | |
stock | integer | null | |
made_to_order | boolean | |
lead_days | integer | null | |
weight_g | integer | null | |
dimensions | object | null | |
is_active | boolean | |
is_digital | boolean | |
vat_code | integer | null | |
sort_order | integer | |
images | string[] | Только адреса из POST /shop/images или уже стоящие в товарах проекта. До 20 |
category_ids | string[] | Пустой список снимает все категории |
attributes | object[] | |
variants | object[] | Только при создании. До 100 |
{
"price": 1090,
"stock": 8
}
Ответ 200
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"title": "Свеча «Лаванда»",
"slug": "svecha-lavanda",
"sku": "LAV-1",
"description": "Соевый воск, 40 часов горения",
"price": 990,
"compare_at_price": 1200,
"currency": "RUB",
"stock": 10,
"made_to_order": false,
"lead_days": null,
"weight_g": 300,
"dimensions": null,
"is_active": true,
"is_digital": false,
"vat_code": null,
"sort_order": 0,
"images": [
"https://mob.bio/api/media/s3?key=iteration%2Fshop%2F…jpg"
],
"category_ids": [
"b6f79eaadf6c11f19760fa163eb739b5"
],
"attributes": [
{
"name": "Аромат",
"values": [
"лаванда"
]
}
],
"variants": [
{
"id": "88a3467d6b7aaf2ca805017f59430342",
"title": "200 мл",
"sku": "LAV-1-200",
"price": 990,
"stock": 5,
"is_active": true
}
],
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:00:00.000Z"
}
}
Ошибки
- 400 — Неверные поля
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
- 422 — Текст не прошёл проверку
DELETE /v1/shop/products/{id}
Удалить товар · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id товара |
Ответ 200
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"deleted": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
POST /v1/shop/products/bulk
Пакетная загрузка до 100 товаров · право shop:write
Товар с артикулом (sku), который уже есть в магазине, обновляется (без вариантов), остальные создаются. Ошибка одной позиции не останавливает остальные. Не больше 60 пакетов в час на ключ.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
products обязательно | ProductInput[] |
{
"products": [
{
"sku": "LAV-1",
"title": "Свеча «Лаванда»",
"price": 1090,
"stock": 8
},
{
"sku": "ROSE-1",
"title": "Свеча «Роза»",
"price": 890
}
]
}
Ответ 200
{
"data": [
{
"index": 0,
"ok": true,
"action": "updated",
"id": "7cc0184d032b083e9a398a0c9076c4dc"
},
{
"index": 1,
"ok": false,
"error": {
"code": "invalid",
"message": "Проверьте поля: title"
}
}
]
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/shop/products/bulk-delete
Удалить до 500 товаров · право shop:write
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
ids обязательно | string[] |
{
"ids": [
"7cc0184d032b083e9a398a0c9076c4dc"
]
}
Ответ 200
{
"data": {
"deleted": 1
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/shop/products/{id}/variants
Добавить вариант · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id товара |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title обязательно | string | |
sku | string | |
price | number | null | |
stock | integer | null | |
is_active | boolean |
{
"title": "400 мл",
"price": 1590,
"stock": 3
}
Ответ 201
{
"data": {
"id": "88a3467d6b7aaf2ca805017f59430342",
"title": "200 мл",
"sku": "LAV-1-200",
"price": 990,
"stock": 5,
"is_active": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Товар не найден
PATCH /v1/shop/products/{id}/variants/{vid}
Изменить вариант · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id товара |
vid обязательно | путь | id варианта |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title | string | |
sku | string | |
price | number | null | |
stock | integer | null | |
is_active | boolean |
{
"stock": 7
}
Ответ 200
{
"data": {
"id": "88a3467d6b7aaf2ca805017f59430342",
"title": "200 мл",
"sku": "LAV-1-200",
"price": 990,
"stock": 5,
"is_active": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
DELETE /v1/shop/products/{id}/variants/{vid}
Удалить вариант · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id товара |
vid обязательно | путь | id варианта |
Ответ 200
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"deleted": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
POST /v1/shop/images
Загрузить фото товара · право shop:write
multipart/form-data, поле file: PNG, JPEG, WebP, GIF, AVIF, до 8 МБ. Фото проверяется на откровенное содержание до сохранения. Верните url в images товара. Не больше 300 фото в час на ключ.
Тело запроса — multipart/form-data
curl -X POST https://api.tapway.me/v1/shop/images \ -H "Authorization: Bearer tw_live_…" \ -F "file=@photo.jpg"
Ответ 201
{
"data": {
"url": "https://mob.bio/api/media/s3?key=iteration%2Fshop%2F1794579344013-b1b2.jpg"
}
}
Ошибки
- 400 — Не изображение
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 413 — Больше 8 МБ
- 422 — Фото не прошло проверку
GET /v1/shop/orders
Список заказов · право shop:read
| Параметр | Где | Описание |
|---|---|---|
status | запрос | Статус заказа |
payment_status | запрос | Статус оплаты |
from | запрос | Создан с даты |
to | запрос | Создан по дату |
updated_since | запрос | Только изменённые после этого момента (ISO 8601) |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "TWMHX2K1A9F3C0D4E5B6A7C8D9",
"status": "paid",
"payment_status": "paid",
"fulfillment_status": "unfulfilled",
"total": 2280,
"items_total": 1980,
"delivery_cost": 300,
"currency": "RUB",
"customer": {
"name": "Мария",
"phone": "+79001234567",
"email": "maria@example.com"
},
"delivery": {
"type": "courier",
"address": "Москва, ул. Лесная, 5",
"pickup_point": null,
"tracking_url": null
},
"notes": "Позвоните за час",
"admin_notes": null,
"fields": [],
"items": [
{
"product_id": "7cc0184d032b083e9a398a0c9076c4dc",
"variant_id": "88a3467d6b7aaf2ca805017f59430342",
"title": "Свеча «Лаванда» 200 мл",
"qty": 2,
"price": 990
}
],
"paid_at": "2026-11-13T12:05:00.000Z",
"refunded_at": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:05:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/shop/orders/{id}
Один заказ по номеру · право shop:read
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | Номер заказа TW… |
Ответ 200
{
"data": {
"id": "TWMHX2K1A9F3C0D4E5B6A7C8D9",
"status": "paid",
"payment_status": "paid",
"fulfillment_status": "unfulfilled",
"total": 2280,
"items_total": 1980,
"delivery_cost": 300,
"currency": "RUB",
"customer": {
"name": "Мария",
"phone": "+79001234567",
"email": "maria@example.com"
},
"delivery": {
"type": "courier",
"address": "Москва, ул. Лесная, 5",
"pickup_point": null,
"tracking_url": null
},
"notes": "Позвоните за час",
"admin_notes": null,
"fields": [],
"items": [
{
"product_id": "7cc0184d032b083e9a398a0c9076c4dc",
"variant_id": "88a3467d6b7aaf2ca805017f59430342",
"title": "Свеча «Лаванда» 200 мл",
"qty": 2,
"price": 990
}
],
"paid_at": "2026-11-13T12:05:00.000Z",
"refunded_at": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:05:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
PATCH /v1/shop/orders/{id}
Статус, отслеживание, заметка · право shop:write
Отмена возвращает остатки на склад, покупатель получает письмо о смене статуса — как из кабинета. Отменённый или возвращённый заказ не меняется. Отправления СДЭК/Яндекс через API не создаются.
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | Номер заказа TW… |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
status | string | (new, pending, confirmed, paid, processing, shipped, completed, cancelled, refunded) |
tracking_url | string | https://… |
admin_notes | string |
{
"status": "shipped",
"tracking_url": "https://www.cdek.ru/ru/tracking?order_id=123"
}
Ответ 200
{
"data": {
"id": "TWMHX2K1A9F3C0D4E5B6A7C8D9",
"status": "shipped",
"payment_status": "paid",
"fulfillment_status": "unfulfilled",
"total": 2280,
"items_total": 1980,
"delivery_cost": 300,
"currency": "RUB",
"customer": {
"name": "Мария",
"phone": "+79001234567",
"email": "maria@example.com"
},
"delivery": {
"type": "courier",
"address": "Москва, ул. Лесная, 5",
"pickup_point": null,
"tracking_url": "https://www.cdek.ru/ru/tracking?order_id=123"
},
"notes": "Позвоните за час",
"admin_notes": null,
"fields": [],
"items": [
{
"product_id": "7cc0184d032b083e9a398a0c9076c4dc",
"variant_id": "88a3467d6b7aaf2ca805017f59430342",
"title": "Свеча «Лаванда» 200 мл",
"qty": 2,
"price": 990
}
],
"paid_at": "2026-11-13T12:05:00.000Z",
"refunded_at": null,
"created_at": "2026-11-13T12:00:00.000Z",
"updated_at": "2026-11-13T12:05:00.000Z"
}
}
Ошибки
- 400 — Неверные поля
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
- 409 — Заказ уже отменён или возвращён
GET /v1/shop/reviews
Отзывы · право shop:read
| Параметр | Где | Описание |
|---|---|---|
status | запрос | pending, published или hidden |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "5d1e0c7a9b2f4e6d8c3a1b0f9e8d7c6b",
"product_id": "7cc0184d032b083e9a398a0c9076c4dc",
"author_name": "Ольга",
"rating": 5,
"body": "Пахнет чудесно, горит долго",
"status": "published",
"is_buyer": true,
"reply": "Спасибо!",
"created_at": "2026-11-12T09:00:00.000Z",
"published_at": "2026-11-12T10:00:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
PATCH /v1/shop/reviews/{id}
Опубликовать, скрыть, ответить · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id отзыва |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
status | string | (pending, published, hidden) |
reply | string | null |
{
"status": "published",
"reply": "Спасибо за отзыв!"
}
Ответ 200
{
"data": {
"id": "5d1e0c7a9b2f4e6d8c3a1b0f9e8d7c6b",
"product_id": "7cc0184d032b083e9a398a0c9076c4dc",
"author_name": "Ольга",
"rating": 5,
"body": "Пахнет чудесно, горит долго",
"status": "published",
"is_buyer": true,
"reply": "Спасибо!",
"created_at": "2026-11-12T09:00:00.000Z",
"published_at": "2026-11-12T10:00:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
DELETE /v1/shop/reviews/{id}
Удалить отзыв · право shop:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id отзыва |
Ответ 200
{
"data": {
"id": "7cc0184d032b083e9a398a0c9076c4dc",
"deleted": true
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
Заявки и квизы
GET /v1/leads/forms
Заявки с форм мультиссылки и сайта · право leads:read
| Параметр | Где | Описание |
|---|---|---|
from | запрос | С даты |
to | запрос | По дату |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "2b7f0c9e4d3a4f1e8a6c5d2b1e0f9a8c",
"block_id": "4f3e2d1c0b9a48b7a6c5d4e3f2a1b0c9",
"name": "Ольга",
"phone": "+79165551230",
"email": null,
"fields": {
"name": "Ольга",
"phone": "+79165551230",
"message": "Хочу на консультацию"
},
"created_at": "2026-11-13T09:14:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/leads/surveys
Квизы и опросы · право leads:read
Ответ 200
{
"data": [
{
"id": "c1d2e3f4a5b6478899aabbccddeeff00",
"title": "Подбор ухода",
"mode": "quiz",
"status": "published",
"slug": "podbor-uhoda",
"responses": 42,
"created_at": "2026-10-01T08:00:00.000Z"
}
]
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/leads/surveys/{id}/responses
Ответы квиза · право leads:read
По умолчанию — только завершённые. finished=all — вместе с брошенными на полпути.
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id квиза |
finished | запрос | all — все ответы |
updated_since | запрос | Только изменённые после этого момента (ISO 8601) |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "0f1e2d3c4b5a49687766554433221100",
"finished": true,
"score": 3,
"result": "Уход для сухой кожи",
"answers": [
{
"question": "Тип кожи",
"answer": "Сухая"
},
{
"question": "Что важнее всего?",
"answer": "Увлажнение"
}
],
"contact": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": null
},
"started_at": "2026-11-13T10:00:00.000Z",
"finished_at": "2026-11-13T10:02:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Квиз не найден
CRM
GET /v1/crm/contacts
Контакты · право crm:read
| Параметр | Где | Описание |
|---|---|---|
q | запрос | Поиск по имени, телефону, почте |
updated_since | запрос | Только изменённые после этого момента (ISO 8601) |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/crm/contacts
Создать или обновить контакт · право crm:write
Контакт с тем же телефоном (последние 10 цифр) или почтой обновляется — ответ 200 и created=false. Новый — 201. Новый контакт упирается в лимит контактов тарифа.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
name | string | |
phone | string | |
email | string | |
telegram | string |
{
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com"
}
Ответ 201
{
"data": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
},
"created": true
}
Ошибки
- 400 — Нужны name, phone или email
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
GET /v1/crm/contacts/{id}
Один контакт · право crm:read
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id контакта |
Ответ 200
{
"data": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
PATCH /v1/crm/contacts/{id}
Изменить контакт · право crm:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id контакта |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
name | string | null | |
phone | string | null | |
email | string | null | |
telegram | string | null |
{
"telegram": "@vika"
}
Ответ 200
{
"data": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найден
GET /v1/crm/deals
Сделки · право crm:read
| Параметр | Где | Описание |
|---|---|---|
stage | запрос | Стадия |
contact_id | запрос | Сделки контакта |
updated_since | запрос | Только изменённые после этого момента (ISO 8601) |
limit | запрос | Сколько записей вернуть, 1–200 (по умолчанию 50) |
cursor | запрос | next_cursor из предыдущего ответа |
Ответ 200
{
"data": [
{
"id": "9ea5407a0603f126bbe547928069239c",
"title": "Курс ухода",
"stage": "won",
"amount": 4900,
"notes": null,
"contact": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
},
"order_id": null,
"appointment_id": null,
"created_at": "2026-11-13T10:10:00.000Z",
"updated_at": "2026-11-13T11:00:00.000Z"
}
],
"next_cursor": "YzoxMjM0"
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
POST /v1/crm/deals
Создать сделку · право crm:write
Контакт — по contact_id или полями contact (найдём по телефону/почте или создадим). При исчерпанном лимите контактов сделка создаётся без контакта.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title обязательно | string | |
stage | string | По умолчанию new |
amount | number | null | |
notes | string | null | |
contact_id | string | Публичный id: 32 шестнадцатеричных символа |
contact | object |
{
"title": "Курс ухода",
"stage": "new",
"amount": 4900,
"contact": {
"name": "Вика",
"phone": "+79001234567"
}
}
Ответ 201
{
"data": {
"id": "9ea5407a0603f126bbe547928069239c",
"title": "Курс ухода",
"stage": "new",
"amount": 4900,
"notes": null,
"contact": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
},
"order_id": null,
"appointment_id": null,
"created_at": "2026-11-13T10:10:00.000Z",
"updated_at": "2026-11-13T11:00:00.000Z"
}
}
Ошибки
- 400 — Неверные поля
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Контакт не найден
GET /v1/crm/deals/{id}
Одна сделка · право crm:read
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id сделки |
Ответ 200
{
"data": {
"id": "9ea5407a0603f126bbe547928069239c",
"title": "Курс ухода",
"stage": "won",
"amount": 4900,
"notes": null,
"contact": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
},
"order_id": null,
"appointment_id": null,
"created_at": "2026-11-13T10:10:00.000Z",
"updated_at": "2026-11-13T11:00:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
PATCH /v1/crm/deals/{id}
Изменить сделку · право crm:write
| Параметр | Где | Описание |
|---|---|---|
id обязательно | путь | id сделки |
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
title | string | |
stage | string | |
amount | number | null | |
notes | string | null | |
contact_id | string | null | Публичный id: 32 шестнадцатеричных символа |
{
"stage": "won"
}
Ответ 200
{
"data": {
"id": "9ea5407a0603f126bbe547928069239c",
"title": "Курс ухода",
"stage": "won",
"amount": 4900,
"notes": null,
"contact": {
"id": "45e54a7f7c4b74942c83642581dc26c4",
"name": "Вика",
"phone": "+79001234567",
"email": "vika@example.com",
"telegram": "@vika",
"source": "api",
"created_at": "2026-11-13T10:00:00.000Z",
"updated_at": "2026-11-13T10:05:00.000Z"
},
"order_id": null,
"appointment_id": null,
"created_at": "2026-11-13T10:10:00.000Z",
"updated_at": "2026-11-13T11:00:00.000Z"
}
}
Ошибки
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 404 — Не найдена
Статистика
GET /v1/stats
Посещения и клики за период · право stats:read
Сводные цифры без отдельных визитов. Без параметров — последние 7 дней. Боты не учитываются.
| Параметр | Где | Описание |
|---|---|---|
period | запрос | today, yesterday, week, month или year |
from | запрос | Начало периода (до 366 дней) |
to | запрос | Конец периода |
surface | запрос | multi — мультиссылка (по умолчанию), website — сайт, all — всё |
Ответ 200
{
"data": {
"period": {
"kind": "week",
"from": null,
"to": null,
"days": null,
"granularity": "day",
"surface": "multi"
},
"totals": {
"visits": 1240,
"unique_visitors": 860,
"clicks": 312,
"unique_clicks": 240
},
"series": [
{
"t": "2026-11-12",
"hits": 180,
"unique_hits": 131,
"clicks": 44
}
],
"top_links": [
{
"url": "https://t.me/studio_anna",
"clicks": 120
}
],
"top_blocks": [
{
"block_id": "9db0cf42adc44b4e8c17bdede6b20a02",
"label": "Онлайн-запись",
"clicks": 96
}
],
"top_referrers": [
{
"referer": "instagram.com",
"cnt": 410
}
],
"top_geo": [
{
"country": "Россия",
"city": "Москва",
"cnt": 520
}
],
"utm": {
"sources": [
{
"value": "vk",
"hits": 210,
"uniqueHits": 160
}
],
"mediums": [],
"campaigns": [],
"combos": []
}
}
}
Ошибки
- 400 — Неверные параметры
- 402 — Тариф без API (ниже «Про») или исчерпан лимит тарифа
- 503 — Статистика временно недоступна