Clientes oficiales

Modera desde tu propio código

Python, PHP y JavaScript con los mismos nombres en los tres, Laravel sobre el de PHP, y nada más que instalar.

Python

Python 3.9+, sin dependencias

pip install toxicfilter-sdk

from toxicfilter import Client

tf = Client("tf_live_...")
verdict = tf.text(comment, locales=["en"])

if verdict.blocked:
    refuse()
elif verdict.needs_review:
    hold(verdict.id, verdict.reasons)

PHP

PHP 8.1+, ext-curl

composer require edulazaro/toxicfilter-sdk

use ToxicFilter\Client;

$tf = new Client('tf_live_...');
$verdict = $tf->text($comment, ['locales' => ['en']]);

if ($verdict->blocked()) {
    return refuse();
}

JavaScript

Node 20+, Deno, Bun, Workers

npm install toxicfilter-sdk

import ToxicFilter from 'toxicfilter-sdk'

const tf = new ToxicFilter('tf_live_...')
const verdict = await tf.text(comment, { locales: ['en'] })

if (verdict.blocked) return refuse()

Reintentos seguros

Si se supera el límite de peticiones o falla el servidor, se reintenta con esperas cada vez más largas y la misma clave de idempotencia, así que se analiza y se cobra una sola vez. Quedarse sin créditos nunca se reintenta.

Un tipo de error para cada caso

Una clave incorrecta, un campo rechazado y una cuenta sin créditos llegan cada uno con su propio tipo y con lo que necesitas para actuar.

Webhooks verificables

Una sola llamada comprueba que un evento lo hemos enviado nosotros antes de que tu código haga nada.

Sin dependencias

No impone ninguna librería HTTP a tu aplicación. Cada cliente acepta un transporte propio si quieres cambiarlo.

Laravel: Laratox

Laravel 12 y 13, sobre el cliente de PHP

composer require edulazaro/laratox

Una fachada en la que cada llamada dice lo que hace, una regla de validación Moderated que invalida el campo cuando ToxicFilter lo bloquea y un fake para tus tests que usa el cliente real sin conexión.

$verdict = ToxicFilter::text($comment->body)
    ->policy('comments')
    ->check();

if ($verdict->blocked()) {
    return back()->withErrors($verdict->reason());
}

// Or in validation: a block fails the field.
$request->validate([
    'body' => ['required', 'string', Moderated::text()],
]);

Toda la API, con los mismos nombres

Los tres clientes cubren toda la API con los mismos nombres de método. En Python, los de dos palabras van en snake_case: image_data(), batch_async(), needs_review.

MétodoEndpointPara
text() POST /v1/text Un comentario, una publicación, un mensaje
image() · imageData() POST /v1/image Una imagen por URL, o sus bytes
conversation() POST /v1/conversation El último mensaje, juzgado con el hilo anterior
name() · email() · signup() POST /v1/name · /email · /signup Un registro: nombre, correo y biografía, juntos o por separado
url() POST /v1/url Un enlace, analizado por su forma, sin descargarlo nunca
prompt() POST /v1/prompt Texto que va a entrar en tu propio modelo
batch() · batchAsync() · batchStatus() · batches() POST /v1/batch · GET /v1/batches Hasta 100 al instante, o 1.000 en segundo plano
records() · record() · resolve() · feedback() GET /v1/records · POST …/resolve · …/feedback La cola de revisión, y avisarnos cuando nos equivocamos
statement() · appeal() · resolveAppeal() · transparency() GET …/statement · POST …/appeal · GET /v1/statements/transparency Declaraciones de motivos, recursos y la base de datos de la Comisión
usage() · ping() · keys() · revokeKey() GET /v1/usage · /ping · /keys Créditos que quedan, estado de la clave y del servicio. Gratis

Lo que te dice un veredicto

Cada llamada devuelve un objeto con el veredicto completo y, detrás, la respuesta tal cual. No hay isToxic(): quince categorías y tres decisiones no caben en un booleano.

decision()
allow, review o block
blocked() · needsReview() · allowed()
Las tres como booleanos, igual de a mano
reasons() · reason()
El porqué, en frases que puedes enseñar a la persona
scores() · score($category)
Cada categoría, nunca un único número de toxicidad
topics() · leads()
De qué trata, y quién escribe
redacted()
El texto con los datos personales ocultos, si lo pides
facts()
El idioma, una dirección canónica, la huella de una imagen
degraded() · modelSkipped()
Si lo leyó el modelo y, si no, por qué
statement() · statementText()
La declaración de motivos que pide la DSA, lista para enviar
appeal() · appealDecision()
Un recurso contra él, y la decisión motivada sobre ese recurso
id() · reference() · policy()
Qué veredicto, para cuál de tus registros, con qué reglas

Un tipo de error para cada caso

Cada fallo tiene su propia clase en los tres clientes, así que una cuota agotada nunca se confunde con un límite de peticiones. La diferencia importa: uno significa esperar; el otro, pagar.

QuotaExhausted 402
Sin créditos. Nunca se reintenta: vuelve con un plan mayor. Incluye remaining() y required().
RateLimited 429
Demasiado rápido. Se reintenta por ti, con esperas cada vez más largas y la misma clave.
InvalidRequest 422
Un campo que la API rechazó, nombrado en fields(), con el nombre real más cercano si era una errata.
AuthenticationError 401
Una clave que falta, es incorrecta o está revocada.
NotFound 404
Un registro o lote que no es tuyo o no existe.
ApiError 409
Un conflicto: nada que recurrir, ya recurrido, demasiado tarde. Su code() dice cuál. No se reintenta.
ServerError 5xx
Nuestro lado o la red. Se reintenta por ti y después se lanza.

La misma aplicación, de cuatro maneras

Un muro de comentarios construido con cada cliente, desde un formulario hasta un webhook firmado. Cada aplicación es su propio repositorio, lista para clonar o usar como plantilla.

Moderar comentarios en PHP sin framework con el SDK de ToxicFilter

Sin framework: un muro de comentarios en PHP puro que publica, retiene o rechaza cada comentario, explica al autor el motivo y publica los retenidos cuando una persona los aprueba.

Moderar comentarios en Flask con el SDK de Python

Monta un muro de comentarios en Flask que publica, retiene o rechaza cada comentario con su motivo, verifica el webhook de revisión y pasa sus tests sin acceso a la red.

Moderar comentarios en Express con el SDK de JavaScript

Construye en Express un muro de comentarios que publica, retiene o rechaza cada comentario con su motivo, mantiene la clave en el servidor y verifica el webhook de revisión.

Moderar comentarios en Laravel con Laratox

Una regla de validación, una facade y un fake: construye en Laravel un muro de comentarios que publica, retiene o rechaza cada comentario, y publica los retenidos cuando una persona los aprueba.

¿Prefieres HTTP a secas? Todos los endpoints están en la referencia de la API, con un curl para cada uno.