API

Commandez des services depuis votre propre site, boutique ou script : listez les services et leurs prix, passez des commandes avec la tâche à réaliser, suivez-les et récupérez les résultats. C’est le même service que sur le site : les commandes passées via l’API apparaissent aussi dans votre compte.

Premiers pas

  1. Connectez-vous et ouvrez Solde et clés API.
  2. Créez une clé. Elle n’est affichée qu’une seule fois : copiez-la et gardez-la secrète, comme un mot de passe. Vous pouvez révoquer une clé à tout moment.
  3. Rechargez votre solde. Les commandes passées via l’API sont payées à partir de celui-ci, en dollars américains.

Envoyez la clé avec chaque requête :

Authorization: Bearer dlx_your_key

Adresse de l’API : https://dleex.com/api/v1. Les requêtes et les réponses sont au format JSON. Les prix et les montants sont exprimés en cents américains entiers : 1500 signifie 15,00 $.

Services

GET /services liste ce qui peut être commandé.

curl https://dleex.com/api/v1/services -H "Authorization: Bearer dlx_your_key"
[
  {
    "service": "seo-article",
    "category": "seo",
    "title": { "en": "SEO article", "ru": "SEO-статья" },
    "linkRequired": false,
    "files": null,
    "script": null,
    "briefQuestions": [
      { "q": { "en": "What is the article about?", "ru": "О чём статья?" }, "hint": { "en": "The topic, or a link to the page.", "ru": "..." } },
      { "q": { "en": "Who will read it?", "ru": "..." } }
    ],
    "packages": [
      { "tier": "basic", "title": { "en": "...", "ru": "..." }, "priceUsdCents": 1500, "days": 2, "revisions": 1 },
      { "tier": "standard", "...": "..." },
      { "tier": "premium", "...": "..." }
    ],
    "addons": [
      {
        "id": 7,
        "title": { "en": "Express delivery", "ru": "Срочное выполнение" },
        "description": null,
        "priceUsdCents": 1000,
        "extraDays": -1,
        "tiers": ["standard", "premium"]
      }
    ]
  }
]

days indique la durée du travail ; revisions indique combien de fois vous pouvez demander des retouches. addons sont les options que vous pouvez commander avec les formules listées dans tiers : leur prix s’ajoute à celui de la formule, et extraDays à son délai (valeur négative : plus rapide, jamais moins d’un jour). briefQuestions sont les questions que le service pose sur la tâche, certaines accompagnées d’un hint ; répondez-y dans answers lorsque vous passez une commande. La liste est vide quand un service ne pose aucune question. linkRequired vaut true pour un service réalisé à partir de ce qu’ouvre un lien, comme un profil ou une publication, ou un enregistrement à sous-titrer : une commande de ce service nécessite link.

files vaut null pour un service qui n’accepte aucun fichier avec le brief. Sinon, il indique lesquels il accepte, par exemple {"accept": ["image"], "maxFiles": 3, "maxMb": 5, "required": true, "insteadOfLink": false} : les types (image, audio, video), le nombre de fichiers par brief ou par demande de retouches, la taille maximale de chaque fichier en Mo, si le brief en exige au moins un, et si un fichier peut remplacer link (linkRequired reste alors true pour les commandes envoyées sans fichier). Voir Fichiers.

script vaut null pour un service qui ne lit aucun texte à voix haute. Un service de voix off indique le texte le plus long que lit chaque formule, en caractères, par exemple {"maxChars": {"basic": 1000, "standard": 3000, "premium": 9000}} : ses commandes nécessitent script, le texte à lire mot pour mot. L’enregistrement est lu par une voix de synthèse : où que vous le publiiez, indiquez à vos auditeurs que la voix est synthétique (voir les Conditions d’utilisation).

Solde

GET /balance

{ "balanceUsdCents": 10000, "currency": "USD" }

Passer une commande

POST /orders. Le prix (la formule et les options, moins une éventuelle remise) est débité du solde et le travail commence aussitôt.

Champ
serviceobligatoireService issu de /services
tierobligatoirebasic, standard ou premium
textobligatoire sans answers, script ni awaitBriefLa tâche : ce qu’il faut faire, jusqu’à 10 000 caractères. Avec script : comment le lire (ton, rythme, prononciation des noms)
linkfacultatifUn lien vers la page, le profil ou la publication, ou vers un enregistrement : un lien direct vers le fichier, ou un lien Dropbox ou Yandex Disk. Obligatoire lorsque linkRequired vaut true
answersfacultatifRéponses aux briefQuestions du service : [{"q": "question", "a": "answer"}], jusqu’à 8, chaque réponse jusqu’à 5 000 caractères
scriptobligatoire lorsque script dans /services ne vaut pas null, refusé ailleursLe texte à lire à voix haute, mot pour mot, dans la limite du maxChars de la formule (20 000 caractères au maximum, un saut de ligne comptant pour un). Laissez une ligne vide entre les paragraphes
localefacultatifLangue du résultat, en ou ru. Par défaut, la langue de votre compte
addonsfacultatifIdentifiants des options de /services proposées pour cette formule, par exemple [7]
promoCodefacultatifUn code promo ; s’il ne s’applique pas, la commande n’est pas passée (voir Erreurs)
awaitBrieffacultatiftrue pour envoyer le brief plus tard, après avoir téléversé les fichiers : la commande est payée et attend avec le statut awaiting_brief. Omettez alors text, link, answers et script. Voir Fichiers
curl https://dleex.com/api/v1/orders -H "Authorization: Bearer dlx_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: <your-order-id>" \
  -d '{"service":"seo-article","tier":"basic","text":"An article about trail running shoes, 5 keywords: ..."}'

Idempotency-Key est facultatif et permet de répéter la requête en toute sécurité ; chaque nouvelle commande nécessite une nouvelle clé. Voir Idempotence ci-dessous.

Indiquez soit text, soit au moins une réponse, soit les deux ; pour une voix off, script suffit. Écrivez chaque question dans q telle qu’elle figure dans briefQuestions, dans la langue de la commande, et omettez celles auxquelles vous n’avez pas de réponse :

{
  "service": "seo-article",
  "tier": "basic",
  "answers": [
    { "q": "What is the article about?", "a": "Choosing trail running shoes" },
    { "q": "Who will read it?", "a": "Runners moving from road to trail" }
  ]
}

La réponse est la commande (statut 201) :

{
  "id": 1042,
  "status": "in_progress",
  "service": "seo-article",
  "tier": "basic",
  "priceUsdCents": 1500,
  "addons": [],
  "discountUsdCents": 0,
  "promoCode": null,
  "locale": "en",
  "text": "An article about trail running shoes...",
  "link": null,
  "answers": [],
  "script": null,
  "fileIds": [],
  "files": [],
  "revisionsLeft": 1,
  "createdAt": "2026-10-16T11:00:00.000Z",
  "dueAt": "2026-10-18T11:00:00.000Z",
  "deliveredAt": null,
  "autoAcceptAt": null,
  "completedAt": null,
  "results": []
}

Fichiers

Certains services travaillent à partir des fichiers du client, comme des photos de pages à retranscrire ou un enregistrement à sous-titrer : leur files dans /services ne vaut pas null. Les fichiers sont téléversés sur une commande qui attend son brief :

  1. Passez la commande avec "awaitBrief": true et sans text, link, answers ni script. Elle est payée aussitôt et son statut est awaiting_brief ; le délai commence à courir avec le brief.
  2. Pour chaque fichier, envoyez POST /orders/{id}/files avec {"name": "page-1.png", "size": 482113, "mime": "image/png"} : size est la taille exacte en octets, mime est facultatif. La réponse (201) contient le fichier et l’adresse où le téléverser :
{
  "file": { "id": 77, "name": "page-1.png", "mime": "application/octet-stream", "size": 482113, "status": "pending", "used": false, "uploadExpiresAt": "2026-10-16T12:00:00.000Z", "createdAt": "2026-10-16T11:00:00.000Z" },
  "upload": { "url": "https://...", "headers": { "content-type": "application/octet-stream" }, "expiresAt": "2026-10-16T12:00:00.000Z" }
}
  1. Envoyez les octets du fichier par PUT à upload.url avec exactement les headers indiqués et sans clé API, avant upload.expiresAt (une heure) :
curl -X PUT "$url" -H "content-type: application/octet-stream" --data-binary @page-1.png
  1. POST /orders/{id}/files/{fileId}/complete. Un fichier dont la taille diffère de size, ou dont les octets ne correspondent à aucun type de accept, est refusé avec 422 et supprimé : le nom et mime ne comptent pas. Sinon, la réponse est le fichier, désormais checking. Après quelques secondes, ou quelques minutes pour un long enregistrement, il passe à ready, ou à rejected avec le motif dans reason, par exemple recording_no_sound ou file_unreadable. Le champ files de la commande indique leur état.
  2. POST /orders/{id}/brief avec text, link, answers et script comme pour POST /orders. Les fichiers prêts pas encore envoyés l’accompagnent, ou listez ceux à envoyer dans fileIds. Tant que l’un d’eux est encore checking, le brief est refusé avec 409 files_not_ready : renvoyez-le un peu plus tard. La réponse (200) est la commande, désormais in_progress.

DELETE /orders/{id}/files/{fileId} retire un fichier pas encore envoyé. Une commande accepte au maximum 5 fichiers et 4 Go au total ; un fichier dont le téléversement a commencé compte jusqu’à ce qu’il soit finalisé ou retiré, et pendant une journée à compter du début de leur téléversement, les fichiers retirés ou refusés comptent dans une limite de 12 Go avec les fichiers de la commande : au-delà, un téléversement est refusé avec 409 upload_quota et retryAt, l’heure à laquelle il sera de nouveau accepté. Une commande livrée accepte aussi des fichiers pour une demande de retouches : téléversez-les de la même façon, puis envoyez fileIds avec la demande.

Sans awaitBrief, une commande d’un service dont les fichiers sont required est refusée avec 400 files_required, et celle d’un service où un fichier peut remplacer le lien, envoyée sans lien, avec 400 link_required.

Dans la commande, files liste vos fichiers avec leur status, et fileIds ceux qui ont accompagné le brief. Un fichier prêt possède une url valable jusqu’à expiresAt, comme les fichiers de résultat. Les fichiers sont conservés 30 jours après la clôture de la commande.

Idempotence

Une requête peut expirer alors que la commande a déjà été passée. Pour répéter POST /orders sans payer deux fois, envoyez avec elle un en-tête Idempotency-Key : une chaîne de 1 à 255 caractères ASCII imprimables que vous choisissez une fois par commande, comme un UUID ou votre propre numéro de commande. Envoyez la même clé et le même corps lorsque vous répétez la requête.

curl -i https://dleex.com/api/v1/orders -H "Authorization: Bearer dlx_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: shop-order-981" \
  -d '{"service":"seo-article","tier":"basic","text":"An article about trail running shoes, 5 keywords: ..."}'

Si une commande a déjà été passée avec cette clé, la réponse est cette commande dans son état actuel, avec le statut 201 et un en-tête supplémentaire. Rien n’est débité une seconde fois :

HTTP/1.1 201 Created
Idempotent-Replayed: true

La validation, les briefs et les demandes de retouches ne prennent pas de clé. La validation peut être répétée sans risque : une fois la commande terminée, une répétition renvoie 409 order_not_delivered. De même pour un brief : une fois qu’il est passé, une répétition renvoie 409 brief_not_expected et la commande est in_progress. Une demande de retouches est différente : pendant que le travail est repris, une répétition renvoie 409 order_not_delivered, mais une fois la nouvelle version livrée, une répétition demande une retouche supplémentaire. Avant de répéter une demande de retouches, vérifiez la commande avec GET /orders/{id} (status et revisionsLeft).

Suivi des commandes

GET /orders/{id} renvoie une commande, GET /orders vos commandes, des plus récentes aux plus anciennes. La liste accepte status, limit (de 1 à 100, 20 par défaut) et before (un identifiant de commande, pour obtenir des commandes plus anciennes).

Statut de la commande :

StatutSignification
awaiting_briefPassée avec awaitBrief : en attente de POST /orders/{id}/brief
in_progressLe travail est en cours
quality_checkLe travail est terminé et vérifié avant la livraison
deliveredLe résultat est prêt, voir results. Validez-le ou demandez des retouches avant autoAcceptAt
revisionLes retouches demandées sont en cours
completedVous avez validé le résultat, ou il a été validé automatiquement
refundedL’argent a été restitué sur votre solde

Vérifiez toutes les quelques minutes ; inutile d’interroger plus souvent. Lorsque la commande est delivered, results contient le travail : kind vaut text (Markdown), report (un rapport de livraison pour les commandes réseaux sociaux) ou files (des fichiers à télécharger, avec une note facultative dans body). Chaque résultat comporte une liste files, vide pour les textes et les rapports : chaque fichier a un name, un mime, une size en octets et une url valable jusqu’à expiresAt, environ une heure. Relisez la commande pour obtenir de nouveaux liens. Le lien peut rediriger vers le stockage des fichiers : suivez donc les redirections, par exemple curl -L -o result.png "$url", et n’envoyez pas de clé API avec : le lien suffit à ouvrir le fichier.

Validation et retouches

Si vous ne validez pas une commande livrée et ne demandez pas de retouches, elle est validée automatiquement 3 jours après la livraison, à l’heure indiquée dans autoAcceptAt (null dans les autres états). Une nouvelle livraison après des retouches relance les 3 jours. Vous pouvez aussi valider le travail sur le site. Si vous écrivez dans le chat de la commande sur le site après la livraison, la commande n’est pas validée automatiquement et autoAcceptAt vaut null jusqu’à ce que vous la validiez ou que nous reprenions le travail ou le remboursions. Après avoir répondu à votre message, nous pouvons aussi relancer les 3 jours : autoAcceptAt indique alors la nouvelle heure.

Erreurs

Les erreurs sont accompagnées d’un statut HTTP et d’un code :

{ "code": "insufficient_balance" }
StatutCodeSignification
400validationUn champ est manquant ou incorrect ; fields les liste
400link_requiredCe service nécessite link
400files_requiredCe service nécessite un fichier : passez la commande avec awaitBrief et téléversez-le
400script_requiredCe service lit un texte à voix haute : envoyez-le dans script
400script_too_longscript est plus long que ce que lit la formule ; maxChars dans la réponse indique le maximum accepté. Rien n’a été débité
400script_not_acceptedLe service ne lit aucun texte à voix haute (son script dans /services vaut null) : omettez script. Rien n’a été débité
400files_not_accepted, file_too_largeLe service n’accepte aucun fichier, ou le fichier dépasse son maxMb
400invalid_idempotency_keyIdempotency-Key est vide, dépasse 255 caractères ou n’est pas en ASCII imprimable
401invalid_api_keyClé absente, incorrecte ou révoquée. Les clés sont aussi révoquées lorsque l’e-mail non confirmé du compte est confirmé par une connexion avec Google ou par la définition d’un nouveau mot de passe
402insufficient_balanceSolde insuffisant ; rien n’a été débité
404package_not_found, order_not_found, file_not_foundService, formule, commande ou fichier introuvable
409order_not_delivered, no_revisions_leftLa commande n’est pas dans un état qui le permet
409brief_not_expectedLa commande n’attend pas son brief : elle a été passée sans awaitBrief, ou son brief a déjà été envoyé
409uploads_closedLes fichiers ne sont acceptés que lorsque la commande attend son brief ou est livrée
409files_limitPlus de fichiers que le service n’en accepte par brief ou par demande, ou plus de 5 fichiers ou 4 Go pour la commande
409upload_quotaAvec celui-ci, les fichiers de la commande (y compris ceux envoyés et les téléversements inachevés) et ceux commencés au cours de la dernière journée puis retirés ou refusés dépassent 12 Go : réessayez après retryAt
409files_not_ready, file_rejectedUn fichier à envoyer est encore en cours de vérification, ou a été rejeté
409upload_incompleteRien n’a encore été téléversé sur le lien : terminez le PUT, puis finalisez à nouveau le téléversement
409file_in_use, file_busyLe fichier a accompagné le brief ou une demande et reste lié à la commande, ou il est en cours de déplacement par sa vérification : réessayez dans un instant
409addon_unavailableUne option n’est pas proposée pour ce service et cette formule
409promo_not_found, promo_inactive, promo_used_up, promo_already_used, promo_first_order_only, promo_min_orderLe code promo n’existe pas, n’est pas actif actuellement, est épuisé, a déjà été utilisé par vous, est réservé à une première commande ou exige une commande plus importante. Rien n’a été débité
409idempotency_key_in_progressUne requête avec cette Idempotency-Key est encore en cours de traitement ; répétez-la un instant plus tard
410upload_expired, file_removedLe lien de téléversement a expiré avant que quoi que ce soit ait été téléversé, ou vous avez retiré le fichier : lancez un nouveau téléversement
415file_type_not_acceptedLe mime indiqué ne correspond à aucun type accepté par le service
422idempotency_key_reusedCette Idempotency-Key a déjà été utilisée avec une autre requête
422upload_size_mismatch, file_type_not_acceptedLe fichier téléversé n’a pas la taille indiquée dans size, ou ses octets ne correspondent à aucun type accepté par le service ; il a été supprimé
422file_unreadable, recording_no_sound, check_failedFinalisation d’un fichier rejeté par la vérification : il ne s’ouvre pas, l’enregistrement n’a pas de son, ou il n’a pas pu être vérifié. Téléversez à nouveau le fichier ou un autre
429rate_limitedPlus de 120 requêtes par minute avec une même clé ; attendez le nombre de secondes indiqué dans Retry-After

Remboursements

Si nous remboursons une commande, l’argent est restitué sur le solde et la commande passe à refunded.