L’API di KolWrite per gli agenti IA
Come lasciare che un agente IA (Claude Code, Codex, Cursor o uno script tuo) trasformi le registrazioni in trascrizioni, sottotitoli SRT e tempi per parola con l’API di piattaforma di KolWrite su https://api.kolwrite.com. Una persona crea un token una sola volta; l’agente lo legge da una variabile d’ambiente e chiama semplicemente HTTPS. Non serve nessun SDK.
Questa è l’API di piattaforma, con token kol_. L’API dei crediti su https://app.kolwrite.com (intestazione x-api-key) è un’altra API, descritta (in inglese) su https://console.kolwrite.com/llms.txt per chi cerca quella.
1. Dare un token all’agente
- L’accesso all’API è attivato per singolo account; senza, creare o usare un token viene rifiutato.
- Una persona crea il token nell’app KolWrite (Impostazioni → Account → Accesso API → Crea token) e sceglie il più piccolo insieme di ambiti. Il segreto (
kol_...) viene mostrato una sola volta. - Conservalo in una variabile d’ambiente, lontano da prompt, log e git.
| Attività | Ambiti |
|---|---|
| Trascrivere ed esportare | files:write, jobs:write, jobs:read, transcripts:read |
| Controllare anche il saldo crediti | aggiungi billing:read |
| Endpoint compatibili con OpenAI | ai:use (consuma crediti; non fa parte della preimpostazione Automazione dell’app) |
| Creare link di condivisione | aggiungi shares:write |
Incolla questo in AGENTS.md, CLAUDE.md o .cursorrules:
## KolWrite platform API
- Base URL https://api.kolwrite.com. The token is in the environment variable KOLWRITE_TOKEN: send it as "Authorization: Bearer $KOLWRITE_TOKEN" and never print it.
- Flow: POST /api/v1/media/upload-session, PUT the bytes to data.upload_url, POST /api/v1/media/complete, POST /api/v1/jobs, poll GET /api/v1/jobs/{job_id} until status is succeeded, then GET /api/v1/jobs/{job_id}/export?format=json
- Spec: https://kolwrite-docs.pages.dev/openapi.json. Guide: https://kolwrite-docs.pages.dev/agents.md
2. Quale chiamata usare
| Vuoi | Chiamata |
|---|---|
| La trascrizione di un file, con tempi per parola e parlanti | sessione di caricamento, poi POST /api/v1/jobs (type: transcription), poi GET /api/v1/jobs/{job_id}/export?format=json |
| Sottotitoli SRT o VTT | GET /api/v1/jobs/{job_id}/export?format=srt oppure format=vtt (piano Plus o superiore) |
| Sottotitoli in un’altra lingua | options.target_language sul job, poi esportare |
| Testo semplice | export?format=text |
| Il testo di una breve clip vocale, senza job | POST /api/v1/ai/openai/audio/transcriptions |
| Chat, risposte, embeddings | /api/v1/ai/openai/* (endpoint compatibili con OpenAI) |
| La trascrizione salvata, con le versioni | GET /api/v1/jobs/{job_id}/artifacts |
| Il saldo crediti | GET /api/v1/billing/balance |
| Un link pubblico a una trascrizione | POST /api/v1/shares |
| Quali profili di modello esistono | GET /api/v1/models |
3. Trascrivere un file in Python
import json, mimetypes, os, time
import requests
BASE = "https://api.kolwrite.com"
TOKEN = os.environ["KOLWRITE_TOKEN"]
def call(method, path, **kw):
headers = {"Authorization": f"Bearer {TOKEN}", **kw.pop("headers", {})}
r = requests.request(method, BASE + path, headers=headers, timeout=120, **kw)
r.raise_for_status()
return r
def transcribe(path, profile="oracle", language="auto"):
name, size = os.path.basename(path), os.path.getsize(path)
ctype = mimetypes.guess_type(name)[0] or "application/octet-stream"
session = call("POST", "/api/v1/media/upload-session",
json={"filename": name, "file_size_bytes": size,
"content_type": ctype}).json()["data"]
with open(path, "rb") as f:
requests.put(session["upload_url"], data=f, headers=session["headers"],
timeout=3600).raise_for_status()
media = call("POST", "/api/v1/media/complete",
json={"finalize_token": session["finalize_token"]}).json()["data"]
job = call("POST", "/api/v1/jobs",
headers={"Idempotency-Key": f"{name}-{size}-{profile}-{language}"},
json={"type": "transcription",
"input": {"type": "media_ref", "media_id": media["media_id"]},
"profile": profile,
"options": {"language": language,
"diarization": {"mode": "regular"}}}).json()["data"]
while True:
status = call("GET", f"/api/v1/jobs/{job['job_id']}").json()["data"]["status"]
if status in ("succeeded", "failed", "cancelled"):
break
time.sleep(5)
if status != "succeeded":
raise RuntimeError(f"job {job['job_id']} {status}")
export = call("GET", f"/api/v1/jobs/{job['job_id']}/export",
params={"format": "json"}).json()
return job["job_id"], json.loads(export["data"]) # data is a JSON string
job_id, transcript = transcribe("interview.wav")
for seg in transcript["segments"]:
print(f"{seg['start']:.2f}-{seg['end']:.2f} {seg.get('speaker', '')} {seg['text']}")
I file grandi vengono caricati a parti: la sessione restituisce allora data.upload_url come null e un URL per ogni parte in data.multipart_part_urls (vedi la guida rapida).
4. Usare i tempi
L’esportazione JSON contiene segments, ciascuno con start e end in secondi, text, uno speaker quando la separazione dei parlanti è stata eseguita e words (text, start, end). Lascia che l’agente scelga i segmenti per indice e legga i tempi dalla trascrizione; non lasciare mai che un modello scriva a mano i timestamp.
import subprocess
keep = [s for s in transcript["segments"] if "pricing" in s["text"].lower()]
for i, seg in enumerate(keep):
subprocess.run(["ffmpeg", "-y", "-i", "talk.mp4", "-ss", str(seg["start"]),
"-to", str(seg["end"]), f"clip{i}.mp4"], check=True)
I sottotitoli arrivano direttamente dall’API. include_speakers=false omette i nomi dei parlanti e max_chars_per_entry imposta la lunghezza di ogni voce di sottotitolo:
curl -H "Authorization: Bearer $KOLWRITE_TOKEN" -o talk.srt \
"https://api.kolwrite.com/api/v1/jobs/JOB_ID/export?format=srt&include_speakers=false&max_chars_per_entry=42"
Il download di SRT e VTT richiede il piano Plus o superiore. Gli altri piani ricevono HTTP 403 con il codice subtitle_export_requires_plus; le esportazioni JSON e di testo non sono interessate.
5. Regole per gli agenti
- Invia un
Idempotency-Keyquando crei un job, così un nuovo tentativo non ne avvia un secondo. - Riprova dopo
429,502,503e504con backoff esponenziale; su429attendiRetry-After. Non riprovare dopo401,403o errori di validazione. Vedi errori. - Leggi
detail.code, non il testo del messaggio. - Un job riserva crediti alla creazione e li regola al termine; controlla
GET /api/v1/billing/balanceprima di un lotto grande. - Il file OpenAPI è il contratto: ogni operazione indica l’ambito richiesto in
x-required-scope.
Domande
Come faccio i sottotitoli SRT da un video con un agente IA?
Carica il file, crea un job di trascrizione, attendi succeeded e chiama l’endpoint di esportazione con format=srt. I sottotitoli richiedono il piano Plus o superiore.
Claude Code o Codex possono chiamare l’API di KolWrite?
Sì. La chiamano via HTTPS con un token di accesso personale letto da una variabile d’ambiente. Non c’è nessun SDK né server MCP da installare.
Come ottiene un agente il timestamp di ogni parola?
Esporta il job come JSON. Ogni segmento contiene words con start e end in secondi.