Abundera QR Pro API
Справочник REST API для pro.qr.abundera.ai. Создавайте, редактируйте и анализируйте динамические QR-коды программно. Всё, JSON поверх HTTPS, аутентификация через bearer-токен.
/docs/openapi.json, импортируйте в Postman, Insomnia или любой клиент OpenAPI 3.1. Охватывает 36 клиентских эндпоинтов: Codes, Analytics, Groups, Teams, Webhooks и User. Административные эндпоинты и Stripe-вебхуки намеренно исключены (только для межсервисного взаимодействия).Введение
API Abundera QR Pro позволяет создавать, редактировать и анализировать динамические QR-коды программно, всё, что разработчик хотел бы автоматизировать через панель управления. Управление командой, биллинг и аккаунт остаются в интерфейсе; этот API предназначен для операций с кодами.
Базовый URL: https://pro.qr.abundera.ai/api
Формат запроса: JSON (Content-Type: application/json) для POST / PATCH / DELETE.
Формат ответа: JSON (application/json; charset=utf-8).
Доступность: API доступен начиная с тарифа Business. Пользователи Solo могут работать только через панель управления.
Аутентификация
Каждый запрос передаёт API-ключ в качестве bearer-токена:
Authorization: Bearer abnd_qrpro_...Создавайте и отзывайте ключи на странице /account/keys (тарифы Business, Team или Agency). Токен abnd_qrpro_... показывается ровно один раз при создании, сохраните его немедленно. Мы храним только его SHA-256-хеш; восстановить утраченный ключ невозможно.
Неаутентифицированные запросы возвращают 401 { "error": "not_signed_in" }. Недействительные или отозванные ключи возвращают 401 { "error": "invalid_api_key" }.
API-ключи привязаны к создавшему их пользователю. Если этот пользователь входит в команду, эндпоинты ниже автоматически работают с кодами команды (контекст текущей команды хранится в аккаунте и управляется через панель управления).
Лимиты запросов
Лимиты применяются на уровне API-ключа. Каждый ответ содержит заголовки X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset (unix-время сброса окна).
| Тариф | Лимит | Окно |
|---|---|---|
| Business | 1 000 запросов / день | UTC-сутки |
| Team | 10 000 запросов / день | UTC-сутки |
| Agency | 50 000 запросов / день | UTC-сутки |
| Solo | (403 insufficient_plan) | , |
Запросы сверх лимита возвращают 429 { "error": "rate_limited", "window": "day", "retry_at": 1234567890 } с заголовком Retry-After в секундах.
Сканирования не ограничены по частоте, путь редиректа (aqr.net/{shortcode}) не требует аутентификации и не имеет лимита на сканирование. У каждого тарифа есть явный месячный лимит сканирований (100к / 1М / 10М / 30М). При превышении лимита редирект продолжает работать; мы пишем вам, чтобы вы могли решить, повысить тариф или переждать разовый всплеск. Планируете более ~10М сканирований в сутки? Напишите нам, чтобы согласовать мощности.
Ошибки
Каждый ответ с ошибкой, это JSON с машиночитаемым кодом error и, при необходимости, дополнительным контекстом:
{ "error": "plan_limit", "plan": "business", "limit": 500, "current": 500 }| Статус | Код | Значение |
|---|---|---|
| 400 | validation_error | Поле тела запроса не прошло валидацию. Ответ содержит field + message. |
| 401 | not_signed_in / invalid_api_key | Отсутствующий, недействительный или отозванный bearer-токен. |
| 402 | plan_limit | Достигнут лимит активных+приостановленных кодов для вашего тарифа. Ответ содержит plan, limit, current. |
| 402 | plan_expired | Аккаунт вышел за пределы 90-дневного льготного периода; обновите тариф для продолжения. |
| 403 | insufficient_plan | Доступ к API требует тарифа Business или выше. Solo-пользователи получают эту ошибку. |
| 403 | insufficient_role | Ваша роль в команде не разрешает запрошенное действие (требуется admin+). |
| 404 | not_found | Ресурс не существует или недоступен в вашей области видимости. |
| 409 | code_not_editable | Код находится в статусе grace или expired; реактивируйте для редактирования. |
| 429 | rate_limited | Дневной лимит тарифа превышен. См. Лимиты запросов. |
| 500 | internal | Необработанная ошибка сервера, напишите в поддержку, если воспроизводится. |
Коды
Динамические QR-коды: 7-символьный Base58-шорткод, который перенаправляет через aqr.net/{shortcode}. К каждому коду прилагается статический резервный QR, который можно скачать из панели управления. Если вы перестанете платить, статическая версия продолжит работать без обращения к нашему редиректу.
GET /api/codes
Список всех кодов в вашей текущей области видимости (личной или командной). Возвращает массив со сводкой сканирований за 30 дней для каждого кода.
$ curl -H "Authorization: Bearer abnd_qrpro_..." https://pro.qr.abundera.ai/api/codes
{
"codes": [
{ "id": "uuid", "shortcode": "aBc123x",
"url": "https://example.com/landing",
"label": "Q2 campaign", "tags": "q2,print",
"status": "active", "scans_30d": 1245,
"created_at": 1713288000, "updated_at": 1713370000 }
],
"plan": "business",
"plan_limit": 500,
"scope": { "type": "user" }
}POST /api/codes
Создать новый динамический код. Лимит активных+приостановленных кодов проверяется перед вставкой. Минимальное тело запроса:
{ "url": "https://example.com/landing" }Полная настройка (все параметры необязательны):
{ "url": "https://example.com/landing",
"label": "Spring campaign",
"tags": "q2,print",
"qr_type": "url",
"style_json": "{...}",
"logo_key": "instagram",
"frame_style": "scan-me",
"frame_text": "SCAN ME" }Возвращает 201 + созданную запись, включая сгенерированный shortcode и short_url для печати.
GET /api/codes/{id}
Получить один код. 404, если код недоступен в вашей области видимости.
PATCH /api/codes/{id}
Обновить любое изменяемое поле. Наиболее частый сценарий: изменить URL назначения уже напечатанного кода.
$ curl -X PATCH -H "Authorization: Bearer abnd_qrpro_..." -H "Content-Type: application/json" -d '{"url":"https://example.com/new-landing"}' https://pro.qr.abundera.ai/api/codes/uuidИзменения вступают в силу в редиректе в течение нескольких секунд. Допустимые значения status для PATCH: "active", "paused". Для удаления используйте DELETE.
DELETE /api/codes/{id}
Мягкое удаление. Переводит код в статус status=grace с grace_until = now + 90 days. Редирект продолжает работать в течение всего льготного периода, это конкретное воплощение обещания об отсутствии привязки. По истечении 90 дней код переходит в статус expired, и редирект возвращает 410 Gone.
POST /api/codes/import
Массовое создание из массива (также используется в сценарии «Сохранить в Pro» на qr.abundera.ai). Принимает один объект или массив. Лимит тарифа проверяется один раз перед пакетной вставкой.
Аналитика
GET /api/codes/{id}/analytics
Параметры запроса:
range=7d|30d|90d|1y|3y, ограничено сроком хранения вашего тарифа (Solo 1y, Business 2y, Team/Agency 3y).granularity=day|hour, почасовая гранулярность доступна только для Team и Agency; максимальное окно для почасовых данных, 7 дней.
{
"range": "30d", "days": 30, "granularity": "day",
"total": 4321,
"timeseries": [
{ "bucket": "2026-04-01", "scans": 142 },
{ "bucket": "2026-04-02", "scans": 178 },
...
],
"by_country": [
{ "key": "US", "total": 3012 },
{ "key": "CA", "total": 402 },
{ "key": "Other", "total": 108 }
],
"by_device": [
{ "key": "mobile", "total": 3850 },
{ "key": "tablet", "total": 312 },
{ "key": "desktop", "total": 159 }
]
}Страны с менее чем 5 сканированиями в выбранном окне сворачиваются в "Other" из соображений приватности (см. Модель приватности).
API-ключи
Создавайте и отзывайте ключи на странице /account/keys. Программное самоуправление через API доступно только в режиме чтения, вы можете просматривать и отзывать ключи, но создание нового требует панели управления (иначе нужен ключ, чтобы создать ключ).
GET /api/keys
Список ваших API-ключей. Сырой токен никогда не возвращается, только метаданные.
{
"keys": [
{ "id": "uuid", "label": "Production server",
"created_at": 1713288000, "last_used_at": 1713370000 }
],
"allowed": true,
"plan": "business"
}DELETE /api/keys/{id}
Отозвать ключ. Он перестаёт работать немедленно; любой запрос с ним вернёт 401 invalid_api_key.
Экспорт данных
GET /api/user/export
Скачать ZIP с полным набором данных, codes.csv (все коды, включая grace и expired), scans.csv (агрегированные суточные данные) и README.txt с описанием формата. Архив передаётся как application/zip; сохраните в файл:
$ curl -H "Authorization: Bearer abnd_qrpro_..." -o abundera-qr-export.zip https://pro.qr.abundera.ai/api/user/exportИмпортируйте куда угодно. Это и есть гарантия портативного формата, привязки к платформе быть не может, если данные принадлежат вам.
Модель приватности
Агрегат сканирований, это вся история с приватностью. Что мы храним по каждому сканированию на пути редиректа:
code_id, какой из ваших кодов был отсканированday_bucket, дата UTC (YYYY-MM-DD). Никакой суточной детализации в агрегате.country, ISO-3166-1 alpha-2 из заголовка CloudflareCF-IPCountry. Ни города, ни региона, ни геолукапа.device_type,mobile/tablet/desktop/unknown, определяется по краткому регулярному выражению User-Agent. Сырая строка UA отбрасывается сразу после классификации.scan_count, агрегированный счётчик, увеличивается при каждом обращении.
Чего мы не храним: IP-адреса (ни в каком виде), сырые строки User-Agent, геолокацию с точностью до города, субсуточные временные метки, реферер, куки, пиксели ретаргетинга и любые данные, позволяющие идентифицировать конкретного человека. Порог шума в 5 сканирований защищает от деанонимизации малых выборок.
Тарифы Team и Agency дополнительно записывают параллельный почасовой агрегат с hour_bucket (YYYY-MM-DD-HH UTC). Та же модель приватности, никакой детализации мельче часа, тот же порог шума, те же отсутствующие данные о конкретных сканирующих.
Подробнее: /manifesto/ и /no-lock-in/ на сайте бесплатного инструмента.