> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API de modération

> Filtrez les prompts et les images avant la génération par votre produit d’IA, et obtenez un verdict d’autorisation, de signalement ou de refus, accompagné d’un score pour 17 catégories de contenu.

<CardGroup cols={2}>
  <Card title="Screen a Prompt" icon="shield-check" href="/api-reference/moderation/screen">
    Envoyez du texte, une image ou les deux, et obtenez un verdict.
  </Card>

  <Card title="Get Moderation Usage" icon="chart-column" href="/api-reference/moderation/get-usage">
    Consultez vos filtrages facturables et votre prochaine charge.
  </Card>
</CardGroup>

## Présentation

La Moderation API filtre les entrées utilisateur avant que votre produit d’IA ne les utilise pour générer du contenu. Vous envoyez le texte d’un prompt, une image ou les deux, et Dodo Payments renvoie un verdict `allow`, `flag` ou `deny`, accompagné d’un score pour chaque catégorie de contenu.

Utilisez-la devant n’importe quel modèle de génération d’images, de vidéos ou de texte qui accepte les entrées de vos utilisateurs. La Moderation API est activée par défaut pour toutes les entreprises et fonctionne avec votre clé API Dodo Payments existante : aucune inscription n’est nécessaire. Dodo Payments peut la désactiver pour une entreprise donnée ; les appels renvoient alors `403` avec `MODERATION_DISABLED`.

## Pourquoi nous avons créé la Moderation API

Un produit de génération par IA crée du contenu à partir de ce que ses utilisateurs saisissent. Vous ne pouvez pas examiner chaque prompt manuellement, et un seul résultat préjudiciable peut mettre votre entreprise en danger.

En tant que Merchant of Record, Dodo Payments assume la responsabilité juridique et réputationnelle de ce qui est vendu sur la plateforme. La [Merchant Acceptance Policy](/miscellaneous/merchant-acceptance) examine les outils de génération de contenu par IA et n’autorise pas l’usurpation d’identité, les deepfakes ni le contenu explicite, y compris le contenu généré par IA. Un compte qui génère du contenu préjudiciable, provoque un nombre excessif de rétrofacturations ou reçoit des signalements de partenaires de paiement peut faire l’objet d’un examen ou être suspendu.

Nous avons créé la Moderation API pour vous permettre d’arrêter ce contenu avant que votre modèle ne le crée :

* **Filtrez avant de générer.** Un prompt bloqué n’atteint jamais votre modèle : aucun résultat préjudiciable n’existe et vous ne dépensez aucune ressource de calcul pour le traiter.
* **Couvrez les catégories importantes pour la génération.** Le filtrage attribue un score à 17 catégories, notamment la ressemblance avec une personne réelle, les images intimes non consenties, le langage évoquant un mineur et l’association d’une personne réelle à du contenu sexuel qui caractérise un deepfake sexuel.
* **Intégrez-la sans autre fournisseur.** L’API fonctionne avec votre clé API Dodo Payments et ses frais sont débités de votre solde. Aucun contrat, aucune facture ni aucun compte distinct n’est nécessaire.
* **Préservez la confidentialité du contenu utilisateur.** Dodo Payments ne stocke ni n’enregistre le texte et les images que vous filtrez.

<Note>
  La Moderation API est un outil destiné à votre propre application des règles. Elle ne remplace pas la Merchant Acceptance Policy, et vous restez responsable de ce que votre produit génère.
</Note>

## Fonctionnement

Appelez la Moderation API depuis votre backend après l’envoi du prompt par l’utilisateur et avant l’exécution de votre modèle :

```mermaid theme={null}
flowchart LR
  A[User submits a prompt] --> B[Your backend calls POST /moderation/screen]
  B -->|allow| C[Generate]
  B -->|flag| D[Apply your own policy]
  B -->|deny| E[Block the request]
  B -->|error, no verdict| E
```

Chaque appel correspond à un **filtrage**. Le texte et l’image envoyés dans le même appel comptent comme un seul filtrage.

### Verdicts

Le champ `decision` contient le verdict :

| Verdict | Signification                                                                                                    | Action à effectuer                                                                                 |
| ------- | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `allow` | Le contenu est accepté.                                                                                          | Générez le contenu.                                                                                |
| `flag`  | Le contenu a dépassé le seuil d’une catégorie qui nécessite un jugement. Il ne s’agit pas d’un refus temporaire. | Appliquez vos propres règles. Vous pouvez bloquer le contenu, l’envoyer en révision ou le générer. |
| `deny`  | Le contenu ne doit pas être généré.                                                                              | Bloquez la demande et affichez une erreur à l’utilisateur.                                         |

<Warning>
  Ne générez rien lorsque vous ne recevez aucun verdict. Un `503` signifie que Dodo Payments n’a pas pu produire de verdict ; un délai d’attente ou une erreur réseau vous laisse également sans verdict. Traitez tous ces cas comme un blocage et demandez à l’utilisateur de réessayer.
</Warning>

## Filtrer un prompt

Pour filtrer un prompt, envoyez une requête `POST` à `/moderation/screen` avec au moins l’un des champs `text` et `image`. La requête accepte trois champs :

| Champ        | Type   | Description                                                                                                                                                                         |
| ------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text`       | string | Le texte à filtrer, jusqu’à 8 000 caractères.                                                                                                                                       |
| `image`      | string | L’image à filtrer, au format base64, avec ou sans préfixe `data:image/...;base64,`.                                                                                                 |
| `request_id` | string | Facultatif. Votre identifiant pour ce filtrage, par exemple un ID de génération, de 128 caractères maximum et sans caractères de contrôle. La réponse le renvoie sans modification. |

Les SDK TypeScript et Python exposent le endpoint sous le nom `client.moderation.screen()`. Cet exemple bloque la génération pour `deny`, pour `flag` et pour toute erreur :

<Note>
  Les exemples utilisent le mode live, car seul le mode live exécute le modèle de modération. Le mode test renvoie des [verdicts simulés](#testing-your-integration) et ne filtre jamais le contenu. Les filtrages en mode live sont facturés.
</Note>

<CodeGroup>
  ```typescript Node.js expandable theme={null}
  import DodoPayments from 'dodopayments';

  const client = new DodoPayments({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: 'live_mode',
  });

  async function generateImage(prompt: string, generationId: string) {
    let verdict;
    try {
      verdict = await client.moderation.screen({
        text: prompt,
        request_id: generationId,
      });
    } catch (err) {
      // No verdict: do not generate.
      throw new Error('Moderation is unavailable. Try again in a moment.');
    }

    if (verdict.decision !== 'allow') {
      throw new Error('This prompt cannot be generated. Revise it and try again.');
    }

    return myModel.generate(prompt);
  }
  ```

  ```python Python expandable theme={null}
  import os
  from dodopayments import DodoPayments, APIError

  client = DodoPayments(
      bearer_token=os.environ["DODO_PAYMENTS_API_KEY"],
      environment="live_mode",
  )

  def generate_image(prompt: str, generation_id: str):
      try:
          verdict = client.moderation.screen(text=prompt, request_id=generation_id)
      except APIError:
          # No verdict: do not generate.
          raise RuntimeError("Moderation is unavailable. Try again in a moment.")

      if verdict.decision != "allow":
          raise ValueError("This prompt cannot be generated. Revise it and try again.")

      return my_model.generate(prompt)
  ```

  ```bash cURL theme={null}
  curl -X POST https://live.dodopayments.com/moderation/screen \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "text": "a watercolor painting of a lighthouse at sunset",
      "request_id": "gen_7Hc2k9"
    }'
  ```
</CodeGroup>

L’exemple traite `flag` comme `deny`. Si votre produit autorise certains contenus signalés, consultez `triggered` pour prendre une décision selon la catégorie.

<Tip>
  Filtrez le texte écrit par votre utilisateur, et non le modèle de prompt que vous ajoutez autour. Votre propre modèle est identique à chaque appel et n’apporte rien au filtrage.
</Tip>

### Filtrer des images

Envoyez une image pour filtrer une image de référence téléversée ou une image générée avant de l’afficher. L’image doit respecter les exigences suivantes :

* Le format est JPEG, PNG, WebP, GIF ou BMP.
* La chaîne base64 comporte au maximum 6 991 530 caractères et l’image décodée ne dépasse pas 5 MiB.
* L’image est une seule image fixe. Les images GIF et WebP animées sont refusées.
* Le côté le plus long mesure au moins 32 pixels.

Une image qui ne respecte pas l’une de ces vérifications renvoie `400` avec `MODERATION_INVALID_IMAGE`, ou `413` avec `MODERATION_INPUT_TOO_LARGE` lorsqu’elle est trop volumineuse.

Pour filtrer une image, lisez le fichier, encodez-le au format base64 et envoyez-le dans `image`. Pour filtrer une image et son prompt ensemble, envoyez `text` et `image` dans le même appel. Cela compte comme un seul filtrage. Cet exemple utilise le `client` de l’exemple précédent :

<CodeGroup>
  ```typescript Node.js expandable theme={null}
  import { readFile } from 'node:fs/promises';

  async function screenImage(path: string, prompt: string, generationId: string) {
    const image = (await readFile(path)).toString('base64');

    const verdict = await client.moderation.screen({
      image, // or `data:image/png;base64,${image}`
      text: prompt, // optional: screen the prompt with the image
      request_id: generationId,
    });

    return verdict.decision === 'allow';
  }
  ```

  ```python Python expandable theme={null}
  import base64

  def screen_image(path: str, prompt: str, generation_id: str) -> bool:
      with open(path, "rb") as f:
          image = base64.b64encode(f.read()).decode("ascii")

      verdict = client.moderation.screen(
          image=image,  # or f"data:image/png;base64,{image}"
          text=prompt,  # optional: screen the prompt with the image
          request_id=generation_id,
      )
      return verdict.decision == "allow"
  ```

  ```bash cURL expandable theme={null}
  # Builds the JSON body with jq, so a large image does not hit the shell argument limit.
  base64 < reference.png | tr -d '\n' \
    | jq -Rs '{image: ., text: "turn this photo into a watercolor painting", request_id: "gen_7Hc2k9"}' \
    | curl -X POST https://live.dodopayments.com/moderation/screen \
        -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY" \
        -H "Content-Type: application/json" \
        --data @-
  ```
</CodeGroup>

Gérez les erreurs d’un filtrage d’image comme celles d’un filtrage de texte : si l’appel échoue, ne générez rien.

## Lire la réponse

La réponse renvoie le verdict et les éléments qui le justifient :

| Champ                | Description                                                                                                                                                                     |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `decision`           | Le verdict : `allow`, `flag` ou `deny`.                                                                                                                                         |
| `triggered`          | Les catégories dont le score a dépassé le seuil de la catégorie. Ce champ peut être vide pour un `flag` issu de la vérification générale.                                       |
| `compound_triggered` | `true` lorsque la ressemblance avec une personne réelle et le contenu sexuel ont ensemble dépassé leur seuil combiné, ce qui correspond au schéma d’un deepfake sexuel.         |
| `categories`         | La probabilité, de 0 à 1, que le contenu appartienne à chaque catégorie.                                                                                                        |
| `provenance`         | La manière dont chaque score a été mesuré : `targeted` par une vérification de cette seule catégorie, ou `broad` par la vérification générale qui couvre toutes les catégories. |
| `notes`              | Les raisons, en langage naturel, de la décision. La formulation peut changer ; ne l’analysez donc pas.                                                                          |
| `normalized_applied` | `true` lorsque le texte a également été filtré après suppression de l’obfuscation, comme les caractères invisibles ou ressemblants.                                             |
| `passes`             | Le nombre de questions oui/non auxquelles le modèle a répondu pour ce filtrage.                                                                                                 |
| `latency_ms`         | La durée du filtrage, en millisecondes.                                                                                                                                         |
| `request_id`         | Le `request_id` que vous avez envoyé, ou `null`.                                                                                                                                |

Fondez votre logique sur `decision` et `triggered`. Chaque catégorie possède son propre seuil ; un seuil unique dans votre code ne correspond donc pas au verdict.

### Catégories

Chaque réponse évalue le contenu selon 17 catégories :

| Catégorie                         | Contenu couvert                                                                       |
| --------------------------------- | ------------------------------------------------------------------------------------- |
| `violent_crimes`                  | Crimes violents.                                                                      |
| `sex_related_crimes`              | Crimes à caractère sexuel.                                                            |
| `child_sexual_exploitation`       | Exploitation sexuelle des enfants.                                                    |
| `suicide_and_self_harm`           | Suicide et automutilation.                                                            |
| `indiscriminate_weapons`          | Armes chimiques, biologiques, radiologiques, nucléaires ou explosives.                |
| `intellectual_property`           | Violation des droits d’auteur ou des marques.                                         |
| `defamation`                      | Représentation mensongère susceptible de nuire à la réputation d’une personne réelle. |
| `non_violent_crimes`              | Crimes non violents.                                                                  |
| `hate`                            | Dévalorisation de personnes en raison d’une caractéristique protégée.                 |
| `privacy`                         | Informations privées sensibles concernant une personne.                               |
| `specialized_advice`              | Conseils financiers, médicaux, juridiques ou électoraux non qualifiés.                |
| `sexual_content`                  | Contenu sexuellement explicite ou pornographique.                                     |
| `non_consensual_intimate_imagery` | Déshabillage, dénudage ou sexualisation d’une personne réelle.                        |
| `minor_coded_language`            | Langage évoquant un âge qui suggère que le sujet est mineur.                          |
| `real_person_likeness`            | Ressemblance avec une personne réelle, identifiable et nommée.                        |
| `living_artist_style`             | Imitation du style caractéristique d’un artiste vivant précis.                        |
| `prompt_injection`                | Tentative de contourner ou de manipuler les instructions du système.                  |

## Gérer les erreurs

Les erreurs renvoient le corps d’erreur Dodo Payments standard avec un `code` et un `message`. Aucune erreur ne constitue un verdict ; aucune n’autorise donc la génération :

| Status | `code`                       | Cause                                                                                   | Action à effectuer                                                                   |
| ------ | ---------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `400`  | `INVALID_REQUEST_PARAMETERS` | La requête est mal formée ou ne contient ni `text` ni `image`.                          | Corrigez la requête.                                                                 |
| `400`  | `MODERATION_INVALID_IMAGE`   | L’image ne peut pas être décodée, elle est animée ou trop petite.                       | Envoyez une image fixe prise en charge.                                              |
| `403`  | `MODERATION_DISABLED`        | Dodo Payments a désactivé la Moderation API pour votre entreprise.                      | Contactez le support pour en connaître la raison.                                    |
| `413`  | `MODERATION_INPUT_TOO_LARGE` | `text` dépasse 8 000 caractères ou `image` dépasse la limite de taille.                 | Raccourcissez le texte ou réduisez l’image.                                          |
| `429`  | `MODERATION_OVERLOADED`      | La modération a atteint sa capacité. Il s’agit d’une limite de débit, pas d’un verdict. | Attendez le nombre de secondes indiqué dans l’en-tête `Retry-After`, puis réessayez. |
| `503`  | `MODERATION_UNAVAILABLE`     | Aucun verdict n’est disponible.                                                         | Ne générez rien. Réessayez plus tard.                                                |

Par défaut, les SDK réessaient deux fois en cas de `429` ou de `503` et attendent `Retry-After` entre les tentatives. Une fois les tentatives épuisées, le SDK déclenche une erreur et votre code doit bloquer la demande.

## Tester votre intégration

Le mode test renvoie des verdicts simulés et n’appelle jamais le modèle de modération, ce qui vous permet de tester votre routage sans frais. Envoyez les requêtes à `https://test.dodopayments.com` avec une clé API en mode test.

Le verdict simulé par défaut est `allow`. Pour obtenir un autre résultat, placez l’une de ces chaînes n’importe où dans `text` :

| Chaîne dans `text`     | Réponse                                             |
| ---------------------- | --------------------------------------------------- |
| `dodo_mock_flag`       | `200` avec `decision` défini sur `flag`             |
| `dodo_mock_deny`       | `200` avec `decision` défini sur `deny`             |
| `dodo_mock_overloaded` | `429` `MODERATION_OVERLOADED` avec `Retry-After: 1` |
| `dodo_mock_not_ready`  | `503` `MODERATION_UNAVAILABLE`                      |

Un verdict simulé contient une note indiquant qu’il s’agit d’un résultat simulé, et tous ses scores de catégorie sont `0`. Le mode test applique les mêmes validations de requête que le mode live. Pour les images, il vérifie l’encodage base64 et le format, mais pas le nombre d’images ni les dimensions.

Avant de passer en mode live, vérifiez que votre intégration gère chaque cas :

<Steps>
  <Step title="Deny Blocks Generation">
    Envoyez `dodo_mock_deny` et confirmez que votre modèle n’est pas appelé.
  </Step>

  <Step title="Flag Follows Your Policy">
    Envoyez `dodo_mock_flag` et confirmez que votre produit se comporte conformément à vos règles.
  </Step>

  <Step title="Overload Retries">
    Envoyez `dodo_mock_overloaded` et confirmez que votre code attend `Retry-After` et ne génère rien sans verdict.
  </Step>

  <Step title="An Outage Blocks Generation">
    Envoyez `dodo_mock_not_ready` et confirmez que votre modèle n’est pas appelé.
  </Step>

  <Step title="Every Generation Path Screens">
    Vérifiez que chaque chemin de code qui atteint votre modèle appelle d’abord la Moderation API.
  </Step>
</Steps>

## Tarification et facturation

La Moderation API coûte **0,30 \$ USD pour 1 000 filtrages facturables**. Il n’y a ni niveau gratuit ni minimum.

Un filtrage facturable est un filtrage en mode live qui renvoie un verdict. Ces filtrages sont gratuits et ne sont pas comptabilisés :

* Les filtrages en mode test.
* Les filtrages qui renvoient une erreur, notamment `429` et `503`.

Dodo Payments facture par blocs complets de 1 000 filtrages. Chaque bloc complet est facturé dans l’heure, tandis que les filtrages qui ne remplissent pas un bloc restent non facturés jusqu’à ce que le bloc soit complet. Les frais sont débités de votre solde USD et apparaissent dans votre [registre de solde](/api-reference/balance-ledger/list-ledger-entries) avec le type d’événement `moderation_fees`. Les versements les affichent sous **Frais de modération**.

### Suivre l’utilisation

Pour consulter votre utilisation, appelez `GET /moderation/usage`. La réponse renvoie :

| Champ                   | Description                                                                                               |
| ----------------------- | --------------------------------------------------------------------------------------------------------- |
| `unbilled_screens`      | Les filtrages facturables que Dodo Payments ne vous a pas encore facturés.                                |
| `screens_to_next_block` | Le nombre de filtrages facturables encore nécessaires pour remplir le prochain bloc de 1 000.             |
| `daily`                 | Vos filtrages facturables par jour UTC au cours des 30 derniers jours. Les jours sans filtrage sont omis. |

<CodeGroup>
  ```bash cURL theme={null}
  curl https://live.dodopayments.com/moderation/usage \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY"
  ```

  ```typescript Node.js theme={null}
  const usage = await client.moderation.retrieveUsage();
  console.log(usage.unbilled_screens, usage.screens_to_next_block);
  ```

  ```python Python theme={null}
  usage = client.moderation.retrieve_usage()
  print(usage.unbilled_screens, usage.screens_to_next_block)
  ```
</CodeGroup>

Le mode test n’enregistre aucun filtrage ; l’endpoint d’utilisation ne renvoie donc aucune activité du mode test.

## Accès et confidentialité

Le filtrage nécessite une clé API avec un accès en écriture. Toute clé API, y compris une clé en lecture seule, peut consulter l’utilisation. Consultez [Authentication](/api-reference/introduction#authentication) pour savoir comment créer une clé et définir son niveau d’accès.

Dodo Payments ne stocke pas le texte ni les images que vous filtrez et ne les écrit pas dans les journaux. Pour chaque filtrage en mode live, Dodo Payments conserve l’heure, le verdict et votre `request_id` à des fins de facturation et de rapports d’utilisation.

<CardGroup cols={2}>
  <Card title="Usage-Based Billing" icon="arrow-trend-up" href="/features/usage-based-billing/introduction">
    Facturez vos propres clients pour chaque génération.
  </Card>

  <Card title="Credit-Based Billing" icon="coins" href="/features/credit-based-billing">
    Vendez des crédits de génération et déduisez-les à chaque utilisation.
  </Card>
</CardGroup>
