API URL-скорочувача - одна з менших інтеграцій у типовому беклозі інженерної команди. Три кінцеві точки, заголовок авторизації, JSON-payload. Сторінка документації обіцяє перший виклик за п'ять хвилин. Потім приходить продакшн-трафік, логіка повторних спроб створює дублікати посилань, дашборд заповнюється варіантами /foo-1, /foo-2, /foo-3 для одного й того самого пункту призначення, і хтось заводить тікет.
Цей матеріал проходить через реальну інтеграцію. Авторизація, перший виклик, чотири кінцеві точки, що покривають більшість сценаріїв використання, ідемпотентність, обробка помилок, ліміти швидкості і підводні камені продакшену, які пропускає п'ятихвилинний швидкий старт. Приклади коду на TypeScript, Python, Go, Ruby та PHP - перші три через офіційні SDK (@elido/sdk, elido-python, github.com/elido/elido-go), останні два - через звичайні HTTP-клієнти.
Передумови
Увійдіть у дашборд, перейдіть на /dashboard/api-keys і створіть API-ключ (він починається з elido_). Токени прив'язані до робочого простору - токен, виданий у робочому просторі A, не може створювати посилання в робочому просторі B. Токени машинних користувачів (для CI-систем, внутрішніх інструментів, інтеграцій machine-to-machine) створюються на /dashboard/machine-users і ротуються незалежно від персональних ключів. Обидва типи мають задану заздалегідь роль у робочому просторі (viewer, editor або admin), а не окремі права для кожної кінцевої точки, тож видавайте CI-завданню роль editor, якщо воно лише створює посилання. У посібнику з дозволів API-ключів перелічено, до чого може мати доступ кожна роль, зокрема пояснено, чому для змін вебхуків потрібна роль admin.
Базова URL-адреса - https://api.elido.app/v1. Домени для редиректу (f.elido.me, s.elido.me, b.elido.me) окремі від поверхні API. Ваші короткі посилання розв'язуються на домені редиректу; API призначений для створення, зміни і читання посилань.
Специфікація OpenAPI опублікована за адресою https://elido.app/openapi.json і відповідає OpenAPI 3.1. Офіційні SDK згенеровані з цієї специфікації і перевидаються з кожним релізом API; ви також можете згенерувати власний клієнт будь-якою мовою з підтримкою OpenAPI.
Перший виклик
Створіть коротке посилання з цільової URL-адреси. П'ять рядків на TypeScript:
import { Elido } from "@elido/sdk";
const elido = new Elido({ token: process.env.ELIDO_TOKEN! });
const link = await elido.links.create({
destinationUrl: "https://shop.example.com/spring-sale",
});
console.log(link.shortUrl); // https://s.elido.me/abc123
Python:
from elido import Elido
client = Elido(token=os.environ["ELIDO_TOKEN"])
link = client.links.create(
destination_url="https://shop.example.com/spring-sale",
)
print(link.short_url) # https://s.elido.me/abc123
Go:
import "github.com/elido/elido-go/v2/elido"
client := elido.NewClient(elido.WithToken(os.Getenv("ELIDO_TOKEN")))
link, err := client.Links.Create(ctx, &elido.LinkCreateInput{
DestinationURL: "https://shop.example.com/spring-sale",
})
if err != nil {
return fmt.Errorf("create link: %w", err)
}
fmt.Println(link.ShortURL)
Ruby (без офіційного SDK - через net/http):
require "net/http"
require "json"
uri = URI("https://api.elido.app/v1/links")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['ELIDO_TOKEN']}"
req["Content-Type"] = "application/json"
req.body = { destination_url: "https://shop.example.com/spring-sale" }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
link = JSON.parse(res.body)
puts link["short_url"]
PHP (Guzzle):
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.elido.app/v1/']);
$res = $client->post('links', [
'headers' => ['Authorization' => 'Bearer ' . getenv('ELIDO_TOKEN')],
'json' => ['destination_url' => 'https://shop.example.com/spring-sale'],
]);
$link = json_decode((string) $res->getBody(), true);
echo $link['short_url'];
Усі п'ять прикладів дають однаковий результат. Тіло відповіді містить коротку URL-адресу, канонічний ID посилання, ID робочого простору і мітку часу створення. Slug - abc123 у прикладі вище - генерується сервером, якщо ви не передасте slug у запиті. Алфавіт slug - base62 ([0-9A-Za-z]); довжина за замовчуванням - шість символів.
Чотири кінцеві точки, які ви справді використовуватимете
В API більше ніж чотири кінцеві точки, але більшість інтеграцій обходяться цим набором.
Створення посилання
POST /v1/links приймає цільову URL-адресу плюс опційні поля:
slug- slug, який ви обираєте самі (має бути унікальним на домені).domain_id- для посилань на власному домені; на/v1/linksвикористовується короткий домен за замовчуванням вашого плану, якщо його не вказано. Шлях із робочим простором/v1/workspaces/{workspace_id}/linksвимагає його.title- мітка, яка відображається в дашборді.tags- масив довільних рядків для організації.expires_at- мітка часу RFC 3339, після якої посилання повертає 410 Gone.redirect_status-301,302(за замовчуванням) або307.password- під час створення поки що не приймається; встановіть його одразу після цього черезPATCH, і редирект спершу покаже сторінку з паролем.utmіmetadata- заплановані. Сьогодні додавайте параметри UTM безпосередньо доdestination_url, а власні ключі зв'язку зберігайте вtags.
Власний slug - це поле, яке кусає команди в продакшені. Якщо ви передаєте slug, який вже використовується іншим посиланням на тому самому домені, API повертає 409 Conflict. Наївний обробник повторних спроб, що додає лічильник (my-slug-1, my-slug-2), спричиняє проблему з дублікатами посилань, описану на початку. Правильна поведінка при повторних спробах описана в розділі про ідемпотентність нижче.
Читання посилання
GET /v1/links/{id} повертає повний запис посилання, включно з short_url і всіма налаштуваннями. Кількість кліків відсутня в записі посилання; її можна отримати з наведених нижче кінцевих точок аналітики. ID посилання - канонічний ідентифікатор: slug може змінюватися, ID - ні.
GET /v1/links?host=…&tags=…&limit=… перелічує посилання в робочому просторі з фільтрами. Пагінація на основі курсору; next_cursor у відповіді непрозорий і повертається як параметр запиту cursor у наступному запиті.
Оновлення посилання
PATCH /v1/links/{id} приймає ті самі поля, що й створення. Найпоширеніші оновлення: зміна цільової URL-адреси (корисно для ротації кампаній без повторного друку QR-кодів), зміна тегів, продовження expires_at. Slug змінюється через той самий PATCH, якщо передати новий slug. Старий slug одразу перестає розв'язуватися; окрема кінцева точка перейменування, яка зберігала б 301 зі старого slug протягом періоду збереження, запланована, але ще не створена.
Видалення посилання
DELETE /v1/links/{id} виконує м'яке видалення і повертає 204 No Content. Посилання перестає перенаправляти і зникає з викликів списку та читання. Розділ «Кошик» з кінцевою точкою відновлення і 90-денним вікном до остаточного видалення запланований; сьогодні немає виклику API, який повертає видалене посилання.
Ключі ідемпотентності
Кожен запит, що змінює дані - POST, PATCH, DELETE - приймає заголовок Idempotency-Key. Значення заголовка - непрозорий рядок довжиною до 255 символів; сервер зберігає тіло відповіді і код статусу протягом 24 годин за ключем (workspace_id, idempotency_key) і повертає збережену відповідь, якщо той самий ключ надійде знову.
Офіційні SDK генерують ключі ідемпотентності автоматично, якщо їх не передано. Ви можете перевизначити його:
const link = await elido.links.create(
{ destinationUrl: "https://shop.example.com/spring-sale" },
{ idempotencyKey: "order-12345-link" },
);
Сценарій використання - цикл повторних спроб. Якщо ваше завдання створює посилання в межах обробки вхідного замовлення, генеруйте ключ ідемпотентності з ID замовлення. Повторна спроба того самого завдання побачить той самий ключ, потрапить у кеш ідемпотентності і поверне вже створене посилання, а не створить друге.
Ключовий підводний камінь: кеш ідемпотентності живе 24 години, а не вічно. Повторна спроба на третій день зависання завдання створить нове посилання. Якщо інтеграція працює на багатоденних пакетах, зберігайте ID посилання, повернутий першим успішним створенням, і шукайте його перед повторним запитом.
Другий підводний камінь: ідемпотентність діє в межах одного робочого простору. Той самий ключ у двох робочих просторах створює два посилання. Це правильна семантика для API з кількома робочими просторами, але вона може здивувати команди, які вважають ключ глобально унікальним.
Обробка помилок
API повертає стандартні HTTP-коди статусу плюс структуроване тіло помилки:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Workspace rate limit of 100 req/s exceeded. Retry after 1 second.",
"request_id": "req_01HXYZAB123",
"retry_after": 1
}
}
Коди, які ви бачитимете найчастіше:
400 invalid_request- помилка валідації payload. Полеmessageперелічує конкретні поля. Не повторюйте запит; виправте payload.401 unauthorized- токен відсутній або недійсний. Не повторюйте запит без ротації токена.403 forbidden- роль токена не дозволяє цю дію (ключ з роллюviewerне може створювати посилання). Перевірте роль ключа на/dashboard/api-keys.404 not_found- ресурс не існує або токен не має до нього доступу (ми повертаємо 404, а не 403, щоб не розкривати існування ресурсу неавторизованим викликам).409 conflict- slug вже використовується, або виявлено одночасне редагування (PATCH застарілої версії). Отримайте дані заново і повторіть спробу.429 rate_limit_exceeded- зменшіть частоту запитів відповідно до значенняretry_after.500 internal_server_error- помилка на боці сервера. Можна безпечно повторити з тим самим ключем ідемпотентності.502 bad_gateway,503 service_unavailable,504 gateway_timeout- тимчасові проблеми інфраструктури. Зменшіть частоту і повторіть спробу.
Офіційні SDK реалізують експоненційну затримку з джиттером для 429, 500, 502, 503 і 504. Вони не повторюють 400, 401, 403, 404 чи 409 - це помилки програмування або конфлікти бізнес-логіки, а не тимчасові збої. Власні HTTP-клієнти мають дотримуватися того самого підходу; повторення запиту 400 з тим самим payload не дасть іншого результату.
request_id у тілі помилки - це поле, яке варто включати в тікети підтримки. Ми можемо відстежити будь-який запит за цим ID через журнал аудиту, журнал застосунку і метрики платформи - і не можемо відстежити запит без нього.
Ліміти швидкості
Опубліковані ліміти швидкості - 100 запитів на секунду на робочий простір на плані Pro, 500 на Business і узгоджений ліміт на Enterprise. Безкоштовний план - 10 запитів на секунду.
Стан ліміту швидкості відображається в трьох заголовках відповіді на кожен запит до API:
X-RateLimit-Limit- поточний ліміт за секунду.X-RateLimit-Remaining- кількість запитів, що залишилися в поточній секунді.X-RateLimit-Reset- мітка часу Unix, коли скидається лічильник.
Ліміт 100/с реалізований через token bucket з пропускною здатністю сплеску 200 - тобто ви можете надіслати 200 запитів одразу, якщо кошик повний, а потім перейти на сталий темп 100/с. Більшість завдань зі створення коротких посилань комфортно вкладаються в цей сплеск; інтеграції з інтенсивною аналітикою, що гортають історичні події кліків, виграють від запасу плану Pro.
Для масових операцій кінцева точка POST /v1/links/bulk приймає до 100 посилань за один запит і рахується як одна одиниця ліміту швидкості. Це правильна кінцева точка для будь-якого завдання, що створює більше сотні посилань за раз. Детальніший розбір темпу відносно token bucket, вибору кодів статусу для повторення і того, як ключі ідемпотентності запобігають дублюванню посилань під час повторних спроб, дивіться в ліміти швидкості, повторні спроби та ідемпотентність у продакшені.
Що роблять SDK, чого не робить звичайний HTTP
Офіційні SDK постачають чотири речі, які швидко окупаються:
- Автоматичне повторення із затримкою для кодів статусу, що допускають повтор.
- Генерація ключів ідемпотентності, якщо їх не передано явно.
- Типізовані помилки, тож ви можете писати
catch (err) { if (err instanceof ElidoRateLimitError) { … } }, а не розбирати JSON у блоках catch. - Ітератори пагінації, тож кінцеві точки списків надають асинхронні ітератори чи генератори замість необхідності вручну обробляти курсор.
Go SDK додатково надає доступ до нижчерівневого HTTP-клієнта для інструментування - корисно, якщо ви хочете підключити його до наявного налаштування трасування. Сторінка функцій API + SDK охоплює всю поверхню; довідник API опубліковано на /docs/api-reference.
Доступ до аналітики
Кінцеві точки аналітики доступні лише для читання і живуть за адресою /v1/workspaces/{id}/analytics/. У посібнику з API аналітики посилань перелічено всі звіти, їхні параметри і форми відповідей. Найпоширеніші запити:
GET .../clicks/recent?from=…&to=…- окремі кліки, від найновіших до найстаріших, із пагінацією черезnext_cursor. Корисно для конвеєрів експорту.GET .../timeseries?from=…&to=…&interval=day- згруповані за відрізками часу кількості кліків для заданого діапазону;intervalможе бутиhourабоday, аtzзадає часовий пояс відрізка.GET .../breakdown/country?from=…&to=…- розбивка за географією.GET .../breakdown/referrer?from=…&to=…- розбивка за реферером.
Інші звіти: summary, links/top, решта розбивок (host, device, browser, destination) і топсписки (top-countries, top-regions, top-cities, top-referrers, top-destinations). from і to - дати у форматі YYYY-MM-DD, причому to є виключною датою; додайте link_id, щоб звузити будь-який звіт до одного посилання, і limit, щоб задати розмір розбивок і топсписків.
Потік сирих подій кліків - найбільший за обсягом. Робочий простір із 10 млн кліків на місяць генерує близько 600 МБ JSON сирих даних подій на місяць. Для експорту в такому масштабі гайд з експорту аналітики описує механізм масового експорту, що обходить JSON-обгортку і передає дані напряму зі сховища аналітики.
Вебхуки для подій посилань
Вебхуки - протилежність опитуванню: замість того, щоб ви питали API, що змінилося, API сам доставляє події посилань і доменів на вашу кінцеву точку. Налаштуйте на /dashboard/webhooks:
await elido.webhooks.create({
url: "https://your-app.example/webhooks/elido",
events: ["link.created", "link.updated", "link.expired"],
secret: process.env.WEBHOOK_SIGNING_SECRET,
});
Подія click.created для кожного окремого кліка - в дорожній карті, але поки недоступна, тож наразі дані про кліки надходять через кінцеві точки аналітики. Кожна доставка містить заголовок X-Elido-Signature (також надсилається як X-Webhook-Signature) зі значенням v1=<hex>: HMAC-SHA256, підписаний вашим секретом кінцевої точки, над значенням X-Webhook-Timestamp, крапкою і сирим тілом запиту. Перевіряйте підпис перед обробкою - без цього будь-який виклик може надіслати запит на вашу кінцеву точку webhook і видати себе за Elido.
Семантика доставки - at-least-once: невдала доставка повторюється із затримкою у хвилинах, за замовчуванням до трьох спроб загалом. Детальнішу структуру і поведінку повторних спроб порівнює матеріал про вебхуки проти опитування, який зіставляє два підходи до інтеграції.
Розібраний приклад: автоматизація кампаній
Інтеграція, що мотивує більшість впроваджень API, виглядає так. Ваша маркетингова автоматизація створює кампанію в Customer.io чи HubSpot. Хук спрацьовує, коли кампанію опубліковано. Ваш обробник створює коротке посилання, прив'язує його до запису кампанії і надсилає назад в інструмент керування кампаніями для підстановки в шаблон листа.
На TypeScript:
import { Elido } from "@elido/sdk";
const elido = new Elido({ token: process.env.ELIDO_TOKEN! });
export async function onCampaignPublished(campaign: Campaign) {
const link = await elido.links.create(
{
destinationUrl: campaign.destinationUrl,
tags: [
"campaign",
`campaign:${campaign.id}`,
`batch:${campaign.batchId}`,
campaign.channel,
],
},
{
idempotencyKey: `campaign-${campaign.id}-link`,
},
);
await campaignStore.update(campaign.id, { shortUrl: link.shortUrl });
return link;
}
Ключ ідемпотентності виводиться з ID кампанії. Якщо хук публікації кампанії спрацьовує двічі (а так і буває - доставки вебхуків мають гарантію at-least-once), другий виклик повертає те саме посилання, не створюючи дубліката. Теги campaign: і batch: містять ваші власні ключі зв'язку, щоб ви могли зіставляти події кліків Elido з кампанією; окреме поле metadata для цього заплановане. Параметри UTM належать до самого campaign.destinationUrl, доки поле utm не буде випущено.
Наскрізну атрибуцію кампаній з UTM-шаблонами і пересиланням конверсій розглядає наріжний матеріал про відстеження UTM.
Чого ще немає в API
Дві речі, про які часто запитують, наразі недоступні:
- Єдиний GET для аналітики посилання, що повертає всі розбивки одним викликом. Поточна модель вимагає окремих викликів для кліків, країни, реферера, пристрою і часового ряду. Агрегація - в дорожній карті; наразі виконуйте запити паралельно у власному коді.
- Повторна доставка webhook через API. Дашборд показує історію доставок webhook і підтримує повторну доставку; API поки ні. Це також в дорожній карті.
Якщо функція є в специфікації OpenAPI, вона підтримується. Якщо вона згадана в цьому матеріалі, але відсутня в специфікації, вважайте її запланованою, а не гарантованою.
Що почитати ще
- Пояснення розумних посилань - наріжний матеріал кластера функцій; описує, як механізм редиректу розв'язує посилання на межі мережі.
- Вебхуки проти опитування для відстеження кліків - коли який підхід до інтеграції використовувати.
- Відстеження конверсій на боці сервера через короткі посилання - розширення API до потоку пересилання конверсій.
- Масовий імпорт кампаній з Google Sheets - розібраний приклад масової кінцевої точки.
- API URL-скорочувача: ліміти швидкості, повторні спроби, ідемпотентність - зміцнення інтеграції для продакшн-трафіку.
- Дозволи API-ключів для інструментів роботи з посиланнями - ключі, прив'язані до робочого простору, обмеження ролей і ротація.
- Безкоштовний API URL-скорочувача: приклади коду, які працюють - виклик створення в curl, JavaScript, Python і Go, і що обмежують безкоштовні плани.
- API аналітики посилань: отримуйте статистику кліків за допомогою API-ключа - усі звіти, параметри запитів і щоденний скрипт для Slack.
- Операційний розбір: гайд з MCP-сервера для підключення поверхні API Elido до Claude, Cursor та інших клієнтів з підтримкою MCP.
- Поверхня продукту:
/features/api-sdksі/solutions/developers.
Спробуйте Elido
Вставте URL - отримайте коротке посилання
Без реєстрації. Посилання живе 30 днів. Зареєструйтесь, щоб зберегти назавжди.
Безкоштовно, без реєстрації · 2 на день