Une API de génération d'images NSFW pour les développeurs
Par L'équipe Fellowi · · 7 min de lecture

La plupart des API de génération d'images refusent le contenu NSFW par principe, avant même d'atteindre une limite technique quelconque. C'est un choix raisonnable pour une plateforme généraliste, mais cela ne laisse presque rien pour un développeur qui a réellement besoin d'un accès programmatique à un générateur autorisant le contenu adulte. L'API publique de Fellowi existe pour ce cas précis. Elle autorise la génération explicite pour les comptes adultes inscrits, sous des limites strictes qui ne bougent jamais : aucun contenu impliquant des mineurs, aucun contenu représentant une absence de consentement. Ce ne sont pas des réglages qu'on peut basculer - ces demandes sont refusées, sans exception.
En dehors de cela, c'est une API REST classique : une clé, un POST qui met une tâche en file d'attente, un polling, un téléchargement. Si vous avez déjà utilisé une autre API de génération asynchrone, cela vous paraîtra familier.
Obtenir une clé
Créez un compte, puis créez une clé API sur l'API Console. La clé ressemble à fk_live_<chaîne aléatoire> et vous est montrée en entier une seule fois, à sa création. Ensuite, seuls un hash et un court aperçu sont conservés de notre côté - si vous la perdez, révoquez-la et créez-en une nouvelle, comme pour n'importe quelle autre clé API que vous avez déjà manipulée. Sauvegardez-la quelque part de fiable avant de fermer l'onglet.
Chaque requête s'authentifie avec un en-tête bearer standard :
Authorization: Bearer fk_live_your_key_hereMettre une génération en file d'attente
POST /v1/api/images avec un prompt et vos options. L'appel renvoie immédiatement un HTTP 202 - il ne bloque pas pendant le rendu :
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"
}La réponse contient un id de tâche, une estimation etaMs, et votre solde de coins restant après le débit. L'en-tête optionnel Idempotency-Key rend une nouvelle tentative sûre - envoyez la même clé lors d'une relance, et vous ne serez pas débité deux fois pour la même tentative.
La tâche elle-même se trouve sous image, avec le solde de votre portefeuille à côté :
{
"image": { "id": "0f9c...", "status": "queued", "etaMs": 42000, "coinsCharged": 40 },
"coins": 360
}Polling, puis téléchargement
Interrogez GET /v1/api/images/:id jusqu'à ce que status passe à "succeeded" ou "failed". En cas de succès, récupérez les octets réels via GET /v1/api/images/:id/content. En cas d'échec, les coins dépensés sont remboursés automatiquement, et failureCode vaut toujours l'une de ces quatre valeurs exactement : TIMEOUT, MODERATION_REJECTED, VENDOR_ERROR, ou UNKNOWN. Il n'y a pas de cinquième code à gérer, ni de débit partiel à réconcilier - nous expliquons pourquoi plus en détail dans notre article sur la tarification de l'API et la gestion des échecs.
curl, de bout en bout
API_KEY="fk_live_your_key_here"
# 1. mettre une tâche en file d'attente
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. interroger jusqu'à la fin
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. télécharger l'image
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)Modèle, tarifs et limites
Chaque réponse indique le modèle comme fellowi-nsfw-image-1. C'est le seul nom que vous verrez - c'est le même générateur que celui derrière l'application web Fellowi Images, et il est facturé sur le même portefeuille Fellowi Coins, au même prix : 40 coins pour Standard (1,5K), 60 pour la haute qualité (2K). Il n'existe pas de grille tarifaire séparée pour l'API à réconcilier avec l'application web.
Les limites de débit sont une protection contre les abus, pas le vrai plafond : par défaut, 20 requêtes par minute pour les générations, 120 par minute pour les lectures. GET /v1/api/me renvoie votre solde de coins actuel, la limite de votre clé, et combien d'images il vous reste aujourd'hui sous le plafond quotidien - vérifiez-le avant de lancer un lot, pas après avoir buté sur un mur.
La documentation complète, les tarifs en direct et la gestion des clés se trouvent sur l'API Console.
Essayez par vous-même
Une compagne IA chaleureuse et privée : 7 jours gratuits et 30 messages, sans carte.