Fellowi

Een NSFW-beeldgeneratie-API voor ontwikkelaars

Door Het Fellowi-team · · 7 min leestijd

Donkere verloopcompositie van violet naar indigo die een ontwikkelaars-API voor AI-beeldgeneratie verbeeldt.

De meeste beeldgeneratie-APIs weigeren NSFW-inhoud principieel, nog voordat je ook maar in de buurt van een technische grens komt. Voor een platform voor algemeen gebruik is dat een verdedigbare keuze, maar het betekent ook dat er bijna niets overblijft voor een ontwikkelaar die echt programmatische toegang nodig heeft tot een generator die volwassenmateriaal toestaat. De publieke API van Fellowi bestaat precies voor dat geval. Hij staat expliciete generatie toe voor geregistreerde volwassen accounts, binnen harde grenzen die nooit verschuiven: geen inhoud waarbij minderjarigen betrokken zijn, geen inhoud die het ontbreken van instemming verbeeldt. Dat zijn geen instellingen die je kunt omzetten - zulke verzoeken worden zonder uitzondering geweigerd.

Verder is het een doodgewone REST-API: een sleutel, een POST die een taak in de wachtrij zet, pollen, downloaden. Heb je eerder met een asynchrone generatie-API gewerkt, dan voelt dit meteen vertrouwd.

Een sleutel aanvragen

Maak een account aan en maak daarna een API-sleutel in de API Console. De sleutel ziet uit als fk_live_<willekeurige tekenreeks> en wordt je precies één keer volledig getoond, bij het aanmaken. Daarna bewaren wij alleen nog een hash en een korte preview - raak je hem kwijt, dan trek je hem in en maak je een nieuwe, net als bij elke andere API-sleutel waarmee je ooit hebt gewerkt. Zet hem ergens veilig neer voordat je het tabblad sluit.

Elk verzoek authenticeert met een standaard bearer-header:

Authorization: Bearer fk_live_your_key_here

Een generatie in de wachtrij zetten

POST /v1/api/images met een prompt en je opties. De call komt direct terug met HTTP 202 - hij blijft niet hangen terwijl de afbeelding rendert:

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"
}

Het antwoord bevat een taak-id, een etaMs-schatting en je resterende coinsaldo na de afschrijving. De optionele Idempotency-Key-header maakt een herhaald verzoek veilig - stuur bij een retry dezelfde sleutel mee en je wordt niet twee keer belast voor dezelfde poging.

De taak zelf staat onder image, met je walletsaldo ernaast:

{
  "image": { "id": "0f9c...", "status": "queued", "etaMs": 42000, "coinsCharged": 40 },
  "coins": 360
}

Pollen, dan downloaden

Poll GET /v1/api/images/:id tot status op "succeeded" of "failed" staat. Bij succes haal je de echte bytes op via GET /v1/api/images/:id/content. Mislukt het, dan worden de bestede coins automatisch teruggestort en is failureCode altijd precies één van vier waarden: TIMEOUT, MODERATION_REJECTED, VENDOR_ERROR of UNKNOWN. Er is geen vijfde code om af te handelen en geen gedeeltelijke afschrijving om recht te trekken - waarom dat zo is, leggen we verder uit in hoe de API geprijsd is en wat er gebeurt als een generatie mislukt.

curl, van begin tot eind

API_KEY="fk_live_your_key_here"

# 1. zet een job in de wachtrij
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. poll tot hij klaar is
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. download de afbeelding
curl -s https://fellowi.com/api/v1/api/images/$ID/content \
  -H "Authorization: Bearer $API_KEY" -o output.png

Node

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, prijzen en limieten

Elk antwoord noemt het model fellowi-nsfw-image-1. Dat is de enige naam die je te zien krijgt - het is dezelfde generator als achter de web-app Fellowi Images, en hij wordt afgerekend op dezelfde Fellowi Coins-wallet tegen dezelfde prijs: 40 coins voor Standard (1,5K), 60 voor High quality (2K). Er is geen aparte API-prijslijst die je tegen die van de web-app moet leggen.

Rate limits zijn een misbruikrem, niet het echte plafond: standaard 20 verzoeken per minuut voor generaties en 120 per minuut voor leesacties. GET /v1/api/me geeft je huidige coinsaldo terug, de rate limit van je sleutel en hoeveel afbeeldingen je vandaag nog over hebt onder het daglimiet - poll dat voordat je een batch wegstuurt, niet nadat je tegen een muur bent gelopen.

De volledige referentiedocumentatie, actuele prijzen en het sleutelbeheer staan allemaal in de API Console.

Probeer het zelf

Een warme, private AI-companion: 7 dagen gratis met 30 berichten, zonder kaart.

Prijzen en limieten

Verder lezen