Requêtes
Une requête correspond à un appel d’un modèle. Elle possède un identifiant (req_…), un statut, son coût en crédits API (1000 = 1 USD) et, lorsqu’elle réussit, les fichiers générés. Le même objet est renvoyé par chaque point de terminaison ci-dessous, pour chaque modèle.
Trouver un modèle
Le catalogue des 1 496 modèles est un JSON public (aucune clé requise) :
curl "https://api.doitong.com/v1/models?category=text-to-video&lab=Google&limit=20"
| Paramètre de requête | Signification |
|---|---|
q |
Mots qui doivent tous apparaître dans le nom, l’identifiant, le fabricant ou les tags, par exemple kling 3. |
category |
Un identifiant de catégorie, par exemple text-to-video ou upscale. GET https://api.doitong.com/v1/categories répertorie les 21 catégories avec leur nombre d’éléments. |
lab |
Le fabricant du modèle, par nom ou identifiant, par exemple Google ou black-forest-labs. |
family |
Un identifiant family provenant d’une ligne précédente : chaque variante d’un modèle (pro, fast, image-to-video, …). |
mode |
exact (le prix est calculé à partir de l’entrée), measured (à partir de la longueur ou de la taille des fichiers d’entrée), estimate (un prix estimé par exécution) ou metered (facturé selon l’utilisation réelle, jusqu’à un maximum par exécution). |
limit, cursor |
Taille de page (de 1 à 100, 50 par défaut) et next_cursor de la page précédente. |
Chaque ligne contient id, name, lab, category, family, summary, tags, output_kind, docs_url et un objet price (voir Tarification). GET https://api.doitong.com/v1/models/{model_id} ajoute le schéma JSON complet des entrées et sorties, les noms canoniques des paramètres, les règles de tarification et un exemple d’entrée. Une category ou un mode inconnu renvoie 400 invalid_parameter.
Exécuter un modèle
curl -X POST "https://api.doitong.com/v1/run/{model_id}?wait=20" \
-H "Authorization: Bearer $DOITONG_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1842-cover" \
-d '{"prompt": "..."}'
- Le corps contient l’entrée du modèle, sous forme d’objet JSON. Chaque page de modèle répertorie ses paramètres.
- L’entrée est vérifiée avant toute facturation. Une entrée non valide renvoie
422 invalid_inputavec leparamconcerné et ne coûte rien. ?wait=N(jusqu’à 20 secondes) maintient l’appel ouvert jusqu’à la fin de la requête ou l’expiration du délai.?webhook_url=https://…envoie un POST signé à cette URL lorsque la requête se termine (voir Webhooks).?storage=permanentou?storage=temporarydétermine la durée de conservation des fichiers de sortie ; sans ce paramètre, le réglage du compte s’applique (voir Emplacement des fichiers).
La réponse est 202 Accepted tant que la requête est en cours, et 200 OK lorsqu’elle s’est terminée pendant l’attente (ou lorsqu’il s’agit d’une nouvelle lecture, voir ci-dessous). Les en-têtes Location et Doitong-Request-Id contiennent l’URL et l’identifiant de la requête.
Statuts
-
queuedAcceptée et facturée, en attente d’un processus -
runningLe modèle génère le résultat -
États finaux:
succeededDevis facturé ; outputs[] contient des URL sur notre stockagefailedRemboursée automatiquement ; l’erreur en indique la raisoncanceledArrêtée avant l’obtention d’un résultat ; remboursée
| Statut | Signification | Final |
|---|---|---|
queued |
Acceptée et facturée, en attente d’un worker. queue_position peut indiquer sa position dans la file. |
non |
running |
Le modèle génère le résultat. | non |
succeeded |
Terminée. outputs répertorie les fichiers. |
oui |
failed |
Le modèle ou une limite l’a arrêtée. error en indique la raison. Les crédits API sont remboursés. |
oui |
canceled |
Annulée avant de produire un résultat. Les crédits API sont remboursés. | oui |
Une requête qui dépasse sa limite de temps échoue avec le code timeout et est remboursée : 15 minutes pour les images, 60 minutes pour les vidéos, 30 minutes pour l’audio et tout le reste.
L’objet requête
{
"id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
"object": "request",
"model": "flux/schnell",
"status": "succeeded",
"created_at": "2026-10-20T12:00:00Z",
"started_at": "2026-10-20T12:00:01Z",
"completed_at": "2026-10-20T12:00:02Z",
"queue_position": null,
"cost": { "credits": 3, "usd": "0.003", "charged": 3, "refunded": 0 },
"input": { "prompt": "..." },
"output": { "images": [ { "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "width": 1024, "height": 768 } ] },
"outputs": [
{ "type": "image", "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "content_type": "image/jpeg",
"width": 1024, "height": 768, "file_size": 183920, "stored": true }
],
"error": null,
"metrics": { "inference_seconds": 1.2 },
"storage": { "mode": "permanent", "bytes": 183920, "expires_at": null, "expired": false },
"urls": {
"self": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
"cancel": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
}
}
outputsest identique pour tous les modèles : une entrée par fichier généré avectype(image,video,audio,fileou3d), uneurlsur notre stockage,content_typeet, lorsqu’elles sont connues,file_size,width,height,duration.outputest l’objet de résultat propre au modèle (ses champs sont répertoriés sur chaque page de modèle), avec les mêmes URL.storageindique comment les fichiers sont conservés :mode(permanentoutemporary),bytesstockés,expires_at(date de suppression d’un fichier temporaire,nullpour les fichiers permanents) etexpired(trueune fois les fichiers supprimés).cost.creditsest le prix de l’appel en crédits API (cost.usden USD),cost.chargedle montant débité du solde API, etcost.refundedle montant remboursé. Pour un modèlemetered,cost.creditscorrespond au maximum bloqué au début (cost.held) ; une fois l’exécution réussie,cost.settledindique le montant correspondant à l’utilisation et le reste du maximum figure danscost.refunded(voir Facturation selon l’utilisation).- Lorsqu’une requête échoue,
errorvaut{ "type": …, "code": …, "message": … }.
Lire une requête
curl "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t?wait=20" \
-H "Authorization: Bearer $DOITONG_API_KEY"
?wait=N(jusqu’à 20 secondes) effectue une attente longue : l’appel renvoie dès que la requête est finale, ou après N secondes avec l’état actuel. Répéter cet appel est le moyen le plus simple d’attendre un résultat.?logs=1ajoute les lignes du journal de progression du modèle (les 50 dernières) souslogs.
Vous pouvez uniquement lire les requêtes de votre propre compte ; tout autre identifiant renvoie 404 request_not_found.
Répertorier les requêtes
curl "https://api.doitong.com/v1/requests?limit=20&status=succeeded&model=flux/schnell" \
-H "Authorization: Bearer $DOITONG_API_KEY"
De la plus récente à la plus ancienne. limit va de 1 à 100 (20 par défaut) ; status et model servent de filtres. La réponse est { "object": "list", "data": [ … ], "has_more": true, "next_cursor": "req_…" } ; transmettez cursor=<next_cursor> pour obtenir la page suivante.
Annuler une requête
curl -X POST "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel" \
-H "Authorization: Bearer $DOITONG_API_KEY"
- Annulée avant le démarrage du modèle : le statut devient
canceled, les crédits API sont remboursés et vous recevez200. - Déjà en cours de génération : l’annulation est transmise et vous recevez
202avec"cancel_requested": true. Si le modèle termine malgré tout, la requête réussit normalement et est facturée. - Déjà finale :
409 not_cancelable(une requête déjàcanceledrenvoie simplement200).
Supprimer les fichiers d’une requête
curl -X DELETE "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/files" \
-H "Authorization: Bearer $DOITONG_API_KEY"
Supprime immédiatement nos copies des fichiers de sortie de la requête et arrête leur facturation de stockage. La réponse est l’objet requête avec storage.expired: true ; ses URL restent dans l’enregistrement, mais ne fonctionnent plus. Un nouvel appel ne change rien (200). Une requête encore queued ou running n’a pas encore de fichiers : 409 request_active. Nécessite models:run.
Idempotence : réessayer sans payer deux fois
Les réseaux peuvent tomber en panne. Pour réessayer une exécution en toute sécurité, envoyez un en-tête Idempotency-Key (toute chaîne de 255 caractères maximum, unique par opération, par exemple votre propre identifiant de commande) :
- Même clé et même corps qu’auparavant : vous récupérez la requête d’origine (
200, en-têteIdempotent-Replayed: true) et rien n’est facturé à nouveau. - Même clé et même corps après une exécution ayant échoué avant d’atteindre le modèle (
upstream_errorouinternal_errorlors de la soumission,insufficient_credits,budget_exceeded,too_many_inflight) : rien n’a été produit et rien n’est facturé ; la nouvelle tentative exécute donc à nouveau le modèle au lieu de renvoyer l’échec. - Même clé avec un corps différent :
409 idempotency_mismatch. - Les clés sont limitées à la clé API qui les a envoyées.
Emplacement des fichiers
Chaque fichier de sortie est copié dans notre stockage avant que la requête soit marquée succeeded ; les URL de outputs se trouvent donc sur nos propres hôtes et vous pouvez les utiliser directement. Vous choisissez leur durée de conservation :
| Mode | Durée | Prix |
|---|---|---|
permanent (par défaut) |
Jusqu’à leur suppression | 100 crédits API (0,10 $) par Go et par mois, facturés quotidiennement sur le solde API |
temporary |
7 jours, puis suppression | Gratuit |
- Le réglage du compte s’applique aux nouvelles requêtes : le bouton « Conserver les fichiers indéfiniment » du tableau de bord, ou
PATCH https://api.doitong.com/v1/account/storageavec{"mode": "temporary"}.GET https://api.doitong.com/v1/accountl’affiche sousstorage, avec les octets conservés et l’estimation mensuelle. ?storage=permanent|temporarylors d’une exécution (l’argumentstoragede l’outil MCPrun) remplace ce réglage pour cette exécution.- Modifier le réglage ne touche jamais aux fichiers déjà présents ; supprimez-les avec
DELETE /requests/{id}/files. - Lorsque le solde API ne peut pas payer le stockage, rien n’est facturé et vous recevez un e-mail : rechargez votre solde dans les 30 jours, sinon les fichiers conservés deviennent temporaires et sont supprimés 7 jours plus tard.
Dans le rare cas où notre copie échoue, l’entrée contient "stored": false et l’URL est celle d’origine, à durée de vie limitée : téléchargez-la rapidement.