czytofejk.pl
Dla developerów

Dokumentacja API

Weryfikuj treści programatycznie: obrazy (AI/deepfake), teksty (fake news, manipulacja) i filmy z social mediów (z automatyczną transkrypcją). Analizy zużywają kredyty z Twojego konta — te same, co w serwisie. Klucz wygenerujesz w koncie, zakładka API.

Base URL: https://czytofejk.pl/api/public/v1

Autoryzacja

Każde żądanie wymaga nagłówka Authorization z kluczem w formacie czf_…:

Authorization: Bearer czf_TWOJ_KLUCZ
Bezpieczeństwo klucza: klucz pokazujemy tylko raz przy utworzeniu (przechowujemy wyłącznie jego hash). Używaj go wyłącznie po stronie serwera — nigdy w kodzie przeglądarki ani w publicznym repozytorium. Wyciek? Odwołaj klucz w koncie (działa natychmiast) i utwórz nowy.

Koszty w kredytach

AnalizaKoszt
Tekst (do 1000 znaków — nadmiar ucinamy)10–150 kredytów
Obraz z linku (AI / deepfake)10–60 kredytów
Film z linku (TikTok, YouTube…) — transkrypcja + analiza10–600 kredytów
Duplikat (treść analizowana wcześniej przez kogokolwiek)0 kredytów

Przy starcie blokujemy kaucję (górna wartość widełek), a po analizie oddajemy różnicę — płacisz dokładnie realny koszt operacji. Jeśli analiza zakończy się błędem po naszej stronie, wraca całość. API rozlicza wyłącznie kredyty (doładowania i subskrypcje: cennik).

Limity zapytań

60 zapytań/min na klucz (plan Redakcja: 300/min) dla POST /checks; odczyty statusu i salda: 300/min. Po przekroczeniu: 429 z nagłówkiem Retry-After.

POST /checks — start analizy

Body JSON z dokładnie jednym z pól: text (tekst do weryfikacji albo link do filmu z social mediów) lub image_url (bezpośredni link do obrazu). Opcjonalnie "wait": true — tryb synchroniczny (niżej).

Opcjonalne pole language (pl — domyślne, en, uk) ustawia język treści werdyktu (podsumowanie, uzasadnienie, sygnały). Wartości enum (PRAWDA | MANIPULACJA | FAŁSZ) pozostają bez zmian niezależnie od języka. Uwaga: dedup działa po treści — powtórzone sprawdzenie tej samej treści zwraca istniejący werdykt w języku, w którym go wygenerowano.

Tryb synchroniczny — wynik w jednej odpowiedzi

Z "wait": true trzymamy żądanie otwarte do zakończenia analizy (maks. ~90 s) i zwracamy 200 z gotowym result — bez pollingu. Gdy analiza trwa dłużej (typowo filmy z transkrypcją), dostaniesz zwykłe 202 running i dociągasz wynik GET-em — najlepiej też z ?wait=true (long-poll). Obrazy i teksty kończą się w budżecie niemal zawsze.

curl — synchronicznie (najprościej)

curl -X POST https://czytofejk.pl/api/public/v1/checks \
  -H "Authorization: Bearer czf_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"text": "Rząd potwierdził, że od sierpnia ceny prądu wzrosną o 45%.", "wait": true}'

# → 200 { "id": "…", "status": "done", "result": { "verdict": "FAŁSZ", … } }

curl — asynchronicznie

curl -X POST https://czytofejk.pl/api/public/v1/checks \
  -H "Authorization: Bearer czf_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"text": "Rząd potwierdził, że od sierpnia ceny prądu wzrosną o 45%."}'

# → 202 { "id": "a1b2c3d4e5", "status": "running", … }
# potem (long-poll do wyniku):
curl "https://czytofejk.pl/api/public/v1/checks/a1b2c3d4e5?wait=true" \
  -H "Authorization: Bearer czf_TWOJ_KLUCZ"

JavaScript (Node) — synchronicznie

const res = await fetch("https://czytofejk.pl/api/public/v1/checks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CZYTOFEJK_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    image_url: "https://example.com/zdjecie.jpg",
    wait: true,
  }),
});
const check = await res.json();
if (check.status === "done") console.log(check.result); // gotowy werdykt

Python — async z long-pollem (np. filmy)

import os, requests

API = "https://czytofejk.pl/api/public/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['CZYTOFEJK_API_KEY']}"}

check = requests.post(f"{API}/checks", headers=HEADERS, json={
    "text": "https://www.tiktok.com/@uzytkownik/video/724..."  # film → transkrypcja
}).json()

# long-poll: każde wywołanie czeka do wyniku albo ~90 s
while check.get("status") == "running":
    check = requests.get(
        f"{API}/checks/{check['id']}", params={"wait": "true"},
        headers=HEADERS, timeout=120,
    ).json()

print(check["result"]["verdict"])

Odpowiedź 202 (analiza wystartowała)

{
  "id": "a1b2c3d4e5",
  "status": "running",
  "cost_tokens": 1,
  "result_url": "https://czytofejk.pl/w/a1b2c3d4e5"
}

Duplikat zwraca 200 z "deduped": true i "cost_tokens": 0 (stary wynik, zero kosztu). Pole cost_tokens przy nowym sprawdzeniu to kaucja — realny koszt zobaczysz w wyniku (chargedCredits).

GET /checks/{id}status i wynik

Z ?wait=true (zalecane) żądanie czeka do wyniku — maks. ~90 s na wywołanie, powtarzaj do statusu done. Bez wait zwraca stan natychmiast (wtedy odpytuj co ~2 s). Czasy analiz: obrazy 5–20 s, teksty 10–30 s, filmy z transkrypcją do kilku minut. Status error = kredyty zwrócone automatycznie.

{
  "id": "a1b2c3d4e5",
  "status": "done",
  "result_url": "https://czytofejk.pl/w/a1b2c3d4e5",
  "result": {
    "kind": "tresc",                 // albo "plik" (obraz)
    "verdict": "MANIPULACJA",        // PRAWDA | MANIPULACJA | FAŁSZ
    "verdictSub": "…",               // 1–2 zdania oceny
    "summary": "…",                  // uzasadnienie
    "signals": [{ "strong": true, "text": "…" }],
    "sources": [{ "domain": "…", "title": "…", "url": "…" }]
    // dla kind="plik": "percent" 0–100 (prawdopodobieństwo AI/fałszerstwa),
    // "verdict" np. "AI" / "AUTENTYCZNE" oraz lista sygnałów technicznych
  }
}

GET /balance — saldo kredytów

{
  "plan": "pro",
  "tokens": { "subscription": 184, "topup": 40, "total": 224 }
}

Kody błędów

StatuserrorZnaczenie
401invalid_api_keyBrak/zły/odwołany klucz
402insufficient_tokensZa mało kredytów (pola required, balance)
400invalid_inputPodaj dokładnie jedno pole: text albo image_url
422text_too_short / not_an_imageTreść nie nadaje się do analizy
429rate_limitedLimit zapytań na minutę — odczekaj Retry-After
404not_foundNie ma sprawdzenia o takim id
500analysis_failedBłąd po naszej stronie — spróbuj ponownie

Dobre praktyki

  • Klucz trzymaj w zmiennej środowiskowej po stronie serwera; do każdej integracji osobny klucz (łatwiejsza rotacja i audyt — kolumna „ostatnio użyty” w koncie).
  • Wynik ma stały, publiczny permalink result_url — możesz go linkować czytelnikom jako dowód.
  • Wysyłasz tę samą treść wielokrotnie? Nic nie tracisz — dedup odpowie natychmiast i za darmo.
  • Werdykt to ocena prawdopodobieństwa oparta na dowodach, nie wyrok — przy decyzjach redakcyjnych zajrzyj w signals i sources.

Pytania, wyższe limity, webhooki? Napisz do nas. Wersjonujemy pod /v1 — zmiany łamiące trafią pod nową ścieżkę.