API do generowania obrazów NSFW dla programistów
Autor: Zespół Fellowi · · 7 min czytania

Większość API do generowania obrazów odmawia treści NSFW z zasady, jeszcze zanim w ogóle dojdziesz do jakiegokolwiek ograniczenia technicznego. Dla platformy ogólnego przeznaczenia to sensowna decyzja, ale programiście, który naprawdę potrzebuje programowego dostępu do generatora dopuszczającego treści dla dorosłych, nie zostaje praktycznie nic. Publiczne API Fellowi istnieje właśnie dla tego przypadku. Pozwala na generowanie treści dla dorosłych na zarejestrowanych, pełnoletnich kontach, w ramach twardych ograniczeń, które nigdy się nie zmieniają: żadnych treści z udziałem osób nieletnich, żadnych treści przedstawiających brak zgody. To nie są ustawienia, które da się przestawić - takie prośby są odrzucane bez wyjątków.
Poza tym to zwyczajne API REST: klucz, POST, który wstawia zadanie do kolejki, odpytywanie, pobranie. Jeśli pracowałaś lub pracowałeś kiedyś z jakimkolwiek asynchronicznym API do generowania, poczujesz się tu jak w domu.
Zdobądź klucz
Utwórz konto, a potem stwórz klucz API w API Console. Klucz wygląda tak: fk_live_<losowy ciąg znaków>, i widzisz go w całości dokładnie raz, w chwili tworzenia. Później po naszej stronie zostaje tylko skrót i krótki podglądowy fragment - jeśli go zgubisz, unieważniasz go i tworzysz nowy, tak samo jak przy każdym innym kluczu API, z jakim miałaś lub miałeś do czynienia. Zapisz go w porządnym miejscu, zanim zamkniesz kartę przeglądarki.
Każde żądanie uwierzytelnia się standardowym nagłówkiem bearer:
Authorization: Bearer fk_live_your_key_hereWstaw generowanie do kolejki
POST /v1/api/images z promptem i twoimi opcjami. Wywołanie wraca natychmiast z kodem HTTP 202 - nie blokuje się na czas renderowania obrazu:
POST /v1/api/images
Content-Type: application/json
Authorization: Bearer fk_live_your_key_here
Idempotency-Key: a-key-you-generate-per-attempt
{
"prompt": "a neon-lit rooftop at night, wide shot, cinematic lighting",
"quality": "standard",
"format": "png",
"aspectRatio": "16:9"
}W odpowiedzi dostajesz id zadania, szacowany czas etaMs oraz stan monet po obciążeniu. Opcjonalny nagłówek Idempotency-Key sprawia, że ponowienie żądania jest bezpieczne - wyślij ten sam klucz przy powtórce i nie zapłacisz dwa razy za tę samą próbę.
Samo zadanie leży pod image, a obok niego stan portfela:
{
"image": { "id": "0f9c...", "status": "queued", "etaMs": 42000, "coinsCharged": 40 },
"coins": 360
}Odpytuj, potem pobierz
Odpytuj GET /v1/api/images/:id, dopóki status nie osiągnie "succeeded" albo "failed". Po sukcesie pobierz właściwe bajty z GET /v1/api/images/:id/content. Jeśli generowanie się nie uda, wydane monety wracają automatycznie, a failureCode zawsze przyjmuje jedną z dokładnie czterech wartości: TIMEOUT, MODERATION_REJECTED, VENDOR_ERROR albo UNKNOWN. Nie ma piątego kodu do obsłużenia ani częściowego obciążenia do rozliczenia - dlaczego tak jest, opisujemy dokładniej w tekście o cenach API i o tym, co się dzieje, gdy generowanie zawodzi.
curl, od początku do końca
API_KEY="fk_live_your_key_here"
# 1. dodaj zadanie do kolejki
JOB=$(curl -s https://fellowi.com/api/v1/api/images \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"a neon-lit rooftop at night","quality":"standard","format":"png","aspectRatio":"16:9"}')
ID=$(echo "$JOB" | jq -r .image.id)
# 2. pytaj, dopóki nie będzie gotowe
while true; do
STATUS=$(curl -s https://fellowi.com/api/v1/api/images/$ID \
-H "Authorization: Bearer $API_KEY" | jq -r .image.status)
[ "$STATUS" = "succeeded" ] && break
[ "$STATUS" = "failed" ] && { echo "generation failed"; exit 1; }
sleep 3
done
# 3. pobierz obraz
curl -s https://fellowi.com/api/v1/api/images/$ID/content \
-H "Authorization: Bearer $API_KEY" -o output.pngNode
const API_KEY = process.env.FELLOWI_API_KEY;
const base = "https://fellowi.com/api/v1/api";
const headers = { Authorization: `Bearer ${API_KEY}` };
const create = await fetch(`${base}/images`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "a neon-lit rooftop at night", quality: "standard", format: "png", aspectRatio: "16:9" }),
});
const { image } = await create.json();
const id = image.id;
let job;
do {
await new Promise((r) => setTimeout(r, 3000));
job = await fetch(`${base}/images/${id}`, { headers }).then((r) => r.json());
} while (job.image.status !== "succeeded" && job.image.status !== "failed");
if (job.image.status === "failed") throw new Error(job.image.failureCode);
const bytes = await fetch(`${base}/images/${id}/content`, { headers }).then((r) => r.arrayBuffer());
await Bun.write("output.png", bytes);Python
import os, time, requests
API_KEY = os.environ["FELLOWI_API_KEY"]
base = "https://fellowi.com/api/v1/api"
headers = {"Authorization": f"Bearer {API_KEY}"}
job = requests.post(f"{base}/images", headers=headers, json={
"prompt": "a neon-lit rooftop at night",
"quality": "standard",
"format": "png",
"aspectRatio": "16:9",
}).json()
while True:
time.sleep(3)
status = requests.get(f"{base}/images/{job['image']['id']}", headers=headers).json()
if status["image"]["status"] in ("succeeded", "failed"):
break
if status["image"]["status"] == "failed":
raise RuntimeError(status["image"]["failureCode"])
content = requests.get(f"{base}/images/{job['image']['id']}/content", headers=headers)
open("output.png", "wb").write(content.content)Model, ceny i limity
Każda odpowiedź podaje model jako fellowi-nsfw-image-1. To jedyna nazwa, jaką zobaczysz - stoi za nią ten sam generator, który napędza aplikację webową Fellowi Images, i rozlicza się z tego samego portfela Fellowi Coins po tej samej cenie: 40 monet za Standard (1,5K), 60 za High quality (2K). Nie ma osobnego cennika dla API, który trzeba by uzgadniać z cennikiem aplikacji webowej.
Limity zapytań to zabezpieczenie przed nadużyciami, a nie prawdziwy pułap: domyślnie 20 żądań na minutę dla generowania i 120 na minutę dla odczytów. GET /v1/api/me zwraca aktualny stan monet, limit twojego klucza i to, ile obrazów zostało ci dzisiaj w ramach dziennego pułapu - sprawdź to przed wysłaniem większej paczki zadań, a nie po tym, jak uderzysz w ścianę.
Pełna dokumentacja, aktualne ceny i zarządzanie kluczami znajdują się w API Console.