API Docs
CA
Primers passos

Creació del primer informe

L’anàlisi pot trigar uns segons. L’API accepta el text, el processa fora de la petició inicial i ofereix un recurs independent per consultar-ne l’estat.

Autenticació

Les integracions directes requereixen una clau activa. Envia-la a la capçalera Authorization i no la incloguis en codi públic ni en aplicacions client.

Authorization: Bearer art_live_…

SDKs oficials

Via d’integració recomanada. Els clients oficials encapsulen el cicle asíncron complet —creació, espera conforme a Retry-After, reintents idempotents i recollida del resultat— en una única crida, sense dependències de tercers.

pip install artext
# Instal·la el client oficial: pip install artext
# Executa aquest codi al servidor; no exposis mai la clau al navegador.
import os

from artext import Artext

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

# analyze crea l'informe, espera respectant Retry-After i retorna el resultat.
# Una anàlisi fallida llança una excepció amb el detall de l'error.
report = client.analyze(
    "En el dia d’avui es durà a terme la revisió de la sol·licitud.",
    language="ca",
    domain_slug="llenguatge-clar",
    text_type_slug="text-juridic-administratiu-dirigit-a-la-ciutadania",
)

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
// Instal·la el client oficial: npm install artext
// Executa aquest codi al servidor; no exposis mai la clau al navegador.
import { Artext } from "artext";

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

// analyze crea l'informe, espera respectant Retry-After i retorna el resultat.
// Una anàlisi fallida llança una excepció amb el detall de l'error.
const report = await client.analyze({
  text: "En el dia d’avui es durà a terme la revisió de la sol·licitud.",
  language: "ca",
  domainSlug: "llenguatge-clar",
  textTypeSlug: "text-juridic-administratiu-dirigit-a-la-ciutadania",
});

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);
  }
}

Els exemples següents mostren el cicle complet sobre HTTP, sense SDK. L’esquema openapi.json permet generar clients per a altres llenguatges.

Semàntica asíncrona

arText segueix la semàntica estàndard d’HTTP per a tasques que no acaben dins la petició inicial. No cal mantenir obert el POST ni triar un interval arbitrari.

202 AcceptedEl text ha estat acceptat, però l’anàlisi encara pot estar a la cua o executant-se. No significa que l’informe estigui complet.
status_url + LocationIdentifiquen el recurs de l’informe. Consulta sempre aquesta mateixa URL; no repeteixis el POST per saber si ha acabat.
Retry-AfterNombre mínim de segons que cal esperar abans de la consulta següent. Una consulta anterior pot rebre 429.
events_urlFlux opcional Server-Sent Events amb els canvis d’estat. Si no l’utilitzes o s’interromp, status_url és el mecanisme de reserva.

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

Seqüència d’integració

L’anàlisi no s’executa dins de la petició inicial: s’encua i es processa en segon pla. La integració consta dels cinc passos següents.

La petició de creació no s’ha de mantenir oberta a l’espera del resultat. La creació i la recollida de l’informe són operacions independents; aquesta separació permet tolerar anàlisis llargues, reinicis i proxies intermedis.

# Desa la clau fora del codi i carrega-la des de l’entorn.
# Requereix curl i jq.
# export ARTEXT_API_KEY='art_live_...'
set -euo pipefail
API_BASE='http://uned.tail9cc3dd.ts.net'
IDEMPOTENCY_KEY="report-$(date +%s)-$RANDOM"
headers_file=$(mktemp)
trap 'rm -f "$headers_file"' EXIT

# Crea l’informe una sola vegada. Idempotency-Key permet repetir el POST amb seguretat després d’un error de xarxa.
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":"ca","domain_slug":"llenguatge-clar","text_type_slug":"text-juridic-administratiu-dirigit-a-la-ciutadania","text":"En el dia d’avui es durà a terme la revisió de la sol·licitud.","external_id":"document-123"}')

# status_url és relatiu: resol-lo 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 mateix informe respectant Retry-After i amb un límit 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

# Processa el resultat només despré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

# Desa la clau fora del codi i carrega-la des de l’entorn.
API_BASE = 'http://uned.tail9cc3dd.ts.net'
API_KEY = os.environ["ARTEXT_API_KEY"]
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
payload = {'language': 'ca', 'domain_slug': 'llenguatge-clar', 'text_type_slug': 'text-juridic-administratiu-dirigit-a-la-ciutadania', 'text': 'En el dia d’avui es durà a terme la revisió de la sol·licitud.', 'external_id': 'document-123'}

# Crea l’informe una sola vegada. Idempotency-Key permet repetir el POST amb seguretat després d’un error de xarxa.
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 és relatiu: resol-lo contra API_BASE.
status_url = urljoin(f"{API_BASE}/", created["status_url"])
retry_after = int(response.headers.get("Retry-After", "2"))

# Consulta el mateix informe respectant Retry-After i amb un límit 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")

# Processa el resultat només despré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+. Executa aquest codi al servidor; no exposis mai la clau al navegador.
const API_BASE = "http://uned.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 l’informe una sola vegada. Idempotency-Key permet repetir el POST amb seguretat després d’un error de xarxa.
const createdResponse = await api("v1/reports", {
  method: "POST",
  headers: { "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({"language":"ca","domain_slug":"llenguatge-clar","text_type_slug":"text-juridic-administratiu-dirigit-a-la-ciutadania","text":"En el dia d’avui es durà a terme la revisió de la sol·licitud.","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 mateix informe respectant Retry-After i amb un límit 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");
}

// Processa el resultat només despré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);
}

Defineix ARTEXT_API_KEY a l’entorn. Els exemples respecten Retry-After, recomanen Idempotency-Key i abandonen al cap de 3 minuts.

Cicle de vida de l’informe

POST respon 202; l’anàlisi continua a la cua. Utilitza el flux SSE d’events_url o consulta status_url fins a arribar a un estat terminal, sense tornar a crear l’informe.

queued

Acceptat i pendent. Espera abans de tornar a consultar.

running

L’analitzador està treballant. Continua el polling.

completed

Estat terminal correcte. result conté l’informe.

failed

Estat terminal fallit. Registra error i X-Request-ID.

SSE és opcional. Si fas polling, respecta sempre Retry-After; una consulta prematura rep 429. No interpretis position_in_queue com una estimació temporal.

202 · A la cua

{
  "events_url": "/v1/reports/rep_7f12a4c8/events",
  "external_id": "document-123",
  "report_id": "rep_7f12a4c8",
  "status": "queued",
  "status_url": "/v1/reports/rep_7f12a4c8"
}
SegüentModel de resultats