# KolWrite API לסוכני בינה מלאכותית

כך נותנים לסוכן בינה מלאכותית (Claude Code, ‏Codex, ‏Cursor או סקריפט משלכם)
להפוך הקלטות לתמלילים, לכתוביות SRT ולתזמוני מילים באמצעות ה-API של פלטפורמת
KolWrite בכתובת `https://api.kolwrite.com`. אדם יוצר אסימון פעם אחת; הסוכן קורא
אותו ממשתנה סביבה ופונה ל-HTTPS רגיל. אין צורך ב-SDK.

זהו ה-API של הפלטפורמה עם אסימוני `kol_`. ה-API של הקרדיטים בכתובת
`https://app.kolwrite.com` (כותרת `x-api-key`) הוא API אחר, והוא מתואר ב-
https://console.kolwrite.com/llms.txt (באנגלית).

## 1. נותנים לסוכן אסימון

- הגישה ל-API מופעלת לכל חשבון בנפרד; בלעדיה יצירת אסימון או שימוש בו נדחים.
- אדם יוצר את האסימון ביישום KolWrite (**הגדרות → חשבון → גישת API → יצירת
  אסימון**) ובוחר את הקבוצה הקטנה ביותר של היקפי הרשאה. הסוד (`kol_...`) מוצג
  פעם אחת.
- שמרו אותו במשתנה סביבה, הרחק מהנחיות, מקובצי לוג ומ-git.

| משימה | היקפי הרשאה |
|---|---|
| תמלול וייצוא | `files:write`, `jobs:write`, `jobs:read`, `transcripts:read` |
| גם בדיקת יתרת הקרדיטים | מוסיפים `billing:read` |
| נקודות הקצה התואמות OpenAI | `ai:use` (צורך קרדיטים; אינו חלק מהגדרה המוכנה Automation ביישום) |
| יצירת קישורי שיתוף | מוסיפים `shares:write` |

הדביקו את זה ב-`AGENTS.md`, ב-`CLAUDE.md` או ב-`.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. איזו קריאה מתאימה למה

| מה רוצים | קריאה |
|---|---|
| תמליל של קובץ, עם תזמוני מילים ודוברים | סשן העלאה, אחר כך `POST /api/v1/jobs` (`type: transcription`), אחר כך `GET /api/v1/jobs/{job_id}/export?format=json` |
| כתוביות SRT או VTT | `GET /api/v1/jobs/{job_id}/export?format=srt` או `format=vtt` (מסלול Plus ומעלה) |
| כתוביות בשפה אחרת | `options.target_language` במשימה, ואז ייצוא |
| טקסט פשוט | `export?format=text` |
| טקסט להקלטה קולית קצרה, בלי משימה | `POST /api/v1/ai/openai/audio/transcriptions` |
| צ'אט, תשובות, הטמעות (embeddings) | `/api/v1/ai/openai/*` ([נקודות קצה תואמות OpenAI](/locales/he/openai-compatible.md)) |
| התמליל השמור, עם גרסאות | `GET /api/v1/jobs/{job_id}/artifacts` |
| יתרת הקרדיטים | `GET /api/v1/billing/balance` |
| קישור ציבורי לתמליל | `POST /api/v1/shares` |
| אילו פרופילי מודל קיימים | `GET /api/v1/models` |

## 3. תמלול קובץ ב-Python

```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']}")
```

קבצים גדולים מועלים בחלקים: הסשן מחזיר אז `data.upload_url` בערך `null`, וכתובת
לכל חלק ב-`data.multipart_part_urls` (ראו את
[ההתחלה המהירה](/locales/he/quickstart.md)).

## 4. משתמשים בתזמונים

ייצוא ה-JSON כולל `segments`, ובכל מקטע `start` ו-`end` בשניות, `text`, ‏`speaker`
כשזיהוי הדוברים רץ, ו-`words` (‏`text`, ‏`start`, ‏`end`). תנו לסוכן לבחור מקטעים
לפי אינדקס ולקרוא את הזמנים מהתמליל; לעולם אל תתנו למודל להקליד חותמות זמן.

```python
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)
```

כתוביות מגיעות ישירות מה-API. `include_speakers=false` משמיט את שמות הדוברים,
ו-`max_chars_per_entry` קובע את אורך כל שורת כתובית:

```bash
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"
```

הורדת SRT ו-VTT דורשת מסלול Plus ומעלה. מסלולים אחרים מקבלים HTTP 403 עם הקוד
`subtitle_export_requires_plus`; ייצוא JSON וטקסט אינו מושפע.

## 5. כללים לסוכנים

- שלחו `Idempotency-Key` בעת יצירת משימה, כדי שניסיון חוזר לא יפעיל משימה שנייה.
- נסו שוב אחרי `429`, ‏`502`, ‏`503` ו-`504` עם השהיה מעריכית; ב-`429` המתינו
  לפי `Retry-After`. אל תנסו שוב אחרי `401`, ‏`403` או שגיאות תיקוף. ראו
  [שגיאות](/locales/he/errors.md).
- קראו את `detail.code`, לא את נוסח ההודעה.
- משימה שומרת קרדיטים בעת היצירה ומסדירה אותם בסיומה; בדקו את
  `GET /api/v1/billing/balance` לפני אצווה גדולה.
- קובץ ה-OpenAPI הוא החוזה: כל פעולה מציינת את ההיקף הנדרש שלה ב-`x-required-scope`.

## שאלות

### איך מכינים כתוביות SRT מסרטון באמצעות סוכן בינה מלאכותית?

מעלים את הקובץ, יוצרים משימת תמלול, ממתינים לסטטוס `succeeded` וקוראים לנקודת
הייצוא עם `format=srt`. כתוביות דורשות מסלול Plus ומעלה.

### האם Claude Code או Codex יכולים לקרוא ל-KolWrite API?

כן. הם פונים אליו דרך HTTPS עם אסימון גישה אישי ממשתנה סביבה. אין SDK או שרת MCP
להתקין.

### איך סוכן מקבל חותמות זמן לכל מילה?

מייצאים את המשימה כ-JSON. בכל מקטע יש `words` עם `start` ו-`end` בשניות.
