API Docs
Primeros pasos

Creación del primer informe

El análisis puede tardar varios segundos. La API acepta el texto, lo procesa fuera de la petición inicial y ofrece un recurso independiente para consultar su estado.

Autenticación

Las integraciones directas requieren una clave activa. Envíala en la cabecera Authorization y no la incluyas en código público ni en aplicaciones cliente.

Authorization: Bearer art_live_…

SDKs oficiales

Vía de integración recomendada. Los clientes oficiales encapsulan el ciclo asíncrono completo —creación, espera conforme a Retry-After, reintentos idempotentes y recogida del resultado— en una única llamada, sin dependencias de terceros.

pip install artext-client
# Instala el cliente oficial: pip install artext-client
# Ejecuta este código en servidor; nunca expongas la clave en el navegador.
import os

from artext_client import ArtextClient

client = ArtextClient(
    api_key=os.environ["ARTEXT_API_KEY"],
    base_url="http://wuned.tail9cc3dd.ts.net",
)

# analyze crea el informe, espera respetando Retry-After y devuelve el resultado.
# Un análisis fallido lanza una excepción con el detalle del error.
report = client.analyze("En el día de hoy se realizará la revisión de la solicitud.", language="es")

print(report.result.measurement("word-count").value)
for suggestion in report.result.suggestions:
    print(suggestion.metric_id, suggestion.summary)
    for occurrence in suggestion.occurrences:
        print("  ", occurrence.text, "->", occurrence.replacement)
npm install artext-client
// Instala el cliente oficial: npm install artext-client
// Ejecuta este código en servidor; nunca expongas la clave en el navegador.
import { ArtextClient } from "artext-client";

const client = new ArtextClient({
  apiKey: process.env.ARTEXT_API_KEY,
  baseUrl: "http://wuned.tail9cc3dd.ts.net",
});

// analyze crea el informe, espera respetando Retry-After y devuelve el resultado.
// Un análisis fallido lanza una excepción con el detalle del error.
const report = await client.analyze({ text: "En el día de hoy se realizará la revisión de la solicitud.", language: "es" });

for (const suggestion of report.result.suggestions) {
  console.log(suggestion.metric_id, suggestion.summary);
  for (const occurrence of suggestion.occurrences) {
    console.log("  ", occurrence.text, "->", occurrence.replacement);
  }
}

Los ejemplos siguientes muestran el ciclo completo sobre HTTP, sin SDK. El esquema openapi.json permite generar clientes para otros lenguajes.

Semántica asíncrona

arText sigue la semántica estándar de HTTP para trabajos que no terminan dentro de la petición inicial. No es necesario mantener abierto el POST ni elegir un intervalo de consulta arbitrario.

202 AcceptedEl texto ha sido aceptado, pero el análisis todavía puede estar en cola o ejecutándose. No significa que el informe esté completado.
status_url + LocationIdentifican el recurso del informe. Consulta siempre esa misma URL; no repitas el POST para saber si ha terminado.
Retry-AfterNúmero mínimo de segundos que debes esperar antes de la siguiente consulta. Una consulta anterior puede recibir 429.
events_urlFlujo opcional Server-Sent Events con los cambios de estado. Si no lo utilizas o se interrumpe, status_url es el respaldo.

HTTP Semantics · 202HTTP Semantics · Retry-AfterHTML · Server-sent events

Secuencia de integración

El análisis no se ejecuta dentro de la petición inicial: se encola y se procesa en segundo plano. La integración consta de los cinco pasos siguientes.

La petición de creación no debe mantenerse abierta a la espera del resultado. La creación y la recogida del informe son operaciones independientes; esta separación permite tolerar análisis largos, reinicios y proxies intermedios.

# Guarda la clave fuera del código y cárgala desde el entorno.
# Requiere curl y jq.
# export ARTEXT_API_KEY='art_live_...'
set -euo pipefail
API_BASE='http://wuned.tail9cc3dd.ts.net'
IDEMPOTENCY_KEY="report-$(date +%s)-$RANDOM"
headers_file=$(mktemp)
trap 'rm -f "$headers_file"' EXIT

# Crea el informe una sola vez. Idempotency-Key hace seguro repetir el POST tras un fallo de red.
created=$(curl --fail-with-body --silent --show-error --dump-header "$headers_file" \
  --request POST "$API_BASE/v1/reports" \
  --header "Authorization: Bearer $ARTEXT_API_KEY" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
  --header 'Content-Type: application/json' \
  --data-binary '{"language":"es","genre":"informe","text":"En el día de hoy se realizará la revisión de la solicitud.","external_id":"document-123"}')

# status_url es relativo: resuélvelo contra API_BASE.
status_url="$API_BASE$(jq -r '.status_url' <<<"$created")"
retry_after=$(awk 'BEGIN { IGNORECASE=1 } /^Retry-After:/ { gsub("\r", "", $2); print $2 }' "$headers_file" | tail -1)
retry_after=${retry_after:-2}

# Consulta el mismo informe respetando Retry-After y con un límite total.
for attempt in $(seq 1 90); do
  sleep "$retry_after"
  report=$(curl --fail-with-body --silent --show-error --dump-header "$headers_file" \
    --header "Authorization: Bearer $ARTEXT_API_KEY" \
    "$status_url")
  status=$(jq -r '.status' <<<"$report")
  case "$status" in
    completed) break ;;
    failed) jq -r '.error.message // "Analysis failed"' <<<"$report" >&2; exit 1 ;;
    queued|running)
      retry_after=$(awk 'BEGIN { IGNORECASE=1 } /^Retry-After:/ { gsub("\r", "", $2); print $2 }' "$headers_file" | tail -1)
      retry_after=${retry_after:-2}
      ;;
    *) echo "Unknown status: $status" >&2; exit 1 ;;
  esac
done

# Procesa el resultado únicamente después de completed.
test "$status" = completed || { echo 'Polling timed out' >&2; exit 1; }
jq '.result.measurements, .result.suggestions' <<<"$report"
import os
import time
import uuid
from urllib.parse import urljoin

import requests

# Guarda la clave fuera del código y cárgala desde el entorno.
API_BASE = 'http://wuned.tail9cc3dd.ts.net'
API_KEY = os.environ["ARTEXT_API_KEY"]
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
payload = {'language': 'es', 'genre': 'informe', 'text': 'En el día de hoy se realizará la revisión de la solicitud.', 'external_id': 'document-123'}

# Crea el informe una sola vez. Idempotency-Key hace seguro repetir el POST tras un fallo de red.
response = requests.post(
    f"{API_BASE}/v1/reports",
    headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
    json=payload,
    timeout=30,
)
response.raise_for_status()
created = response.json()
# status_url es relativo: resuélvelo contra API_BASE.
status_url = urljoin(f"{API_BASE}/", created["status_url"])
retry_after = int(response.headers.get("Retry-After", "2"))

# Consulta el mismo informe respetando Retry-After y con un límite total.
deadline = time.monotonic() + 180
while True:
    time.sleep(retry_after)
    response = requests.get(status_url, headers=HEADERS, timeout=30)
    retry_after = int(response.headers.get("Retry-After", "2"))
    if response.status_code == 429:
        continue
    response.raise_for_status()
    report = response.json()
    status = report["status"]
    if status == "completed":
        break
    if status == "failed":
        raise RuntimeError((report.get("error") or {}).get("message") or "Analysis failed")
    if status not in {"queued", "running"}:
        raise RuntimeError(f"Unknown report status: {status}")
    if time.monotonic() >= deadline:
        raise TimeoutError("Report polling timed out")

# Procesa el resultado únicamente después de completed.
result = report["result"]
for measurement in result["measurements"]:
    print(measurement["metric_id"], measurement["value"], measurement["unit"])
for index, suggestion in enumerate(result["suggestions"]):
    print(index, suggestion["metric_id"], len(suggestion["occurrences"]))
// Node.js 18+. Ejecuta este código en servidor; nunca expongas la clave en el navegador.
const API_BASE = "http://wuned.tail9cc3dd.ts.net";
const API_KEY = process.env.ARTEXT_API_KEY;
if (!API_KEY) throw new Error("ARTEXT_API_KEY is required");

const headers = {
  "Authorization": `Bearer ${API_KEY}`,
  "Content-Type": "application/json"
};
const api = async (path, options = {}) => {
  const response = await fetch(new URL(path, `${API_BASE}/`), {
    ...options,
    headers: { ...headers, ...options.headers },
    signal: AbortSignal.timeout(30_000)
  });
  if (!response.ok && response.status !== 429) {
    throw new Error(`${response.status}: ${await response.text()}`);
  }
  return response;
};
const delay = (milliseconds) =>
  new Promise((resolve) => setTimeout(resolve, milliseconds));

// Crea el informe una sola vez. Idempotency-Key hace seguro repetir el POST tras un fallo de red.
const createdResponse = await api("v1/reports", {
  method: "POST",
  headers: { "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({"language":"es","genre":"informe","text":"En el día de hoy se realizará la revisión de la solicitud.","external_id":"document-123"})
});
const created = await createdResponse.json();
const deadline = Date.now() + 180_000;
let retryAfter = Number(createdResponse.headers.get("Retry-After") || 2);
let report;

// Consulta el mismo informe respetando Retry-After y con un límite total.
while (Date.now() < deadline) {
  await delay(retryAfter * 1_000);
  const statusResponse = await api(created.status_url);
  retryAfter = Number(statusResponse.headers.get("Retry-After") || 2);
  if (statusResponse.status === 429) continue;
  report = await statusResponse.json();
  if (report.status === "completed") break;
  if (report.status === "failed") {
    throw new Error(report.error?.message || "Analysis failed");
  }
  if (!["queued", "running"].includes(report.status)) {
    throw new Error(`Unknown report status: ${report.status}`);
  }
}
if (report?.status !== "completed") {
  throw new Error("Report polling timed out");
}

// Procesa el resultado únicamente después de completed.
for (const item of report.result.measurements) {
  console.log(item.metric_id, item.value, item.unit);
}
for (const [index, item] of report.result.suggestions.entries()) {
  console.log(index, item.metric_id, item.occurrences.length);
}

Define ARTEXT_API_KEY en el entorno. Los ejemplos respetan Retry-After, recomiendan Idempotency-Key y abandonan tras 3 minutos.

Ciclo de vida del informe

POST responde 202; el análisis continúa en la cola. Usa el flujo SSE de events_url o consulta status_url hasta alcanzar un estado terminal, sin crear de nuevo el informe.

queued

Aceptado y pendiente. Espera antes de volver a consultar.

running

El analizador está trabajando. Continúa el polling.

completed

Estado terminal correcto. result contiene el informe.

failed

Estado terminal fallido. Registra error y X-Request-ID.

SSE es opcional. El polling debe respetar siempre Retry-After; una consulta prematura recibe 429. position_in_queue no debe interpretarse como una estimación temporal.

202 · En cola

{
  "events_url": "/v1/reports/rep_7f12a4c8/events",
  "external_id": "document-123",
  "report_id": "rep_7f12a4c8",
  "status": "queued",
  "status_url": "/v1/reports/rep_7f12a4c8"
}
SiguienteModelo de resultados