Dokumentacja API
Sprawdzarka Widoczności AI udostępnia dwa publiczne endpointy JSON. GET /api/report/:domain.json nie wymaga klucza API. POST /api/scan można uwierzytelnić na trzy sposoby — widżetem Turnstile publicznego formularza, darmowym, samodzielnie zakładanym kluczem API klienta lub wewnętrznym tokenem bearer dla bezpośrednich integracji ustawianym przez właściciela strony — zobacz poniżej. Oba endpointy są ograniczone limitami według adresu IP (klucze API klientów dodatkowo mają własny limit per klucz — zobacz „Limity szybkości” i „Uwierzytelnianie” poniżej).
Limity szybkości
- 8 nowych skanów na adres IP na godzinę (żądania anonimowe / Turnstile)
- 3 nowe skany na domenę docelową na godzinę
- 60 nowych skanów na godzinę na jeden samodzielnie założony klucz API klienta — własna pula, nie dzielona z kluczami innych klientów ani z ruchem anonimowym. Zobacz „Uwierzytelnianie” poniżej, jak go zdobyć — jest darmowy.
Wyniki z pamięci podręcznej (do 24 godzin) są zwracane natychmiast i nie liczą się do żadnego z tych limitów.
POST /api/scan
Uruchamia skan lub pobiera zapisany wynik dla domeny.
Uwierzytelnianie
Istnieją trzy sposoby uwierzytelnienia żądania do tego endpointu:
-
Widżet Turnstile (tylko przeglądarka) — publiczny formularz skanowania na tej stronie rozwiązuje niewidoczne wyzwanie Cloudflare Turnstile i wysyła wynikowy
turnstileTokenw treści żądania. Ta ścieżka działa wyłącznie z prawdziwej przeglądarki wczytującej formularz; nie jest dostępna dla bezpośrednich wywołań API. -
Darmowy, samodzielnie zakładany klucz API klienta —
załóż darmowe konto pod adresem
/account/signup,
a następnie wygeneruj nazwany klucz API w swoim
account dashboard.
Wyślij go jako
Authorization: Bearer uvk_...i całkowicie pomińturnstileToken. Każdy klucz dostaje własną pulę limitu 60 skanów/godzinę — wyższą niż anonimowy limit 8/godzinę, i nie dzieloną z kluczami innych klientów ani z ruchem anonimowym. Nie ma żadnej płatności ani niczego do ulepszenia; jedynymi różnicami względem użycia anonimowego są wyższy limit oraz trwały, nazwany, indywidualnie odwoływalny klucz. Klucze są pokazywane w pełni tylko raz, przy tworzeniu, a odwołany klucz natychmiast przestaje działać dla nowych żądań (skan w tle rozpoczęty tuż przed odwołaniem może się jeszcze zakończyć). Rejestracja wymaga tylko adresu e-mail wyglądającego na poprawny oraz hasła o długości co najmniej 12 znaków — nie ma jeszcze weryfikacji e-mail ani procesu resetu hasła (ta aplikacja nie ma obecnie żadnej możliwości wysyłania e-maili transakcyjnych), a sama rejestracja jest chroniona tym samym sprawdzeniem Turnstile i limitami co logowanie administratora. -
Wewnętrzny
PIPELINE_TOKEN(klienci programowi ustawiani przez właściciela strony) — wyślijAuthorization: Bearer <token>i całkowicie pomińturnstileToken. Nie ma samodzielnej rejestracji dla tego tokena — skontaktuj się z właścicielem strony, aby go uzyskać. (Jeśli chcesz po prostu mieć własny klucz już dziś, skorzystaj zamiast tego z darmowej opcji samodzielnej rejestracji powyżej.)
Nie masz tokena? Załóż darmowe konto pod adresem /account/signup aby wygenerować własny klucz API z wyższym limitem (60 skanów/godzinę vs 8/godzinę anonimowo).
Jeśli nagłówek Authorization jest obecny, ale token się nie zgadza — błędny/nieznany PIPELINE_TOKEN, albo samodzielny klucz, który jest nieprawidłowy, nieznany lub odwołany — żądanie kończy się błędem 401 { "error": "Unauthorized" }. Jeśli nagłówek Authorization w ogóle nie zostanie wysłany, zachowanie jest takie jak wcześniej: wymagany jest prawidłowy turnstileToken, w przeciwnym razie żądanie kończy się błędem 403 { "error": "Verification failed. Please retry." }.
Agenci AI lub narzędzia mówiące w MCP mogą pominąć to wszystko i wywołać zamiast tego POST /mcp, który nie wymaga żadnego uwierzytelnienia — zobacz sekcję „MCP server + WebMCP” w README.
Limitowanie szybkości dla wewnętrznego PIPELINE_TOKEN jest takie samo jak dla odwiedzających z przeglądarki: klienci z kluczem dzielą te same limity per IP i per domena docelowa opisane powyżej, więc intensywne użycie programowe może wciąż trafić na limit per IP. Samodzielnie zakładane klucze API klientów działają inaczej — każdy klucz ma własną pulę 60/godzinę (zobacz „Limity szybkości” powyżej), niezależną od adresu IP wywołującego.
Treść żądania
{
"url": "example.com",
"forceRescan": false
}
Odpowiedzi
| Status | Treść | Znaczenie |
|---|---|---|
200 |
ScanRecord |
Trafienie w pamięci podręcznej — wynik jest już świeży (do 24 godz.). |
202 |
{ "domain": "example.com" } |
Skan uruchomiony w tle — odpytuj GET /api/report/:domain.json, aż zwróci 200. |
400 |
{ "error": "..." } |
Błędny lub nierozwiązywalny adres URL. |
401 |
{ "error": "Unauthorized" } |
Wysłano nagłówek Authorization: Bearer, ale token się nie zgadzał. |
403 |
{ "error": "Verification failed. Please retry." } |
Nie wysłano nagłówka Authorization, a sprawdzenie Turnstile nie powiodło się lub turnstileToken był brakujący/nieprawidłowy. |
429 |
{ "error": "...", "retryAfterSeconds": N } |
Przekroczono limit szybkości. Poczekaj retryAfterSeconds przed ponowną próbą. |
Przykład curl
curl -X POST https://aivisibility.unomage.pl/api/scan \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"url":"example.com"}'
Pomiń nagłówek Authorization tylko wtedy, gdy wywołujesz ten endpoint z przeglądarki, która już dostarcza token Turnstile w treści żądania — bezpośredni/skryptowi klienci potrzebują tokena bearer pokazanego powyżej. YOUR_TOKEN może być zarówno samodzielnym kluczem API uvk_... z panelu konta, jak i wewnętrznym PIPELINE_TOKEN — oba są akceptowane w ten sam sposób.
GET /api/report/:domain.json
Pobiera pełny ScanRecord dla domeny. Zwraca 404, jeśli domena nigdy nie była skanowana.
Odpowiedzi
| Status | Treść | Znaczenie |
|---|---|---|
200 |
ScanRecord |
Pełny zapis dla domeny. |
404 |
{ "error": "Not found" } |
Domena nie została jeszcze zeskanowana. |
Przykład curl
curl https://aivisibility.unomage.pl/api/report/example.com.json
Kształt ScanRecord
{
"domain": "example.com",
"status": "ok" | "failed",
"scannedAt": "ISO 8601 string",
"result": {
"score": 0-100,
"grade": "A" | "B" | "C" | "D" | "F",
"label": "string",
"pillars": [
{
"id": "string",
"title": "string",
"score": 0-100,
"points": 0-100,
"weight": 0-100,
"signals": [ /* see below */ ]
}
],
"topIssues": [
{
"id": "string",
"title": "string",
"status": "fail" | "warn",
"impact": "critical" | "high" | "medium" | "low",
"detail": "string",
"fix": {
"what": "string",
"why": "string",
"how": "string",
"effort": "S" | "M" | "L"
}
}
]
} | null,
"offSite": {
"wikidata": { "status": "found" | "not_found" | "unknown", "detail": "string", "url": "string | null" },
"wikipedia": { "status": "found" | "not_found" | "unknown", "detail": "string", "url": "string | null" },
"commonCrawl": { "status": "found" | "not_found" | "unknown", "detail": "string", "url": "string | null" }
} | null
}
result to null, gdy status ma wartość "failed". offSite to null dla skanów wykonanych zanim dodano sprawdzanie sygnałów zewnętrznych, lub gdy samo sprawdzenie się nie powiodło.
Wzorzec odpytywania
Gdy POST /api/scan zwróci 202, skan działa w tle. Odpytuj GET /api/report/:domain.json co 1–2 sekundy, aż zwróci 200:
# 1. Start the scan
curl -s -X POST https://aivisibility.unomage.pl/api/scan \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"url":"example.com"}' | jq .
# 2. Poll until ready (bash loop)
while true; do
result=$(curl -s https://aivisibility.unomage.pl/api/report/example.com.json)
echo "$result" | jq '.status' && break || sleep 2
done