# Detecciones de texto

> Clasifique texto sin formato como escrito con IA, mixto o escrito por una persona con POST /text/detections. Campos de la solicitud y la respuesta, posiciones de los segmentos, límites y facturación.

Fuente: https://fileverity.com/es/docs/text-detections

`POST /text/detections` ejecuta una comprobación de texto. Clasifica texto sin formato con `fvdoc-3-text` y devuelve los pasajes escritos con IA. Es síncrono: el resultado va en la respuesta.

Los ejemplos leen el texto de un archivo, así que guarde antes cualquier pasaje de 100 palabras o más como `essay.txt`. El [Inicio rápido](https://fileverity.com/es/docs/quickstart.md#text) incluye un comando que escribe un ejemplo.

**Solicitud: cURL**

```bash
curl https://api.fileverity.com/v1/text/detections \
  -H "Authorization: Bearer $FILEVERITY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6b9d1c1e-3b0f-4c0a-9a53-2d1c9d6b7e11" \
  -d "$(jq -Rs '{text: ., language: "en"}' essay.txt)"
```

**Solicitud: JavaScript**

```javascript
import { readFile } from "node:fs/promises";
import { randomUUID } from "node:crypto";

const response = await fetch("https://api.fileverity.com/v1/text/detections", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.FILEVERITY_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": randomUUID(),
  },
  body: JSON.stringify({ text: await readFile("essay.txt", "utf8"), language: "en" }),
});
const detection = await response.json();
```

**Solicitud: Python**

```python
import os
import uuid
import requests

response = requests.post(
    "https://api.fileverity.com/v1/text/detections",
    headers={
        "Authorization": "Bearer " + os.environ["FILEVERITY_API_KEY"],
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"text": open("essay.txt", encoding="utf-8").read(), "language": "en"},
)
detection = response.json()
```

## Cuerpo de la solicitud

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `text` | cadena | Sí | Texto sin formato de al menos 100 palabras y como máximo 100 000 caracteres. |
| `model` | cadena | No | Valor predeterminado: `fvdoc-3-text`. Acepta el ID del modelo o el ID de su versión fechada `fvdoc-3-text-2026-11-03`. |
| `language` | cadena o null | No | Código ISO 639-1: `en`, `fr`, `de`, `es`, `zh`. Se detecta automáticamente si se omite. |

Los campos desconocidos se rechazan con `invalid_parameter`. Al comprobar el mínimo de 100 palabras, los caracteres chinos se cuentan a razón de unos dos por palabra.

## Respuesta

**200 OK**

```json
{
  "id": "tdet_8Hk2pQ4vN9sL1xR7cW3mY6zB",
  "object": "text.detection",
  "created": 1793664000,
  "model": "fvdoc-3-text-2026-11-03",
  "livemode": true,
  "language": "en",
  "verdict": "mixed",
  "score": 0.97,
  "ai_fraction": 0.41,
  "segments": [
    {
      "start": 212,
      "end": 433,
      "score": 0.97
    },
    {
      "start": 579,
      "end": 790,
      "score": 0.93
    }
  ],
  "usage": {
    "characters": 1412,
    "free_characters": 0,
    "billed_units": 2
  }
}
```

| Campo | Tipo | Descripción |
| --- | --- | --- |
| `id` | cadena | ID de la detección, con el prefijo `tdet_`. |
| `object` | cadena | Siempre `text.detection`. |
| `created` | entero | Marca de tiempo Unix. |
| `model` | cadena | Versión fechada que produjo el resultado. |
| `livemode` | booleano | `false` para las claves de prueba. |
| `language` | cadena | El idioma utilizado: el que usted envió o el detectado. |
| `verdict` | cadena | `ai`: el texto parece escrito con IA de principio a fin. `mixed`: pasajes escritos con IA dentro de un texto escrito por una persona. `human`: no se encontró ningún pasaje escrito con IA. |
| `score` | número | De 0 a 1. Puntuación del modelo para el pasaje que más se parece a un texto escrito con IA. |
| `ai_fraction` | número | De 0 a 1. Proporción del texto evaluado que se encuentra dentro de segmentos escritos con IA. |
| `segments` | array | Los pasajes escritos con IA. Cada uno tiene `start`, `end` (exclusivo) y `score`. |
| `usage` | objeto | `characters` evaluados, `free_characters` cubiertos por su inicio gratuito y `billed_units` realmente cobradas tras descontar los caracteres gratuitos. |

> **Nota.** La detección de texto devuelve una estimación estadística, no una prueba de autoría. Los límites de los segmentos son aproximados. Úsela como un elemento más de una revisión humana y no se base solo en ella para tomar decisiones que afecten a una persona.

## Posiciones de los segmentos

`start` y `end` son posiciones dentro del texto que envió, contadas en puntos de código Unicode, no en bytes ni en unidades UTF-16. Los límites de los segmentos son aproximados y pueden incluir oraciones adyacentes. Las cadenas de JavaScript se indexan por UTF-16, así que divida primero la cadena en puntos de código:

**Extraer un segmento: JavaScript**

```javascript
const points = Array.from(text);
for (const { start, end } of detection.segments) {
  console.log(points.slice(start, end).join(""));
}
```

**Extraer un segmento: Python**

```python
for segment in detection["segments"]:
    print(text[segment["start"]:segment["end"]])
```

Las cadenas de Python ya se indexan por punto de código.

## Facturación

- El texto se factura por cada 1000 caracteres a 0,14 US$, contados en puntos de código Unicode. Cada solicitud se redondea al alza a unidades enteras, con un mínimo de una unidad.
- Primero se descuentan los caracteres de texto de su inicio gratuito, que se indican en `usage.free_characters`. `usage.billed_units` es el número de unidades que se cobran tras descontarlos, así que el importe es `billed_units` multiplicado por 0,14 US$. Ejemplo: 1412 caracteres, cuando ya no quedan caracteres gratuitos, se facturan como 2 unidades: 0,28 US$.
- Las solicitudes rechazadas antes de la evaluación no se cobran: parámetros no válidos, texto demasiado corto o demasiado largo, idiomas no admitidos y casos similares. Una comprobación que falla dentro del servicio (`service_unavailable`) se libera y no se cobra.
- Si los fondos son insuficientes, se devuelve `insufficient_balance` (402).

## Qué se almacena

El texto se evalúa y se descarta. Nunca se almacena, por lo que no se puede recuperar más tarde.

Fileverity conserva el resultado sin el texto (veredicto, puntuaciones, posiciones de los pasajes y uso) durante 7 días, para que la Consola pueda mostrarlo y el uso pueda facturarse y auditarse. Una solicitud repetida con la misma `Idempotency-Key` recibe el resultado guardado durante 24 horas. Las detecciones de texto son síncronas: no aparecen en `GET /analyses` y no envían eventos de webhook. Las claves de prueba no registran nada. Consulte [Conservación de datos y seguridad](https://fileverity.com/es/docs/security.md).

## Errores

| Código | Estado | Causa |
| --- | --- | --- |
| `text_too_short` | 400 | Menos de 100 palabras. |
| `text_too_long` | 413 | Más de 100 000 caracteres. Divida el texto en varias solicitudes. |
| `unsupported_language` | 400 | El idioma no está admitido o no se pudo detectar. |
| `unsupported_media_type` | 415 | El cuerpo no se envía como `application/json`. |
| `invalid_json` | 400 | El cuerpo no es un objeto JSON. |
| `missing_parameter` | 400 | Falta el campo `text`. |
| `invalid_parameter` | 400 | Un campo tiene un tipo incorrecto, se envió un campo desconocido o la `Idempotency-Key` no es válida. |
| `model_not_found` | 404 | El `model` es desconocido. |
| `insufficient_balance` | 402 | El saldo no cubre la solicitud. |
| `spend_limit_reached` | 402 | La clave alcanzó su límite de gasto mensual. |
| `idempotency_mismatch`, `idempotency_in_progress` | 409 | La `Idempotency-Key` se usó con un cuerpo distinto, o su primera solicitud sigue en curso. |
| `service_unavailable`, `analysis_failed` | 503, 502 | El servicio de detección no está disponible temporalmente o está ocupado. No se cobra; reintente. `service_unavailable` incluye un encabezado `retry-after`. |

> **Nota.** Envíe `Idempotency-Key` para que, si reintenta tras un tiempo de espera agotado, no se facture dos veces. Consulte [Idempotencia](https://fileverity.com/es/docs/idempotency.md).

