iPlanner

Для разработчиков

API и вебхуки iPlanner

Ваша CRM, сайт, Albato, n8n или своя программа читают из кабинета услуги, мастеров и свободное время, записывают клиентов и получают события о записях. Версия API — 1.0.0; адрес — https://iplanner.pro/api/v1.

Как получить ключ

Ключ выпускает владелец кабинета (или сотрудник с правом «API: выпускать и отзывать ключи») в разделе «Настройки → API и доступы». Внешний API работает на оплаченном тарифе, в который он входит. Модуль «API и доступы» должен быть в тарифе и не выключен, кабинет и сотрудник, выпустивший ключ, — не заблокированы. Пробный период не считается оплатой.

Секретный ключ начинается с ipk_live_ и показывается один раз. Он действует от имени выпустившего: при выпуске отмечаются права, и ключ получает пересечение отмеченного с текущими правами этого человека. Сняли право — ключ потерял его сразу. Перестали платить или кабинет заблокирован — запросы получают 403, но ключи не удаляются и заработают снова без перевыпуска.

Права ключа

Без отмеченных прав ключ читает то, что и так видно на витрине: компанию, услуги, мастеров, свободное время и условия записи.

  • journal.view.all — Записи кабинета: читать

    Список записей и запись по номеру (GET /bookings, /bookings/{id}), кто работает в день и рабочие места (GET /shifts, /places), проведённые приходы склада (GET /stock-receipts).

  • clients.view — Имя и телефон клиента

    В записях появляются имя и телефон клиента. Без этого права — только номер клиента.

  • appointments.manage — Записи: создавать, переносить, отменять

    Удержание времени и запись клиента (POST /reservations, POST /bookings), перенос и отмена записи (PUT и DELETE /bookings/{id}).

  • tasks.view — Задачи: ставить

    Новая задача в разделе «Задачи» кабинета (POST /tasks): название, описание, исполнитель и срок.

Вход и лимиты

Ключ передаётся в каждом запросе заголовком Authorization: Bearer …. Нет ключа, ключ отозван или неверный — 401.

curl https://iplanner.pro/api/v1/companies \
  -H "Authorization: Bearer ipk_live_…"

Лимит частоты — 120 запросов за 60 с на ключ и 300 на кабинет целиком (все его ключи вместе). Превышение — 429 с заголовком Retry-After: через сколько секунд повторить.

Все даты-время — ISO 8601 в UTC; дни (ГГГГ-ММ-ДД) и подписи времени — в поясе компании (timezone в ответе /companies). Деньги — целые копейки в полях …Minor.

В версии 1 API только дополняется: новые поля, ручки, значения перечислений и события. Незнакомые поля и значения принимайте молча.

Ручки

GET/companies

Компания ключа

Кабинет с адресом. У сети кабинетов список пуст: сеть компанией не бывает.

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

curl -X GET "https://iplanner.pro/api/v1/companies" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (CompanyList)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "name": "Анна",
      "type": "individual",
      "address": "ул. Ленина, 1",
      "city": "Пермь",
      "location": {
        "lat": 58.01,
        "lng": 56.25
      },
      "timezone": "Europe/Moscow",
      "currency": "RUB",
      "storefront": {
        "url": "текст",
        "qrUrl": "текст",
        "accentColor": "текст",
        "logoUrl": "текст"
      }
    }
  ]
}

Отказы: 400, 401, 403, 429 — коды в разделе «Ошибки и коды».

GET/services

Услуги с онлайн-записью

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
curl -X GET "https://iplanner.pro/api/v1/services" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (ServiceList)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "companyId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "title": "Маникюр с покрытием",
      "category": "Ногти",
      "description": "текст",
      "durationMinutes": 60,
      "price": {
        "amountMinor": 250000,
        "currency": "RUB",
        "isFrom": true
      },
      "resourceIds": [
        "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704"
      ]
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/resources

Мастера, принимающие онлайн-запись

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
serviceIdstring, uuid, в строке запроса
Только те, кто оказывает эту услугу.
curl -X GET "https://iplanner.pro/api/v1/resources" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (ResourceList)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "companyId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "name": "Анна",
      "headline": "Мастер маникюра",
      "avatarUrl": "текст",
      "services": [
        {
          "serviceId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
          "durationMinutes": 60,
          "price": {}
        }
      ]
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/available-dates

Дни со свободным временем

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
resourceIdstring, uuid, в строке запроса, обязательный
Мастер (id из /resources).
serviceIdsstring, в строке запроса, обязательный
Услуги визита через запятую, в порядке исполнения (id из /services).
curl -X GET "https://iplanner.pro/api/v1/available-dates" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (AvailableDates)

{
  "resourceId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "serviceIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "timezone": "Europe/Moscow",
  "dates": [
    "2026-10-01"
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/available-slots

Свободное время на день

Считается той же функцией, что витрина: порог записи, горизонт, перерывы и прилипание — как у клиента на сайте.

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
resourceIdstring, uuid, в строке запроса, обязательный
Мастер (id из /resources).
serviceIdsstring, в строке запроса, обязательный
Услуги визита через запятую, в порядке исполнения (id из /services).
datestring, date, в строке запроса, обязательный
День в поясе компании, ГГГГ-ММ-ДД.
curl -X GET "https://iplanner.pro/api/v1/available-slots" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (AvailableSlots)

{
  "resourceId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "serviceIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "date": "2026-10-01",
  "timezone": "Europe/Moscow",
  "durationMinutes": 60,
  "slots": [
    {
      "start": "2026-10-01T07:30:00.000Z",
      "label": "10:30"
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/booking-conditions

Условия записи

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
curl -X GET "https://iplanner.pro/api/v1/booking-conditions" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (BookingConditions)

{
  "companyId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "personalDataConsentRequired": true,
  "prepayment": {
    "mode": "percent",
    "percent": 1,
    "amountMinor": 250000,
    "currency": "RUB",
    "forAllClients": true,
    "forNewClients": true,
    "forFlaggedServices": true,
    "minPriceMinor": 250000,
    "terms": "текст",
    "offerConsentRequired": true
  },
  "resources": [
    {
      "resourceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "onlineBooking": true,
      "audience": "everyone",
      "horizonDays": 30,
      "minNoticeMinutes": 60,
      "sameDayBooking": true,
      "slotStepMinutes": 60
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/shifts

Кто работает в день

Все сотрудники компании, не только с онлайн-записью, и их рабочее время в этот день: график с учётом отгулов и доп. смен. Пустые spans — в этот день не работает. Отрезков может быть несколько (смена с перерывом).

Право ключа: `journal.view.all` (Записи кабинета: читать).

Право ключа: journal.view.all — Записи кабинета: читать.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
datestring, date, в строке запроса
День в поясе компании, ГГГГ-ММ-ДД. По умолчанию — сегодня.
curl -X GET "https://iplanner.pro/api/v1/shifts" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (ShiftDay)

{
  "companyId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "date": "2026-10-01",
  "timezone": "Europe/Moscow",
  "items": [
    {
      "resourceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "name": "Анна",
      "avatarUrl": "текст",
      "role": "owner",
      "spans": [
        {
          "start": "2026-10-01T07:30:00.000Z",
          "end": "2026-10-01T07:30:00.000Z"
        }
      ]
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/places

Рабочие места

Кресла, кабинеты и аппараты компании. Место записи — placeId в записи.

Право ключа: `journal.view.all` (Записи кабинета: читать).

Право ключа: journal.view.all — Записи кабинета: читать.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
curl -X GET "https://iplanner.pro/api/v1/places" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (PlaceList)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "companyId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "name": "Анна",
      "kind": "chair"
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/bookings

Записи компании

По времени начала, курсором. Перенесённая запись приходит один раз — действующей версией. Имя и телефон клиента — только с правом clients.view.

Право ключа: `journal.view.all` (Записи кабинета: читать).

Право ключа: journal.view.all — Записи кабинета: читать.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
fromstring, date, в строке запроса
Первый день, ГГГГ-ММ-ДД в поясе компании. По умолчанию — сегодня.
tostring, date, в строке запроса
Последний день включительно. По умолчанию — 30 дней от from, не больше 93.
cursorstring, в строке запроса
nextCursor из предыдущей страницы.
limitinteger, 1–200, в строке запроса
Записей на странице: 1–200, по умолчанию 50.
curl -X GET "https://iplanner.pro/api/v1/bookings" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (BookingPage)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "previousIds": [
        "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
      ],
      "companyId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
      "resourceId": "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53",
      "placeId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "status": "pending",
      "cancelledBy": "client",
      "cancelledAt": "2026-10-01T07:30:00.000Z",
      "start": "2026-10-01T07:30:00.000Z",
      "end": "2026-10-01T07:30:00.000Z",
      "services": [
        {
          "serviceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
          "title": "Маникюр с покрытием",
          "durationMinutes": 60,
          "price": {}
        }
      ],
      "price": {
        "totalMinor": 250000,
        "discountMinor": 0,
        "paidMinor": 0,
        "currency": "RUB"
      },
      "prepayment": {
        "status": "none",
        "requiredMinor": 250000
      },
      "channel": "online",
      "tag": "instagram",
      "client": {
        "id": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
        "birthdayToday": true,
        "name": "Анна",
        "phone": "+79001234567"
      },
      "productsCount": 1,
      "createdAt": "2026-10-01T07:30:00.000Z",
      "updatedAt": "2026-10-01T07:30:00.000Z"
    }
  ],
  "nextCursor": "текст"
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

POST/bookings

Записать клиента

Из удержания (reservationId — запись получит его id) или сразу на время из /available-slots. Правила — те же, что у записи с сайта: согласие, доступ «только клиенты», лимит записей, предоплата. Запись ждёт подтверждения мастера (status pending). Имя и телефон клиента в ответе — только с правом clients.view.

Право ключа: `appointments.manage` (Записи: создавать, переносить, отменять).

Право ключа: appointments.manage — Записи: создавать, переносить, отменять.

Параметры

Idempotency-Keystring, заголовок, обязательный
Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.

Тело запроса (BookingCreate)

reservationIdstring, uuid, в теле
Удержание из POST /reservations. С ним resourceId, serviceIds и start не нужны.
resourceIdstring, uuid, в теле
serviceIdsarray, в теле
startstring, date-time, в теле
clientobject, в теле, обязательный
consentobject, в теле, обязательный
promoCodestring, в теле
tagstring, в теле
Метка вашей системы; по умолчанию api (у записи из удержания — метка удержания).
curl -X POST "https://iplanner.pro/api/v1/bookings" \
  -H "Authorization: Bearer ipk_live_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ … }'

Пример тела

{
  "reservationId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "resourceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
  "serviceIds": [
    "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704"
  ],
  "start": "2026-10-01T07:30:00.000Z",
  "client": {
    "name": "Анна",
    "phone": "+79001234567"
  },
  "consent": {
    "personalData": true,
    "offer": true
  },
  "promoCode": "AUTUMN10",
  "tag": "instagram"
}

Ответ 201 (Booking)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "previousIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "companyId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
  "resourceId": "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53",
  "placeId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "status": "pending",
  "cancelledBy": "client",
  "cancelledAt": "2026-10-01T07:30:00.000Z",
  "start": "2026-10-01T07:30:00.000Z",
  "end": "2026-10-01T07:30:00.000Z",
  "services": [
    {
      "serviceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "title": "Маникюр с покрытием",
      "durationMinutes": 60,
      "price": {
        "amountMinor": 250000,
        "currency": "RUB"
      }
    }
  ],
  "price": {
    "totalMinor": 250000,
    "discountMinor": 0,
    "paidMinor": 0,
    "currency": "RUB"
  },
  "prepayment": {
    "status": "none",
    "requiredMinor": 250000
  },
  "channel": "online",
  "tag": "instagram",
  "client": {
    "id": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
    "birthdayToday": true,
    "name": "Анна",
    "phone": "+79001234567"
  },
  "productsCount": 1,
  "createdAt": "2026-10-01T07:30:00.000Z",
  "updatedAt": "2026-10-01T07:30:00.000Z"
}

Отказы: 400, 401, 403, 404, 409, 422, 429 — коды в разделе «Ошибки и коды».

GET/bookings/{id}

Запись по id

Прежний id после переноса ведёт к действующей версии: в ответе её id и previousIds.

Право ключа: `journal.view.all` (Записи кабинета: читать).

Право ключа: journal.view.all — Записи кабинета: читать.

Параметры

idstring, uuid, в пути, обязательный
id записи, в том числе прежний.
curl -X GET "https://iplanner.pro/api/v1/bookings/:id" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (Booking)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "previousIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "companyId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
  "resourceId": "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53",
  "placeId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "status": "pending",
  "cancelledBy": "client",
  "cancelledAt": "2026-10-01T07:30:00.000Z",
  "start": "2026-10-01T07:30:00.000Z",
  "end": "2026-10-01T07:30:00.000Z",
  "services": [
    {
      "serviceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "title": "Маникюр с покрытием",
      "durationMinutes": 60,
      "price": {
        "amountMinor": 250000,
        "currency": "RUB"
      }
    }
  ],
  "price": {
    "totalMinor": 250000,
    "discountMinor": 0,
    "paidMinor": 0,
    "currency": "RUB"
  },
  "prepayment": {
    "status": "none",
    "requiredMinor": 250000
  },
  "channel": "online",
  "tag": "instagram",
  "client": {
    "id": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
    "birthdayToday": true,
    "name": "Анна",
    "phone": "+79001234567"
  },
  "productsCount": 1,
  "createdAt": "2026-10-01T07:30:00.000Z",
  "updatedAt": "2026-10-01T07:30:00.000Z"
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

PUT/bookings/{id}

Перенести запись

Новое начало и/или другой мастер. Те же правила, что у клиента по ссылке из напоминания: окно правки до визита, запас до визита, закрытый визит не переносится. В ответе — новая версия записи, прежний id — в previousIds.

Право ключа: `appointments.manage` (Записи: создавать, переносить, отменять).

Право ключа: appointments.manage — Записи: создавать, переносить, отменять.

Параметры

idstring, uuid, в пути, обязательный
id записи, в том числе прежний: ведём к действующей версии.
Idempotency-Keystring, заголовок, обязательный
Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.

Тело запроса (BookingUpdate)

startstring, date-time, в теле
resourceIdstring, uuid, в теле
Другой мастер компании, оказывающий все услуги записи.
curl -X PUT "https://iplanner.pro/api/v1/bookings/:id" \
  -H "Authorization: Bearer ipk_live_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ … }'

Пример тела

{
  "start": "2026-10-01T07:30:00.000Z",
  "resourceId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90"
}

Ответ 200 (Booking)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "previousIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "companyId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
  "resourceId": "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53",
  "placeId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "status": "pending",
  "cancelledBy": "client",
  "cancelledAt": "2026-10-01T07:30:00.000Z",
  "start": "2026-10-01T07:30:00.000Z",
  "end": "2026-10-01T07:30:00.000Z",
  "services": [
    {
      "serviceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "title": "Маникюр с покрытием",
      "durationMinutes": 60,
      "price": {
        "amountMinor": 250000,
        "currency": "RUB"
      }
    }
  ],
  "price": {
    "totalMinor": 250000,
    "discountMinor": 0,
    "paidMinor": 0,
    "currency": "RUB"
  },
  "prepayment": {
    "status": "none",
    "requiredMinor": 250000
  },
  "channel": "online",
  "tag": "instagram",
  "client": {
    "id": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
    "birthdayToday": true,
    "name": "Анна",
    "phone": "+79001234567"
  },
  "productsCount": 1,
  "createdAt": "2026-10-01T07:30:00.000Z",
  "updatedAt": "2026-10-01T07:30:00.000Z"
}

Отказы: 400, 401, 403, 404, 409, 422, 429 — коды в разделе «Ошибки и коды».

DELETE/bookings/{id}

Отменить запись

Отмена от имени клиента (cancelledBy: client) по тем же правилам, что по ссылке из напоминания. Отменённая уже — не ошибка.

Право ключа: `appointments.manage` (Записи: создавать, переносить, отменять).

Право ключа: appointments.manage — Записи: создавать, переносить, отменять.

Параметры

idstring, uuid, в пути, обязательный
id записи, в том числе прежний: ведём к действующей версии.
Idempotency-Keystring, заголовок, обязательный
Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.
curl -X DELETE "https://iplanner.pro/api/v1/bookings/:id" \
  -H "Authorization: Bearer ipk_live_…" \
  -H "Idempotency-Key: $(uuidgen)"

Ответ 200 (Booking)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "previousIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "companyId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
  "resourceId": "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53",
  "placeId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "status": "pending",
  "cancelledBy": "client",
  "cancelledAt": "2026-10-01T07:30:00.000Z",
  "start": "2026-10-01T07:30:00.000Z",
  "end": "2026-10-01T07:30:00.000Z",
  "services": [
    {
      "serviceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "title": "Маникюр с покрытием",
      "durationMinutes": 60,
      "price": {
        "amountMinor": 250000,
        "currency": "RUB"
      }
    }
  ],
  "price": {
    "totalMinor": 250000,
    "discountMinor": 0,
    "paidMinor": 0,
    "currency": "RUB"
  },
  "prepayment": {
    "status": "none",
    "requiredMinor": 250000
  },
  "channel": "online",
  "tag": "instagram",
  "client": {
    "id": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
    "birthdayToday": true,
    "name": "Анна",
    "phone": "+79001234567"
  },
  "productsCount": 1,
  "createdAt": "2026-10-01T07:30:00.000Z",
  "updatedAt": "2026-10-01T07:30:00.000Z"
}

Отказы: 400, 401, 403, 404, 409, 422, 429 — коды в разделе «Ошибки и коды».

POST/reservations

Удержать время

Держит слот, пока клиент заполняет вашу форму: запись с сайта или из кабинета на это время получит отказ базы. Правила те же, что у записи с сайта (онлайн-запись, запас до визита, места). Снимается само по expiresAt.

Право ключа: `appointments.manage` (Записи: создавать, переносить, отменять).

Право ключа: appointments.manage — Записи: создавать, переносить, отменять.

Параметры

Idempotency-Keystring, заголовок, обязательный
Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.

Тело запроса (ReservationCreate)

resourceIdstring, uuid, в теле, обязательный
serviceIdsarray, в теле, обязательный
Услуги визита в порядке исполнения, от 1 до 20.
startstring, date-time, в теле, обязательный
holdMinutesinteger, 1–30, в теле
Срок удержания; по умолчанию 10 минут, не больше 30.
tagstring, в теле
Метка вашей системы (a–z, 0–9, _ и -, до 32 знаков) — видна в «Хронологии» и отчётах. По умолчанию api.
curl -X POST "https://iplanner.pro/api/v1/reservations" \
  -H "Authorization: Bearer ipk_live_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ … }'

Пример тела

{
  "resourceId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "serviceIds": [
    "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15"
  ],
  "start": "2026-10-01T07:30:00.000Z",
  "holdMinutes": 60,
  "tag": "instagram"
}

Ответ 201 (Reservation)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "companyId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
  "resourceId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
  "serviceIds": [
    "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53"
  ],
  "start": "2026-10-01T07:30:00.000Z",
  "expiresAt": "2026-10-01T07:30:00.000Z"
}

Отказы: 400, 401, 403, 404, 409, 422, 429 — коды в разделе «Ошибки и коды».

DELETE/reservations/{id}

Снять удержание

Время освобождается сразу. Снятое уже — не ошибка. Удержание, ставшее записью, отменяйте как запись.

Право ключа: `appointments.manage` (Записи: создавать, переносить, отменять).

Право ключа: appointments.manage — Записи: создавать, переносить, отменять.

Параметры

idstring, uuid, в пути, обязательный
id удержания.
Idempotency-Keystring, заголовок, обязательный
Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.
curl -X DELETE "https://iplanner.pro/api/v1/reservations/:id" \
  -H "Authorization: Bearer ipk_live_…" \
  -H "Idempotency-Key: $(uuidgen)"

Ответ 200 (ReservationRelease)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "released": true
}

Отказы: 400, 401, 403, 404, 409, 422, 429 — коды в разделе «Ошибки и коды».

GET/reviews

Новые отзывы

Опубликованные отзывы компании с начала дня from, свежие первыми, не больше 200. Только то, что видно на витрине: скрытых нет, а если витрина студии прячет блок отзывов — список пуст. Текста и автора нет — оценка, мастер и время.

Хватает действующего ключа допущенного кабинета.

Хватает действующего ключа.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
fromstring, date, в строке запроса
С какого дня, ГГГГ-ММ-ДД в поясе компании. По умолчанию — сегодня.
curl -X GET "https://iplanner.pro/api/v1/reviews" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (ReviewList)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "resourceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
      "rating": 1,
      "createdAt": "2026-10-01T07:30:00.000Z"
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

GET/stock-receipts

Приход материалов

Проведённые приходы склада с начала дня from, свежие первыми, не больше 200: время проведения и число строк. Отменённые не отдаются. Названий и денег нет. Нет модуля «Склад» в тарифе — пустой список.

Право ключа: `journal.view.all` (Записи кабинета: читать).

Право ключа: journal.view.all — Записи кабинета: читать.

Параметры

companyIdstring, uuid, в строке запроса
Компания ключа. Можно не передавать: ключ принадлежит одной компании; чужой id — 404.
fromstring, date, в строке запроса
С какого дня, ГГГГ-ММ-ДД в поясе компании. По умолчанию — сегодня.
curl -X GET "https://iplanner.pro/api/v1/stock-receipts" \
  -H "Authorization: Bearer ipk_live_…"

Ответ 200 (StockReceiptList)

{
  "items": [
    {
      "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
      "postedAt": "2026-10-01T07:30:00.000Z",
      "lines": 1
    }
  ]
}

Отказы: 400, 401, 403, 404, 429 — коды в разделе «Ошибки и коды».

POST/tasks

Поставить задачу

Задача появляется в разделе «Задачи» кабинета от имени сотрудника, выпустившего ключ. Правила — те же, что у формы: исполнитель только из состава компании и получает уведомление. Модуля «Задачи» нет в тарифе — 403 not_in_plan.

Право ключа: `tasks.view` (Задачи: ставить).

Право ключа: tasks.view — Задачи: ставить.

Параметры

Idempotency-Keystring, заголовок, обязательный
Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.

Тело запроса (TaskCreate)

titlestring, в теле, обязательный
Что нужно сделать: от 2 до 200 знаков.
descriptionstring, в теле
Комментарий, до 2000 знаков.
assigneeResourceIdstring, uuid, в теле
Исполнитель — действующий сотрудник компании (resourceId из /shifts). У мастера-одиночки не ставится.
dueDatestring, date, в теле
Срок, ГГГГ-ММ-ДД.
curl -X POST "https://iplanner.pro/api/v1/tasks" \
  -H "Authorization: Bearer ipk_live_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ … }'

Пример тела

{
  "title": "Маникюр с покрытием",
  "description": "текст",
  "assigneeResourceId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "dueDate": "2026-10-01"
}

Ответ 201 (Task)

{
  "id": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "title": "Маникюр с покрытием",
  "assigneeResourceId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
  "dueDate": "2026-10-01",
  "createdAt": "2026-10-01T07:30:00.000Z"
}

Отказы: 400, 401, 403, 404, 409, 422, 429 — коды в разделе «Ошибки и коды».

GET/events

Каталог событий

Типы событий, которые уходят вебхуком. Формы данных — в разделе webhooks этого описания.

Ключ не нужен.

Ключ не нужен.

curl -X GET "https://iplanner.pro/api/v1/events"

Ответ 200 (EventList)

{
  "items": [
    {
      "type": "текст",
      "event": "текст",
      "label": "10:30",
      "description": "текст",
      "dataVersion": "текст"
    }
  ]
}

Повтор запроса: Idempotency-Key

Ручки, которые меняют данные (POST /bookings, PUT /bookings/{id}, DELETE /bookings/{id}, POST /reservations, DELETE /reservations/{id}, POST /tasks), требуют заголовок Idempotency-Key. Сеть оборвалась, ответ не дошёл — повторите запрос с тем же ключом: вторая запись не появится.

Уникальная строка на каждую попытку (например, UUID), до 255 знаков ASCII. Повтор с тем же ключом и тем же телом отдаёт сохранённый ответ и второй раз ничего не делает; с другим телом — 409 idempotency_conflict. Ключ живёт сутки.

  • 409 idempotency_conflict — Этот ключ идемпотентности уже использован с другим запросом
  • 409 idempotency_in_progress — Такой же запрос уже выполняется. Повторите чуть позже.

Ошибки и коды

Отказ приходит телом { code, message, details? }. Различайте причины по code, а не по тексту: текст — для человека и может меняться. Незнакомый код обрабатывайте по HTTP-статусу. Непредвиденная ошибка сервера — 500 с тем же форматом тела; повторите позже.

{
  "code": "slot_taken",
  "message": "Это время только что заняли. Выберите другое окно."
}

400 — ошибка в запросе

  • consent_required — Отметьте согласие на обработку персональных данных
  • invalid_input — Проверьте заполнение формы
  • offer_consent_required — Отметьте согласие с условиями предоплаты и возврата

401 — ключ не принят

  • api_key_invalid — Ключ API не принят: нет, отозван или неверный

403 — нет доступа или права

  • actor_blocked — Доступ этого сотрудника закрыт
  • cabinet_blocked — Кабинет заблокирован
  • denied — Недостаточно прав
  • not_for_node — В этом кабинете раздел недоступен
  • not_in_plan — Не входит в ваш тариф
  • past_locked — Записи прошлых дней правит только владелец или тот, кому он дал право «Записи прошлых дней: править»
  • plan_not_paid — Работает только на оплаченном тарифе

404 — не найдено

  • not_found — Не найдено
  • not_offered — Такого раздела нет

409 — конфликт: время заняли, удержание истекло, ключ идемпотентности

  • failed — Не удалось выполнить. Попробуйте ещё раз.
  • hold_expired — Время удержания слота вышло. Выберите время заново.
  • idempotency_conflict — Этот ключ идемпотентности уже использован с другим запросом
  • idempotency_in_progress — Такой же запрос уже выполняется. Повторите чуть позже.
  • place_taken — Это место уже занято в это время. Выберите другое кресло или время.
  • slot_taken — Это время только что заняли. Выберите другое окно.
  • slot_unavailable — На это время записаться нельзя — выберите одно из свободных окон.

422 — правило записи не пускает

  • bot — Не удалось записаться, попробуйте ещё раз.
  • change_closed — Изменить запись уже нельзя — свяжитесь с мастером
  • client_blocked — Клиент заблокирован в этом кабинете
  • client_online_closed — Онлайн-запись сейчас недоступна — позвоните, пожалуйста, в студию
  • discount_rejected — Скидка не применима
  • limit_exceeded — На этот номер уже есть несколько предстоящих записей. Свяжитесь с мастером напрямую.
  • online_closed — Мастер сейчас не принимает онлайн-запись
  • stranger — Онлайн-запись — только для клиентов
  • too_soon — Пока рано для записи — выберите время позже

429 — слишком часто

  • rate_limited — Слишком много запросов. Повторите позже.

Вебхуки

События кабинета уходят POST-запросом на ваш адрес. Подключение — в «Настройки → Интеграции», карточка «Свой вебхук»: адрес (только https), галочки нужных событий. Секрет подписи (whsec_…) показывается один раз при подключении. Вебхуки работают на оплаченном тарифе с модулем «Интеграции»; пока кабинет не допущен, события не уходят и потом не досылаются.

Формат — CloudEvents 1.0

Тело — конверт CloudEvents (application/cloudevents+json), его без переводчика понимают Albato, n8n, Make и большинство приёмников событий. type — тип события из каталога ниже, subject — id записи, id уникален навсегда: по нему отбивайте повторы. Версия формы данных — dataversion (1).

{
  "specversion": "1.0",
  "id": "7d0b3e6a-2c51-4f8e-9a14-6b3d2e8c0f71",
  "type": "ru.iplanner.appointment.created",
  "source": "/workspaces/9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
  "subject": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
  "time": "2026-10-01T07:31:12.000Z",
  "datacontenttype": "application/json",
  "dataversion": "1",
  "data": {
    "appointmentId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
    "previousId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
    "status": "confirmed",
    "startsAt": "2026-10-01T07:30:00.000Z",
    "endsAt": "2026-10-01T07:30:00.000Z",
    "professionalId": "c41d8e03-7b6a-4e29-8f15-a3d2c6b9e704",
    "previousProfessionalId": "5e8a2f71-0c4d-4b96-a1e3-7f2b9d6c8a53",
    "previousStartsAt": "2026-10-01T07:30:00.000Z",
    "resourceId": "3f6c1a52-8d1e-4c3b-9a0f-2b7e5d4c1a90",
    "clientId": "9b2e7d14-5a3c-4f81-b6d2-0c9e8a7f3b15",
    "priceTotalMinor": 250000,
    "discountMinor": 0,
    "paidMinor": 0,
    "prepayStatus": "none",
    "source": "online",
    "srcTag": "instagram",
    "cancelledBy": "client",
    "changed": [
      "priceTotalMinor"
    ]
  }
}

Подпись — Standard Webhooks

Каждый запрос подписан по стандарту Standard Webhooks: заголовки webhook-id, webhook-timestamp, webhook-signature (HMAC-SHA256). Проверяйте готовой библиотекой standardwebhooks — она есть для JS, Python, Go, PHP и других языков — по сырому телу запроса, до разбора JSON. Запрос старше 5 минут библиотека отвергнет.

JavaScript (Node.js, Express)

// npm install standardwebhooks express
import express from 'express';
import { Webhook } from 'standardwebhooks';

const wh = new Webhook(process.env.IPLANNER_WEBHOOK_SECRET); // whsec_…
const app = express();

// сырое тело: подпись считается по байтам, а не по разобранному JSON
app.post('/hooks/iplanner', express.raw({ type: '*/*' }), (req, res) => {
  let event;
  try {
    event = wh.verify(req.body.toString('utf8'), req.headers);
  } catch {
    return res.sendStatus(400); // подпись не сошлась или запрос устарел
  }
  // event.id — отбивайте повторы; event.type — ru.iplanner.appointment.…
  res.sendStatus(204);
  handle(event); // тяжёлую работу — после ответа
});

Python (Flask)

# pip install standardwebhooks flask
import os
from flask import Flask, request
from standardwebhooks.webhooks import Webhook

wh = Webhook(os.environ["IPLANNER_WEBHOOK_SECRET"])  # whsec_…
app = Flask(__name__)

@app.post("/hooks/iplanner")
def iplanner():
    try:
        event = wh.verify(request.get_data(), dict(request.headers))
    except Exception:
        return "", 400  # подпись не сошлась или запрос устарел
    # event["id"] — отбивайте повторы; event["type"] — ru.iplanner.appointment.…
    handle(event)
    return "", 204

Повторы

Успех — любой ответ 2xx. Любой другой ответ, таймаут или обрыв — повтор по расписанию (пауза перед каждой попыткой): сразу → 5 с → 5 мин → 30 мин → 2 ч → 5 ч → 10 ч → 10 ч. Всего около 27 ч 35 мин; после этого событие считается недоставленным. Приёмник, который долго не отвечает, помечается сломанным — владелец кабинета увидит это в карточке подключения.

Порядок доставки не гарантирован, повтор возможен и после успеха: сверяйте id и время события. Отвечайте быстро, тяжёлую работу делайте после ответа. Проверить связь — кнопкой в карточке подключения: придёт событие ru.iplanner.ping с той же подписью.

Каталог событий

Тот же список отдаёт без ключа /api/v1/events. Список только растёт: новое событие не придёт, пока вы не отметите его в подключении.

  • Новая запись

    ru.iplanner.appointment.created

    Запись создана — с витрины, из кабинета, через API или виджет. Перенос сюда не относится.

  • Запись перенесена

    ru.iplanner.appointment.rescheduled

    Время записи изменилось. У перенесённой записи новый id, прежний — в previousId.

  • Запись передана другому мастеру

    ru.iplanner.appointment.reassigned

    Сменился мастер (и, возможно, время). Прежний мастер — в previousProfessionalId.

  • Запись подтверждена

    ru.iplanner.appointment.confirmed

    Мастер или администратор подтвердил запись.

  • Клиент пришёл

    ru.iplanner.appointment.started

    Визит начался — клиент на месте.

  • Визит завершён

    ru.iplanner.appointment.completed

    Визит закрыт — вручную или автоматически по окончании времени.

  • Запись отменена

    ru.iplanner.appointment.cancelled

    Запись отменена клиентом, мастером или системой (например, не внесена предоплата). Кто отменил — в cancelledBy.

  • Клиент не пришёл

    ru.iplanner.appointment.no_show

    Визит отмечен неявкой.

  • Запись удалена

    ru.iplanner.appointment.deleted

    Запись убрана из раздела «Записи». Время освобождено.

  • Запись возвращена в работу

    ru.iplanner.appointment.reopened

    Отменённая, удалённая или отмеченная неявкой запись снова действует.

  • Предоплата получена

    ru.iplanner.appointment.prepaid

    По записи отмечена полученная предоплата.

  • Запись изменена

    ru.iplanner.appointment.updated

    Изменились состав, сумма, скидка, оплата, место или клиент записи. Какие поля — в changed.

Персональные данные

В событиях имени и телефона клиента нет. Снимок записи в событии. Имени и телефона клиента нет — только clientId. По clientId и id записи вы запрашиваете подробности через API.

В API имя и телефон клиента есть только у ключа с правом clients.view («Имя и телефон клиента»). В записях появляются имя и телефон клиента. Без этого права — только номер клиента. Отмечайте это право, только если ваша система действительно должна знать клиента, и храните полученное по правилам 152-ФЗ.

OpenAPI

Машиночитаемое описание — OpenAPI 3.1, открыто без ключа: /api/v1/openapi.json. Его можно загрузить в Postman, Insomnia или генератор клиента. Эта страница и описание собираются из одного источника и не расходятся.