Аутентификация
Все запросы к API требуют API-ключа. Передавайте его в заголовке Authorization в формате Bearer krc_.... Ключ привязан к организации — все операции выполняются от её имени.
Как получить ключ
- 1. Откройте Настройки → вкладка «API-ключи»
- 2. Нажмите «Создать ключ», укажите название
- 3. Скопируйте ключ сразу — он показывается только один раз
# Проверка ключа — создать тестовую ссылку
curl -X POST https://koroche.site/api/public/v1/links \
-H "Authorization: Bearer krc_aBcDeFgHiJkL..." \
-H "Content-Type: application/json" \
-d '{"destinationUrl": "https://example.com"}'
# Все запросы используют один и тот же заголовок:
# -H "Authorization: Bearer <ваш-ключ>"Лимиты запросов
Запросы ограничены по IP-адресу. При превышении лимита сервер возвращает 429 Too Many Requests с заголовком Retry-After: 1. Повторите запрос через 1 секунду.
| Лимит | Значение |
|---|---|
| Запросов в секунду (на IP) | 100 |
Каждый ответ содержит заголовки для отслеживания лимита:
| Заголовок | Описание |
|---|---|
| X-RateLimit-Limit | Максимум запросов в секунду |
| X-RateLimit-Remaining | Оставшиеся запросы в текущем окне |
| X-RateLimit-Window | Длина окна (всегда 1s) |
| Retry-After | Секунды до сброса лимита (только при 429) |
Ссылки
/api/public/v1/linksСоздаёт новую короткую ссылку в вашей организации. Возвращает объект ссылки с готовым коротким URL.
Тело запроса (application/json)
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
| destinationUrl | string | да | Конечный URL, на который ведёт ссылка. Должен быть валидным HTTP/HTTPS URL. |
| slug | string | нет | Пользовательский слаг (3–50 символов, a-z 0-9 - _). Если не указан — генерируется автоматически. |
| title | string | нет | Название ссылки для отображения в дашборде. |
| domainId | UUID | нет | ID кастомного домена из вашей организации. Ссылка будет работать на этом домене вместо koroche.site. |
| subdomainId | UUID | нет | ID брендированного субдомена из вашей организации (например, go.brand.ru). |
| startsAt | string | нет | Дата активации ссылки в формате ISO-8601. До этого момента ссылка вернёт 404. |
| expiresAt | string | нет | Дата истечения ссылки в формате ISO-8601 (2026-12-31T23:59:59). После этой даты ссылка перестаёт работать. |
| clickLimit | integer | нет | Максимальное число переходов. После достижения лимита ссылка деактивируется. |
| password | string | нет | Пароль для защиты ссылки. Пользователь увидит форму ввода перед редиректом. |
| utmSource | string | нет | UTM-параметр utm_source. Автоматически добавляется к destinationUrl. |
| utmMedium | string | нет | UTM-параметр utm_medium. |
| utmCampaign | string | нет | UTM-параметр utm_campaign. |
| utmContent | string | нет | UTM-параметр utm_content. |
| utmTerm | string | нет | UTM-параметр utm_term. |
| ogTitle | string | нет | OG-заголовок для предпросмотра в мессенджерах (тариф Старт+). |
| ogDescription | string | нет | OG-описание для предпросмотра (тариф Старт+). |
| ogImage | string | нет | URL OG-изображения (тариф Старт+). |
| iosUrl | string | нет | URL для iOS-пользователей (тариф Про+). Остальные переходят на destinationUrl. |
| androidUrl | string | нет | URL для Android-пользователей (тариф Про+). |
| allowedCountries | string | нет | Коды стран через запятую (RU,BY,KZ). Пользователи из других стран попадут на geoFallbackUrl (тариф Про+). |
| geoFallbackUrl | string | нет | URL для пользователей из заблокированных стран (тариф Про+). |
curl -X POST https://koroche.site/api/public/v1/links \
-H "Authorization: Bearer krc_aBcDeFgHiJkL..." \
-H "Content-Type: application/json" \
-d '{
"destinationUrl": "https://example.com/landing-page",
"slug": "summer-sale",
"title": "Летняя распродажа",
"utmSource": "telegram",
"utmMedium": "social",
"utmCampaign": "sale-june"
}'Ответ 201 Created
{
"id": "018f4a2b-1c3d-7e8f-9a0b-c1d2e3f4a5b6",
"slug": "summer-sale",
"shortUrl": "https://koroche.site/summer-sale",
"destinationUrl": "https://example.com/landing-page",
"title": "Летняя распродажа",
"clickCount": 0,
"clickLimit": null,
"createdAt": "2026-06-13T12:00:00",
"expiresAt": null,
"tags": [],
"lastClickedAt": null,
"ogTitle": null,
"ogDescription": null,
"ogImage": null,
"iosUrl": null,
"androidUrl": null,
"allowedCountries": null,
"geoFallbackUrl": null,
"statsToken": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}/api/public/v1/links/{linkId}/statsВозвращает базовую статистику по ссылке: слаг и общее число переходов.
Параметры пути
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
| linkId | UUID | да | ID ссылки из ответа POST /links. |
curl https://koroche.site/api/public/v1/links/018f4a2b-1c3d-7e8f-9a0b-c1d2e3f4a5b6/stats \ -H "Authorization: Bearer krc_aBcDeFgHiJkL..."
Ответ 200 OK
{
"id": "018f4a2b-1c3d-7e8f-9a0b-c1d2e3f4a5b6",
"slug": "summer-sale",
"clickCount": 1423
}Вебхуки
Вебхуки позволяют получать уведомления о событиях в реальном времени — на ваш сервер. Подписки настраиваются в Настройках → «Вебхуки». Каждый запрос содержит HMAC-SHA256 подпись для верификации подлинности.
События
| Событие | Когда срабатывает |
|---|---|
| link.created | Создана новая ссылка (через UI или API) |
| link.deleted | Ссылка удалена |
Проверка подписи
Каждый запрос содержит заголовок X-Koroche-Signature: sha256=<hex>. Вычислите HMAC-SHA256 от тела запроса, используя secret из настроек подписки, и сравните с полученным значением. Также приходит заголовок X-Koroche-Event с именем события.
import hmac, hashlib
def verify(secret: str, body: bytes, signature_header: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)const crypto = require("crypto");
function verify(secret, rawBody, signatureHeader) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}Формат payload
Все события имеют одинаковую обёртку. Поле data содержит объект события.
// link.created
{
"event": "link.created",
"timestamp": 1749816000000,
"data": {
"id": "018f4a2b-1c3d-7e8f-9a0b-c1d2e3f4a5b6",
"slug": "summer-sale",
"shortUrl": "https://koroche.site/summer-sale",
"destinationUrl": "https://example.com/landing-page",
"title": "Летняя распродажа",
"clickCount": 0,
"createdAt": "2026-06-13T12:00:00"
}
}
// link.deleted
{
"event": "link.deleted",
"timestamp": 1749816000000,
"data": {
"id": "018f4a2b-1c3d-7e8f-9a0b-c1d2e3f4a5b6",
"slug": "summer-sale"
}
}Повторные попытки
Если ваш сервер вернул не 2xx, доставка повторяется с экспоненциальной задержкой: 1 мин → 5 мин → 15 мин → 60 мин. После 5 неудачных попыток доставка помечается как FAILED. Ваш эндпоинт должен отвечать в течение 10 секунд.
Коды ошибок
| Код | Причина |
|---|---|
| 400 | Неверный формат запроса — проверьте обязательные поля и типы данных |
| 401 | API-ключ отсутствует, неверен или отозван |
| 403 | Недостаточно прав — ключ не имеет доступа к этому ресурсу |
| 404 | Ресурс не найден |
| 409 | Конфликт — например, слаг уже занят |
| 422 | Ошибка валидации — поле не прошло проверку (см. поле error в ответе) |
| 429 | Превышен лимит запросов — повторите через минуту |
| 500 | Внутренняя ошибка сервера |
Формат ошибки
{
"error": "Слаг 'summer-sale' уже занят",
"status": 409
}