API skracacza URL to jedna z mniejszych integracji w backlogu typowego zespołu inżynierskiego. Trzy endpointy, nagłówek autoryzacji, ładunek JSON. Strona dokumentacji obiecuje pierwsze wywołanie w pięć minut. Potem uderza ruch produkcyjny, logika ponowień tworzy zduplikowane linki, dashboard zapełnia się wariantami /foo-1, /foo-2, /foo-3 tego samego miejsca docelowego, i ktoś zgłasza ticket.
Ten wpis przechodzi przez faktyczną integrację. Autoryzacja, pierwsze wywołanie, cztery endpointy pokrywające większość przypadków użycia, idempotencja, obsługa błędów, limity szybkości i haczyki produkcyjne, które pięciominutowy szybki start pomija. Przykłady kodu w TypeScript, Python, Go, Ruby i PHP - pierwsze trzy przez oficjalne SDK (@elido/sdk, elido-python, github.com/elido/elido-go), pozostałe dwa przez zwykłe klienty HTTP.
Wymagania wstępne
Zaloguj się do dashboardu, przejdź do /dashboard/api-keys i utwórz klucz API (zaczyna się od elido_). Tokeny są ograniczone do workspace'u - token wydany w workspace'ie A nie może tworzyć linków w workspace'ie B. Tokeny maszynowe (dla systemów CI, narzędzi wewnętrznych, integracji maszyna-maszyna) są tworzone pod /dashboard/machine-users i rotują niezależnie od kluczy osobistych. Oba rodzaje niosą wstępnie ustawioną rolę workspace'u (viewer, editor albo admin), a nie uprawnienia per endpoint, więc nadaj zadaniu CI rolę editor, jeśli tylko tworzy linki. Przewodnik uprawnienia kluczy API dla narzędzi do linków wyjaśnia, do czego można użyć każdej roli, w tym dlaczego zmiany webhooków wymagają roli admin.
Bazowy URL to https://api.elido.app/v1. Domeny przekierowania (f.elido.me, s.elido.me, b.elido.me) są osobne od powierzchni API. Twoje krótkie linki rozwiązują się na domenie przekierowania; API służy do tworzenia, modyfikowania i odczytywania ich.
Specyfikacja OpenAPI jest opublikowana pod https://elido.app/openapi.json i zgodna z OpenAPI 3.1. Oficjalne SDK są generowane z tej specyfikacji i republikowane przy każdym wydaniu API; możesz też wygenerować własnego klienta w dowolnym języku obsługiwanym przez OpenAPI.
Pierwsze wywołanie
Utwórz krótki link z docelowego URL. Pięć linijek w 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 (bez oficjalnego SDK - używając 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'];
Wszystkie pięć produkuje ten sam wynik. Treść odpowiedzi zawiera krótki URL, kanoniczny identyfikator linku, identyfikator workspace'u i znacznik czasu utworzenia. Slug - abc123 w powyższym przykładzie - jest generowany przez serwer, chyba że przekażesz slug w żądaniu. Alfabet sluga to base62 ([0-9A-Za-z]); domyślna długość to sześć znaków.
Cztery endpointy, których faktycznie będziesz używać
API ma więcej niż cztery endpointy, ale większość integracji zostaje w tym zestawie.
Tworzenie linku
POST /v1/links przyjmuje docelowy URL plus opcjonalne pola:
slug- slug, który wybierasz (musi być unikalny w obrębie domeny).domain_id- dla linków na własnej domenie; w/v1/linksużywana jest domyślna krótka domena Twojego planu, jeśli pole zostanie pominięte. Ścieżka obejmująca workspace,/v1/workspaces/{workspace_id}/links, wymaga tego pola.title- etykieta wyświetlana w dashboardzie.tags- tablica dowolnych ciągów do organizacji.expires_at- znacznik czasu RFC 3339, po którym link zwraca 410 Gone.redirect_status-301,302(domyślnie) albo307.password- nie jest jeszcze akceptowane przy tworzeniu; ustaw je od razu potem przezPATCH, a przekierowanie będzie wyświetlać stronę z hasłem przed przekazaniem dalej.utmimetadata- planowane. Dziś umieszczaj parametry UTM bezpośrednio wdestination_url, a własne klucze złączeń przechowuj wtags.
Niestandardowy slug to pole, które gryzie zespoły na produkcji. Jeśli przekażesz slug już używany przez inny link w tej samej domenie, API zwraca 409 Conflict. Naiwny handler ponowień, który dopisuje licznik (my-slug-1, my-slug-2), produkuje problem zduplikowanych linków opisany na wstępie. Właściwe zachowanie przy ponowieniu jest opisane w sekcji o idempotencji poniżej.
Odczyt linku
GET /v1/links/{id} zwraca pełny rekord linku, w tym short_url i całą konfigurację. Liczby kliknięć nie znajdują się w rekordzie linku; pochodzą z opisanych niżej endpointów analityki. Identyfikator linku to kanoniczny identyfikator - slugi mogą się zmieniać, identyfikatory nie.
GET /v1/links?host=…&tags=…&limit=… listuje linki w workspace'ie z filtrami. Paginacja jest oparta na kursorze; next_cursor w odpowiedzi jest nieprzezroczysty i wraca jako parametr zapytania cursor w następnym żądaniu.
Aktualizacja linku
PATCH /v1/links/{id} przyjmuje te same pola co tworzenie. Najczęstsze aktualizacje: zmiana docelowego URL (przydatne przy rotacji kampanii bez ponownego drukowania kodów QR), zmiana tagów, przedłużenie expires_at. Slug zmienia się przez to samo PATCH, wysyłając nowy slug. Stary slug natychmiast przestaje działać; osobny endpoint zmiany nazwy, który utrzymuje 301 ze starego sluga przez okres retencji, jest planowany, ale jeszcze nie został zbudowany.
Usuwanie linku
DELETE /v1/links/{id} usuwa miękko i zwraca 204 No Content. Link przestaje przekierowywać i wypada z wywołań listowania oraz odczytu. Widok kosza z endpointem przywracania i 90-dniowym okresem przed trwałym usunięciem jest planowany; dziś nie ma wywołania API, które przywraca usunięty link.
Klucze idempotencji
Każde żądanie mutujące - POST, PATCH, DELETE - przyjmuje nagłówek Idempotency-Key. Wartość nagłówka to nieprzezroczysty ciąg do 255 znaków; serwer przechowuje treść odpowiedzi i kod statusu przez 24 godziny, kluczowane przez (workspace_id, idempotency_key), i zwraca zapisaną odpowiedź, jeśli ten sam klucz zostanie przedstawiony ponownie.
Oficjalne SDK generują klucze idempotencji automatycznie, gdy nie są dostarczone. Możesz to nadpisać:
const link = await elido.links.create(
{ destinationUrl: "https://shop.example.com/spring-sale" },
{ idempotencyKey: "order-12345-link" },
);
Przypadek użycia to pętla ponowień. Jeśli Twoje zadanie tworzy link jako część przetwarzania zamówienia wyższego w łańcuchu, wygeneruj klucz idempotencji z identyfikatora zamówienia. Ponowienie tego samego zadania widzi ten sam klucz, trafia w cache idempotencji i zwraca oryginalnie utworzony link zamiast wyprodukować drugi.
Kluczowy haczyk: cache idempotencji żyje 24 godziny, nie wiecznie. Ponowienie trzeciego dnia zablokowanego zadania stworzy nowy link. Jeśli integracja działa na przestrzeni wielodniowych partii, zapisz identyfikator linku zwrócony przez pierwsze udane utworzenie i sprawdź go, zanim wydasz ponownie.
Drugi haczyk: idempotencja jest per workspace. Ten sam klucz w dwóch workspace'ach tworzy dwa linki. To właściwa semantyka dla API wieloworkspace'owego, ale może zaskoczyć zespoły, które zakładają, że klucz jest globalnie unikalny.
Obsługa błędów
API zwraca standardowe kody statusu HTTP plus ustrukturyzowaną treść błędu:
{
"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
}
}
Kody, które zobaczysz najczęściej:
400 invalid_request- awaria walidacji ładunku. Polemessagewymienia konkretne pola. Nie ponawiaj; napraw ładunek.401 unauthorized- brak tokena albo nieprawidłowy. Nie ponawiaj bez rotacji tokena.403 forbidden- rola tokena nie pozwala na akcję (kluczviewernie może tworzyć linków). Sprawdź rolę klucza pod/dashboard/api-keys.404 not_found- zasób nie istnieje albo token nie ma do niego dostępu (zwracamy 404 zamiast 403, żeby uniknąć ujawniania istnienia zasobu nieautoryzowanym wywołującym).409 conflict- slug już używany, albo wykryto jednoczesną edycję (PATCH na nieaktualnej wersji). Pobierz ponownie i spróbuj jeszcze raz.429 rate_limit_exceeded- wycofaj się zgodnie z wartościąretry_after.500 internal_server_error- awaria po stronie serwera. Bezpiecznie ponowić z tym samym kluczem idempotencji.502 bad_gateway,503 service_unavailable,504 gateway_timeout- przejściowe problemy infrastrukturalne. Wycofaj się i ponów.
Oficjalne SDK implementują wykładnicze wycofanie z jitterem dla 429, 500, 502, 503 i 504. Nie ponawiają 400, 401, 403, 404 ani 409 - to błędy programistyczne albo konflikty logiki biznesowej, nie przejściowe awarie. Niestandardowe klienty HTTP powinny stosować ten sam wzorzec; ponowienie 400 z tym samym ładunkiem nie da innego wyniku.
request_id w treści błędu to pole do umieszczenia w ticketach wsparcia. Możemy prześledzić dowolne żądanie z tego identyfikatora przez log audytu, log aplikacji i metryki platformy - a nie możemy prześledzić żądania bez niego.
Limity szybkości
Opublikowane limity szybkości to 100 żądań na sekundę per workspace na Pro, 500 na Business i negocjowany limit na Enterprise. Darmowy poziom to 10 req/s.
Stan limitu szybkości jest wystawiony w trzech nagłówkach odpowiedzi przy każdej odpowiedzi API:
X-RateLimit-Limit- bieżący limit na sekundę.X-RateLimit-Remaining- żądania pozostałe w bieżącej sekundzie.X-RateLimit-Reset- znacznik czasu Unix, kiedy zasobnik się resetuje.
Limit 100/s to implementacja token-bucket z pojemnością wybuchu 200 - co oznacza, że możesz wydać 200 żądań naraz, jeśli zasobnik jest pełny, a potem ustabilizować się w stałym tempie 100/s. Większość zadań tworzenia krótkich linków mieści się wygodnie w wybuchu; integracje mocno oparte na analityce, które stronicują przez historyczne zdarzenia kliknięć, korzystają z zapasu poziomu Pro.
Dla operacji masowych endpoint POST /v1/links/bulk przyjmuje do 100 linków na żądanie i liczy się jako jedna jednostka limitu szybkości. To właściwy endpoint dla każdego zadania, które tworzy więcej niż sto linków naraz. Dla głębszego omówienia tempa względem token bucket, wyboru, które kody statusu ponawiać, i tego, jak klucze idempotencji chronią przed duplikowaniem linków przy ponowieniach, zobacz limity szybkości, ponowienia i idempotencja na produkcji.
Co robią SDK, czego nie robi zwykłe HTTP
Oficjalne SDK dostarczają cztery rzeczy, które szybko się zwracają:
- Automatyczne ponowienie z wycofaniem dla kodów statusu podlegających ponowieniu.
- Generowanie kluczy idempotencji, gdy nie są jawnie dostarczone.
- Typowane błędy, więc możesz zrobić
catch (err) { if (err instanceof ElidoRateLimitError) { … } }zamiast parsować JSON w blokach catch. - Iteratory paginacji, więc endpointy listujące wystawiają asynchroniczne iteratory albo generatory zamiast wymagać ręcznej obsługi kursora.
SDK w Go dodatkowo wystawia bazowego klienta HTTP do instrumentacji - przydatne, jeśli chcesz podłączyć go do swojej istniejącej konfiguracji tracingu. Strona funkcji API + SDK w repozytorium omawia pełną powierzchnię; referencja API jest opublikowana pod /docs/api-reference.
Dostęp do analityki
Endpointy analityki są tylko do odczytu i żyją pod /v1/workspaces/{id}/analytics/; przewodnik po API analityki linków zawiera listę wszystkich raportów, ich parametrów i kształtów odpowiedzi. Najczęstsze zapytania:
GET .../clicks/recent?from=…&to=…- pojedyncze kliknięcia, od najnowszych, stronicowane przeznext_cursor. Przydatne dla pipeline'ów eksportu.GET .../timeseries?from=…&to=…&interval=day- liczby kliknięć w koszykach dla zakresu czasu;intervaltohouralboday, atzustawia strefę czasową koszyka.GET .../breakdown/country?from=…&to=…- podział geograficzny.GET .../breakdown/referrer?from=…&to=…- podział wg referrera.
Pozostałe raporty to summary, links/top, pozostałe podziały (host, device, browser, destination) oraz listy top (top-countries, top-regions, top-cities, top-referrers, top-destinations). from i to to daty w formacie YYYY-MM-DD, a to jest wyłączne; dodaj link_id, aby zawęzić dowolny raport do jednego linku, oraz limit, aby określić rozmiar podziałów i list top.
Strumień surowych zdarzeń kliknięć jest największy. Workspace z 10 mln kliknięć miesięcznie produkuje około 600 MB danych JSON surowych zdarzeń miesięcznie. Dla eksportów na tę skalę przewodnik eksportu analityki omawia mechanizm eksportu masowego, który omija kopertę JSON i strumieniuje bezpośrednio z hurtowni analityki.
Webhooki dla zdarzeń linków
Webhooki to odwrotność pollingu - zamiast Ciebie pytającego API, co się zmieniło, API dostarcza zdarzenia linków i domen na Twój endpoint. Skonfiguruj pod /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,
});
Zdarzenie click.created per kliknięcie jest na mapie drogowej, ale jeszcze niedostępne, więc dziś dane o kliknięciach pochodzą z endpointów analityki. Każda dostawa zawiera nagłówek X-Elido-Signature (wysyłany też jako X-Webhook-Signature) z wartością v1=<hex>: HMAC-SHA256, kluczowany Twoim sekretem endpointu, nad wartością X-Webhook-Timestamp, kropką i surową treścią żądania. Zweryfikuj sygnaturę przed przetwarzaniem - bez tego każdy wywołujący może wysłać POST na Twój endpoint webhooka i podszyć się pod Elido.
Semantyka dostawy to at-least-once: nieudana dostawa jest ponawiana z wycofaniem liczonym w minutach, domyślnie w sumie trzy próby. Po szczegółowy kształt i zachowanie ponowień, wpis webhooki kontra polling porównuje oba wzorce integracji.
Przerobiony przykład: automatyzacja kampanii
Integracja, która motywuje większość adopcji API, wygląda tak. Twoja automatyzacja marketingowa tworzy kampanię w Customer.io albo HubSpot. Hook wystrzeliwuje, gdy kampania jest publikowana. Twój handler tworzy krótki link, dołącza go do rekordu kampanii i wysyła go z powrotem do narzędzia zarządzania kampanią, żeby podstawić do szablonu e-maila.
W 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;
}
Klucz idempotencji jest wyprowadzony z identyfikatora kampanii. Jeśli hook publikacji kampanii wystrzeli dwa razy (a wystrzeli - dostawy webhooków są at-least-once), drugie wywołanie zwraca ten sam link bez tworzenia duplikatu. Tagi campaign: i batch: przenoszą Twoje własne klucze złączeń, żebyś mogła skorelować zdarzenia kliknięć Elido z powrotem do kampanii; osobne pole metadata do tego celu jest planowane. Parametry UTM umieszczaj w samym campaign.destinationUrl, dopóki pole utm nie zostanie wdrożone.
Dla atrybucji kampanii od początku do końca z szablonami UTM i przekazywaniem konwersji, artykuł filarowy o śledzeniu UTM przechodzi przez cały pipeline.
Czego jeszcze nie ma w API
Dwie rzeczy, o które często się pyta, obecnie niedostępne:
- Pojedynczy GET analityki linku, który zwraca wszystkie podziały w jednym wywołaniu. Obecny model wymaga osobnych wywołań dla kliknięć, kraju, referrera, urządzenia i szeregu czasowego. Agregacja jest na mapie drogowej; na razie uruchamiaj żądania równolegle we własnym kodzie.
- Odtwarzanie webhooków z API. Dashboard wystawia historię dostaw webhooków i obsługuje odtwarzanie; API jeszcze nie. To też jest na mapie drogowej.
Jeśli funkcja jest w specyfikacji OpenAPI, jest obsługiwana. Jeśli jest w tym wpisie, ale nie w specyfikacji, traktuj ją jako planowaną, a nie gwarantowaną.
Powiązana lektura
- Smart links wyjaśnione - artykuł filarowy dla klastra funkcji; omawia, jak silnik przekierowania rozwiązuje link na brzegu sieci.
- Webhooki kontra polling dla śledzenia kliknięć - kiedy używać którego wzorca integracji.
- Śledzenie konwersji po stronie serwera przez krótkie linki - rozszerzanie API o przepływ przekazywania konwersji.
- Import masowy kampanii z Arkuszy Google - przerobiony przykład endpointu masowego.
- API skracacza URL: limity szybkości, ponowienia, idempotencja - hartowanie integracji dla ruchu produkcyjnego.
- Uprawnienia kluczy API dla narzędzi do linków - klucze przypisane do workspace'u, ograniczenia ról i rotacja.
- Darmowe API skracacza URL: przykłady kodu, które działają - wywołanie create w curl, JavaScript, Python i Go, i co blokują darmowe poziomy.
- API analityki linków: pobieranie statystyk kliknięć za pomocą klucza API - każdy raport, jego parametry zapytania i codzienny skrypt do Slacka.
- Przewodnik operacyjny: przewodnik po serwerze MCP do łączenia powierzchni API Elido z Claude, Cursor i innymi klientami obsługującymi MCP.
- Powierzchnia produktowa:
/features/api-sdksi/solutions/developers.
Wypróbuj Elido
Wklej URL, otrzymaj krótki link
Bez rejestracji. Link działa 30 dni. Zarejestruj się, aby zachować go na zawsze.
Za darmo, bez rejestracji · 2 dziennie