API Qronika

API позволяет вашей CRM, сайту или внутренней системе работать с QR-кодами и папками без ручных действий в кабинете.

Доступ

API доступен на тарифах Business и Enterprise и работает с данными аккаунта или выбранной команды. Данные разных команд изолированы. Выпускать ключи и управлять ими может владелец или администратор пространства. Ключ выполняет только действия, разрешённые его scopes; редакторская роль сама по себе не даёт права выпускать ключи.

Как выпустить ключ

  1. Откройте «API-ключи» в меню аккаунта.
  2. Переключитесь в нужный контекст.
  3. Укажите понятное название и выберите разрешения на просмотр или изменение QR-кодов, папок и аналитики.
  4. Скопируйте секрет сразу: повторно он не показывается.

Ответы и повтор запросов

Проверяйте HTTP-статус и JSON-ответ перед повтором запроса. Списки возвращаются постранично, частота запросов ограничена. Для безопасного повтора POST /qr-codes используйте заголовок Idempotency-Key. На создание папок и другие методы эта защита не распространяется.

Отзыв доступа

Отозванный ключ перестаёт работать сразу. При удалении команды все её ключи также перестают работать.

Начало работы

export API_BASE="https://qronika.ru/api/v1"
export API_KEY="YOUR_API_KEY"
export IDEMPOTENCY_KEY="unique-request-0001"

Все запросы выполняются через HTTPS. Подставьте адрес сервиса в API_BASE (с /api/v1), секрет — в API_KEY. QR_ID, FOLDER_ID и USER_ID в примерах обозначают UUID. Полный ключ доступен только при выпуске; не вставляйте его в публичный код.

Для чтения: qr:read, папок: folders:read, статистики: analytics:read. Изменения QR требуют qr:write, изменения папок и перемещение — folders:write. Создавайте ключ с минимально необходимыми разрешениями.

Один ключ допускает 120 запросов в минуту. При 429 дождитесь Retry-After (секунды). API требует Business или Enterprise на каждом запросе: при окончании доступа возвращается 403 api_unavailable, ключи сохраняются. После восстановления тарифа действующий ключ снова работает.

Как избежать повторного создания QR

Для POST /qr-codes передайте Idempotency-Key длиной 8–128 символов: латинские буквы, цифры и знаки ._:-. Без заголовка или с пустым значением запрос также принимается, но каждый повтор может создать ещё один QR.

Защита действует 24 часа и относится к конкретному API-ключу. Повторите тот же JSON с тем же ключом идемпотентности и тем же API-ключом: получите сохранённый результат. Не меняйте типы значений и порядок полей. Другое тело с тем же ключом даёт 409 idempotency_conflict.

При таймауте не создавайте новый ключ идемпотентности и не переключайтесь на другой API-ключ: первый запрос мог уже завершиться. После 24 часов прежний ключ может создать новый QR, поэтому сначала сверьте результат предыдущей операции. Для самостоятельной новой операции используйте новый ключ.

Пагинация QR: page по умолчанию 1, per_page — 20. Целый размер страницы ограничивается диапазоном 1–100; неверное значение использует 20. Страница за концом списка возвращает пустой массив. Фильтры: folder_id, type, mode, search. Список папок возвращается целиком.

Для перемещения folder_id обязателен: UUID выбирает папку, null переносит QR в корень. Создание QR использует поле названия qr_name, обновление — name; при PATCH название обязательно. Для динамического QR передавайте также новое содержимое соответствующего типа либо строковый destination_url.

Ключ действует календарный год. За 7 дней до окончания появляется «Продлить на год». Приостановка обратима и не освобождает лимит, отзыв окончателен. Название можно менять без изменения секрета.

Примеры ответов иллюстративные: реальные ID, даты и счётчики будут другими. Для запросов с удалением используйте тестовые объекты. 204 означает успешное выполнение без тела ответа.

Список QR-кодов

GET /qr-codes?page=1&per_page=20 · Разрешение: qr:read

curl -i -X GET "$API_BASE/qr-codes?page=1&per_page=20" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"
HTTP 200
{
  "data": [
    {
      "id": "QR_ID",
      "name": "CRM",
      "type": "url",
      "mode": "dynamic",
      "folder_id": null,
      "destination_url": "https://example.com",
      "scan_count": 0,
      "created_at": "2026-10-15 10:00:00"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "pages": 1
  }
}

Создать QR-код

POST /qr-codes · Разрешение: qr:write

curl -i -X POST "$API_BASE/qr-codes" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --data '{"qr_name": "CRM", "type": "url", "mode": "dynamic", "value": "https://example.com"}'
HTTP 201
{
  "data": {
    "id": "QR_ID",
    "name": "CRM",
    "type": "url",
    "mode": "dynamic",
    "folder_id": null,
    "destination_url": "https://example.com",
    "scan_count": 0,
    "created_at": "2026-10-15 10:00:00"
  }
}

Получить QR-код

GET /qr-codes/QR_ID · Разрешение: qr:read

curl -i -X GET "$API_BASE/qr-codes/QR_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"
HTTP 200
{
  "data": {
    "id": "QR_ID",
    "name": "CRM",
    "type": "url",
    "mode": "dynamic",
    "folder_id": null,
    "destination_url": "https://example.com",
    "scan_count": 0,
    "created_at": "2026-10-15 10:00:00"
  }
}

Изменить Dynamic QR

PATCH /qr-codes/QR_ID · Разрешение: qr:write

curl -i -X PATCH "$API_BASE/qr-codes/QR_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"name": "CRM", "value": "https://example.com/new"}'
HTTP 200
{
  "data": {
    "id": "QR_ID",
    "name": "CRM",
    "type": "url",
    "mode": "dynamic",
    "folder_id": null,
    "destination_url": "https://example.com/new",
    "scan_count": 0,
    "created_at": "2026-10-15 10:00:00"
  }
}

Удалить QR-код

DELETE /qr-codes/QR_ID · Разрешение: qr:write

curl -i -X DELETE "$API_BASE/qr-codes/QR_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"
HTTP 204
(без тела ответа)

Статистика QR-кода

GET /qr-codes/QR_ID/stats · Разрешение: analytics:read

curl -i -X GET "$API_BASE/qr-codes/QR_ID/stats" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"
HTTP 200
{
  "data": {
    "qr_code_id": "QR_ID",
    "scan_count": 0
  }
}

Переместить QR-код

POST /qr-codes/QR_ID/move · Разрешение: folders:write

curl -i -X POST "$API_BASE/qr-codes/QR_ID/move" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"folder_id": "FOLDER_ID"}'
HTTP 200
{
  "data": {
    "id": "QR_ID",
    "folder_id": "FOLDER_ID"
  }
}

Список папок

GET /folders · Разрешение: folders:read

curl -i -X GET "$API_BASE/folders" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"
HTTP 200
{
  "data": [
    {
      "id": "FOLDER_ID",
      "userId": "USER_ID",
      "name": "CRM",
      "qrCount": 1,
      "createdAt": "2026-10-15 10:00:00"
    }
  ]
}

Создать папку

POST /folders · Разрешение: folders:write

curl -i -X POST "$API_BASE/folders" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"name": "CRM"}'
HTTP 201
{
  "data": {
    "id": "FOLDER_ID"
  }
}

Переименовать папку

PATCH /folders/FOLDER_ID · Разрешение: folders:write

curl -i -X PATCH "$API_BASE/folders/FOLDER_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"name": "CRM 2"}'
HTTP 200
{
  "data": {
    "id": "FOLDER_ID"
  }
}

Удалить папку

DELETE /folders/FOLDER_ID · Разрешение: folders:write

curl -i -X DELETE "$API_BASE/folders/FOLDER_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Accept: application/json"
HTTP 204
(без тела ответа)

Параметры создания

Обязательные поля: qr_name (1–255 символов), type и данные выбранного типа. mode: static (по умолчанию) или dynamic. folder_id необязателен. Название папки — 1–48 символов. GET /qr-codes/{id}/stats возвращает суммарное scan_count, а не полный аналитический отчёт.

Дизайн передаётся при POST /qr-codes в том же JSON: foreground и background — HEX #RRGGBB; size — 256–1200 (по умолчанию 720); margin — 0–16 модулей (по умолчанию 1); corner_radius — 0–12; error_correction — L/M/Q/H.

module_style: square, rounded_soft, rounded, rounded_strong, dots, dots_small, diamond, hexagon, vertical, horizontal, leaf, star. eye_style и eye_inner_style принимают те же значения, а также circle и pointy. eye_outer_color и eye_inner_color — HEX.

gradient_enabled и background_transparent включаются строкой "1". Для градиента: gradient_color (HEX), gradient_type (linear, radial, vertical, horizontal, diagonal, inverse_diagonal), gradient_angle (0–360). JSON boolean true вместо строки "1" не включает эти параметры. Загрузка логотипа и скачивание изображения отдельными API-методами сейчас не предоставляются.

Ошибки и диагностика

Ошибки обработчиков API имеют формат: {"error":{"code":"insufficient_scope","message":"…"}}. Используйте HTTP-статус и code, а не текст сообщения. Авторизованные ответы содержат X-Request-Id; передайте его поддержке. Для непредвиденной ошибки идентификатор также доступен в журнале ключа. Ранний отказ веб-сервера или ограничения тела может иметь другой формат и не попасть в журнал ключа: сначала проверяйте HTTP-статус и Content-Type.

Содержимое QR-кодов

Для URL и текста — value; email — email, subject, body; телефона — phone; Wi-Fi — ssid, encryption, password, hidden; vCard — name, organization, phone, email, url; SMS — phone, message; геопозиции — latitude, longitude; WhatsApp — phone, message. Для POST название QR задаётся qr_name, для PATCH — name. Тип и дизайн после создания не меняются; назначение меняется только у Dynamic QR.

Журнал хранится 90 дней и включает ответы 403 по тарифу, 429 и внутренние ошибки после распознавания ключа. Заголовок Authorization и секрет не сохраняются; значения тела запроса очищаются. Неопознанный или отозванный ключ не привязывается к пользовательскому журналу.

Подтвердите действие

Войдите в аккаунт

Сессия завершилась. После входа вы вернётесь на эту страницу.