> ## 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 moderación

> Analiza prompts e imágenes antes de que tu producto de IA genere contenido y obtén un veredicto de permitir, marcar o denegar, junto con una puntuación para 17 categorías de contenido.

<CardGroup cols={2}>
  <Card title="Screen a Prompt" icon="shield-check" href="/api-reference/moderation/screen">
    Envía texto, una imagen o ambos, y obtén un veredicto.
  </Card>

  <Card title="Get Moderation Usage" icon="chart-column" href="/api-reference/moderation/get-usage">
    Consulta tus análisis facturables y tu próximo cargo.
  </Card>
</CardGroup>

## Descripción general

La API de moderación analiza la entrada del usuario antes de que tu producto de IA genere contenido a partir de ella. Envías el texto de un prompt, una imagen o ambos, y Dodo Payments devuelve un veredicto de `allow`, `flag` o `deny`, junto con una puntuación para cada categoría de contenido.

Úsala delante de cualquier modelo de generación de imágenes, vídeos o texto que reciba entradas de tus usuarios. La API de moderación está activada para todas las empresas de forma predeterminada y funciona con tu clave de API existente de Dodo Payments, por lo que no tienes que registrarte. Dodo Payments puede desactivarla para una empresa específica; en ese caso, las llamadas devuelven `403` con `MODERATION_DISABLED`.

## Por qué creamos la API de moderación

Un producto de generación de IA crea contenido nuevo a partir de lo que escriben sus usuarios. No puedes revisar cada prompt manualmente, y una sola salida dañina puede poner en riesgo tu empresa.

Como tu Merchant of Record, Dodo Payments es legal y reputacionalmente responsable de lo que se vende a través de la plataforma. La [Merchant Acceptance Policy](/miscellaneous/merchant-acceptance) revisa las herramientas de generación de contenido de IA y no permite la suplantación de identidad, los deepfakes ni el contenido explícito, incluido el contenido generado por IA. Una cuenta que genere contenido dañino, un volumen excesivo de contracargos o alertas de los socios de pago puede quedar bajo revisión o ser suspendida.

Creamos la API de moderación para que puedas detener este contenido antes de que tu modelo lo cree:

* **Analiza antes de generar.** Un prompt bloqueado nunca llega a tu modelo, por lo que no existe ninguna salida dañina y no gastas recursos de cómputo en ella.
* **Cubre las categorías importantes para la generación.** El análisis puntúa 17 categorías, incluidas la semejanza con una persona real, las imágenes íntimas no consentidas, el lenguaje que indica que se trata de un menor y la combinación de una persona real con contenido sexual que identifica un deepfake sexual.
* **Integra sin otro proveedor.** La API funciona con tu clave de API de Dodo Payments y su tarifa se descuenta de tu saldo. No hay un contrato, una factura ni una cuenta independientes.
* **Mantén privado el contenido de los usuarios.** Dodo Payments no almacena ni registra el texto y las imágenes que analizas.

<Note>
  La API de moderación es una herramienta para aplicar tus propias reglas. No sustituye la Merchant Acceptance Policy y sigues siendo responsable de lo que genere tu producto.
</Note>

## Cómo funciona

Llama a la API de moderación desde tu backend después de que el usuario envíe un prompt y antes de que se ejecute tu modelo:

```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
```

Cada llamada equivale a un **análisis**. El texto y una imagen enviados en la misma llamada cuentan como un solo análisis.

### Veredictos

El campo `decision` contiene el veredicto:

| Veredicto | Significado                                                                                             | Qué hacer                                                                      |
| --------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `allow`   | El contenido pasó la revisión.                                                                          | Genera el contenido.                                                           |
| `flag`    | El contenido superó el umbral de una categoría que requiere criterio. No es una denegación provisional. | Aplica tus propias reglas. Puedes bloquearlo, enviarlo a revisión o generarlo. |
| `deny`    | El contenido no debe generarse.                                                                         | Bloquea la solicitud y muestra al usuario un error.                            |

<Warning>
  No generes contenido cuando no recibas ningún veredicto. Un `503` significa que Dodo Payments no pudo producir un veredicto, y un error de tiempo de espera o de red hace que no obtengas ninguno. Trata todos estos casos como un bloqueo y pide al usuario que lo intente de nuevo.
</Warning>

## Analizar un prompt

Para analizar un prompt, envía una solicitud `POST` a `/moderation/screen` con al menos uno de `text` y `image`. La solicitud acepta tres campos:

| Campo        | Tipo   | Descripción                                                                                                                                                         |
| ------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text`       | string | El texto que se analizará, de hasta 8.000 caracteres.                                                                                                               |
| `image`      | string | La imagen que se analizará, en base64, con o sin el prefijo `data:image/...;base64,`.                                                                               |
| `request_id` | string | Opcional. Tu identificador para este análisis, como un ID de generación, de hasta 128 caracteres y sin caracteres de control. La respuesta lo devuelve sin cambios. |

Los SDK de TypeScript y Python exponen el endpoint como `client.moderation.screen()`. Este ejemplo bloquea la generación con `deny`, con `flag` y ante cualquier error:

<Note>
  Los ejemplos llaman al modo live, porque solo el modo live ejecuta el modelo de moderación. El modo test devuelve [veredictos simulados](#testing-your-integration) y nunca analiza el contenido. Los análisis del modo live se facturan.
</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>

El ejemplo trata `flag` como `deny`. Si tu producto permite cierto contenido marcado, comprueba `triggered` para decidir según la categoría.

<Tip>
  Analiza el texto que escribió el usuario, no la plantilla del prompt que colocas a su alrededor. Tu propia plantilla es la misma en cada llamada y no aporta nada al análisis.
</Tip>

### Analizar imágenes

Envía una imagen para analizar una imagen de referencia subida o una imagen generada antes de mostrársela al usuario. La imagen debe cumplir estos requisitos:

* El formato es JPEG, PNG, WebP, GIF o BMP.
* La cadena base64 tiene como máximo 6.991.530 caracteres y la imagen decodificada ocupa como máximo 5 MiB.
* La imagen es un único fotograma fijo. Se rechazan las imágenes GIF y WebP animadas.
* El lado más largo tiene al menos 32 píxeles.

Una imagen que no cumpla una de estas comprobaciones devuelve `400` con `MODERATION_INVALID_IMAGE`, o `413` con `MODERATION_INPUT_TOO_LARGE` cuando es demasiado grande.

Para analizar una imagen, lee el archivo, codifícalo como base64 y envíalo en `image`. Para analizar una imagen y su prompt conjuntamente, envía `text` y `image` en la misma llamada. Cuenta como un solo análisis. Este ejemplo usa el `client` del ejemplo anterior:

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

Gestiona los errores de un análisis de imagen igual que los de un análisis de texto: si la llamada genera una excepción, no generes contenido.

## Leer la respuesta

La respuesta devuelve el veredicto y las pruebas en las que se basa:

| Campo                | Descripción                                                                                                                                                      |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `decision`           | El veredicto: `allow`, `flag` o `deny`.                                                                                                                          |
| `triggered`          | Las categorías cuya puntuación superó el umbral de la categoría. Puede estar vacío en un `flag` de la comprobación general.                                      |
| `compound_triggered` | `true` cuando la semejanza con una persona real y el contenido sexual superaron conjuntamente su umbral combinado: el patrón de un deepfake sexual.              |
| `categories`         | La probabilidad, de 0 a 1, de que el contenido pertenezca a cada categoría.                                                                                      |
| `provenance`         | Cómo se midió cada puntuación: `targeted` mediante una comprobación de esa categoría, o `broad` mediante la comprobación general que cubre todas las categorías. |
| `notes`              | Motivos comprensibles para la decisión. La redacción puede cambiar, así que no la analices.                                                                      |
| `normalized_applied` | `true` cuando el texto también se analizó eliminando la ofuscación, como caracteres invisibles o parecidos.                                                      |
| `passes`             | El número de preguntas de sí o no que respondió el modelo para este análisis.                                                                                    |
| `latency_ms`         | El tiempo que tardó el análisis, en milisegundos.                                                                                                                |
| `request_id`         | El `request_id` que enviaste, o `null`.                                                                                                                          |

Basa tu lógica en `decision` y `triggered`. Cada categoría tiene su propio umbral, por lo que un único límite de puntuación en tu código no coincide con el veredicto.

### Categorías

Cada respuesta puntúa el contenido en relación con 17 categorías:

| Categoría                         | Incluye                                                                              |
| --------------------------------- | ------------------------------------------------------------------------------------ |
| `violent_crimes`                  | Delitos violentos.                                                                   |
| `sex_related_crimes`              | Delitos relacionados con el sexo.                                                    |
| `child_sexual_exploitation`       | Explotación sexual infantil.                                                         |
| `suicide_and_self_harm`           | Suicidio y autolesiones.                                                             |
| `indiscriminate_weapons`          | Armas químicas, biológicas, radiológicas, nucleares o explosivas.                    |
| `intellectual_property`           | Infracción de derechos de autor o marcas comerciales.                                |
| `defamation`                      | Representación falsa que probablemente perjudique la reputación de una persona real. |
| `non_violent_crimes`              | Delitos no violentos.                                                                |
| `hate`                            | Degradación de personas por una característica protegida.                            |
| `privacy`                         | Información privada y sensible sobre una persona.                                    |
| `specialized_advice`              | Asesoramiento financiero, médico, legal o electoral no cualificado.                  |
| `sexual_content`                  | Contenido sexualmente explícito o pornográfico.                                      |
| `non_consensual_intimate_imagery` | Desvestir, desnudar digitalmente o sexualizar a una persona real.                    |
| `minor_coded_language`            | Lenguaje que indica una edad y sugiere que el sujeto es menor.                       |
| `real_person_likeness`            | La semejanza de una persona real, identificable y con nombre.                        |
| `living_artist_style`             | Imitación del estilo distintivo de un artista vivo específico.                       |
| `prompt_injection`                | Un intento de anular o manipular las instrucciones del sistema.                      |

## Gestionar errores

Los errores devuelven el cuerpo de error estándar de Dodo Payments con un `code` y un `message`. Ningún error es un veredicto, por lo que ninguno permite generar contenido:

| Estado | `code`                       | Causa                                                                                       | Qué hacer                                                                           |
| ------ | ---------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `400`  | `INVALID_REQUEST_PARAMETERS` | La solicitud tiene un formato incorrecto o no contiene `text` ni `image`.                   | Corrige la solicitud.                                                               |
| `400`  | `MODERATION_INVALID_IMAGE`   | La imagen no se puede decodificar, está animada o es demasiado pequeña.                     | Envía una imagen fija compatible.                                                   |
| `403`  | `MODERATION_DISABLED`        | Dodo Payments ha desactivado la API de moderación para tu empresa.                          | Contacta con soporte para averiguar el motivo.                                      |
| `413`  | `MODERATION_INPUT_TOO_LARGE` | `text` supera los 8.000 caracteres o `image` supera el límite de tamaño.                    | Acorta el texto o reduce el tamaño de la imagen.                                    |
| `429`  | `MODERATION_OVERLOADED`      | La moderación está al límite de su capacidad. Es un límite de rendimiento, no un veredicto. | Espera los segundos indicados en el encabezado `Retry-After` y vuelve a intentarlo. |
| `503`  | `MODERATION_UNAVAILABLE`     | No hay ningún veredicto disponible.                                                         | No generes contenido. Inténtalo más tarde.                                          |

Los SDK reintentan dos veces de forma predeterminada un `429` o un `503` y esperan `Retry-After` entre los intentos. Cuando se agotan los reintentos, el SDK genera un error y tu código debe bloquear la solicitud.

## Probar tu integración

El modo test devuelve veredictos simulados y nunca llama al modelo de moderación, por lo que puedes probar tu lógica de enrutamiento sin coste. Envía solicitudes a `https://test.dodopayments.com` con una clave de API del modo test.

El veredicto simulado predeterminado es `allow`. Para obtener otro resultado, incluye una de estas cadenas en cualquier parte de `text`:

| Cadena en `text`       | Respuesta                                          |
| ---------------------- | -------------------------------------------------- |
| `dodo_mock_flag`       | `200` con `decision` establecido en `flag`         |
| `dodo_mock_deny`       | `200` con `decision` establecido en `deny`         |
| `dodo_mock_overloaded` | `429` `MODERATION_OVERLOADED` con `Retry-After: 1` |
| `dodo_mock_not_ready`  | `503` `MODERATION_UNAVAILABLE`                     |

Un veredicto simulado incluye una nota que indica que es simulado y todas sus puntuaciones de categoría son `0`. El modo test aplica la misma validación de solicitudes que el modo live. Para las imágenes, comprueba la codificación base64 y el formato, pero no el número de fotogramas ni las dimensiones.

Antes de pasar al modo live, confirma que tu integración gestiona cada caso:

<Steps>
  <Step title="Deny Blocks Generation">
    Envía `dodo_mock_deny` y confirma que no se llame a tu modelo.
  </Step>

  <Step title="Flag Follows Your Policy">
    Envía `dodo_mock_flag` y confirma que tu producto hace lo que establecen tus reglas.
  </Step>

  <Step title="Overload Retries">
    Envía `dodo_mock_overloaded` y confirma que tu código espera `Retry-After` y no genera contenido sin un veredicto.
  </Step>

  <Step title="An Outage Blocks Generation">
    Envía `dodo_mock_not_ready` y confirma que no se llame a tu modelo.
  </Step>

  <Step title="Every Generation Path Screens">
    Comprueba que cada ruta de código que llega a tu modelo llame primero a la API de moderación.
  </Step>
</Steps>

## Precios y facturación

La API de moderación cuesta **0,30 USD por cada 1.000 análisis facturables**. No hay nivel gratuito ni mínimo.

Un análisis facturable es un análisis del modo live que devuelve un veredicto. Estos análisis son gratuitos y no se contabilizan:

* Análisis en modo test.
* Análisis que devuelven un error, incluidos `429` y `503`.

Dodo Payments factura en bloques completos de 1.000 análisis. Cada bloque completo se cobra en el plazo de una hora, y los análisis que no completan un bloque permanecen sin facturar hasta que lo hacen. La tarifa se descuenta de tu saldo en USD y aparece en tu [registro de saldo](/api-reference/balance-ledger/list-ledger-entries) con el tipo de evento `moderation_fees`. Los pagos muestran este importe bajo **Tarifas de moderación**.

### Seguimiento del uso

Para consultar tu uso, llama a `GET /moderation/usage`. La respuesta devuelve:

| Campo                   | Descripción                                                                                        |
| ----------------------- | -------------------------------------------------------------------------------------------------- |
| `unbilled_screens`      | Análisis facturables que Dodo Payments aún no ha cobrado.                                          |
| `screens_to_next_block` | Análisis facturables que aún se necesitan para completar el siguiente bloque de 1.000.             |
| `daily`                 | Tus análisis facturables por día UTC durante los últimos 30 días. Se omiten los días sin análisis. |

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

El modo test no registra análisis, por lo que el endpoint de uso no devuelve actividad del modo test.

## Acceso y privacidad

El análisis requiere una clave de API con acceso de escritura. Cualquier clave de API, incluida una clave de solo lectura, puede leer el uso. Consulta [Autenticación](/api-reference/introduction#authentication) para saber cómo crear una clave y establecer su nivel de acceso.

Dodo Payments no almacena el texto ni las imágenes que analizas y tampoco los escribe en los registros. Para cada análisis del modo live, conserva la hora, el veredicto y tu `request_id` para la facturación y los informes de uso.

<CardGroup cols={2}>
  <Card title="Usage-Based Billing" icon="arrow-trend-up" href="/features/usage-based-billing/introduction">
    Cobra a tus propios clientes por cada generación.
  </Card>

  <Card title="Credit-Based Billing" icon="coins" href="/features/credit-based-billing">
    Vende créditos de generación y descuéntalos por cada uso.
  </Card>
</CardGroup>
