# Shotto — full agent reference Source: https://www.shottoai.com/skills/shotto/SKILL.md and reference.md # Shotto Shotto (https://www.shottoai.com) is an Israeli service that makes short vertical ad videos **in Hebrew** for small businesses. The product, the scripts, the voice and every API message are Hebrew; this file is English so any agent can read it. Speak to the user in their language, but write briefs and scripts in Hebrew. What it makes: - **Presenter video**: an AI presenter says a Hebrew ad script, written by Shotto from a 2-line brief. 10, 20 or 30 s. - **Comic video** (`format: "faceless"`): illustrated comic panels with a Hebrew voice-over, no presenter. - **Automatic editing**: the user's own clips get captions, music, zooms and an optional end card. - **Ad images**: on the website only (3 credits each); no API endpoint yet. Full details, curl examples and error codes: [reference.md](https://www.shottoai.com/skills/shotto/reference.md). ## Connect - MCP (preferred): `https://www.shottoai.com/mcp`, Streamable HTTP, header `Authorization: Bearer sk_shotto_…`. Claude Code: `claude mcp add --transport http shotto https://www.shottoai.com/mcp --header "Authorization: Bearer $SHOTTO_API_KEY"` - REST: `https://www.shottoai.com/api/v1`, same header. See reference.md. - The user creates the key at https://www.shottoai.com/settings/api. Never print or commit it. ## Credits (one wallet, same as the website) | Action | Cost | |---|---| | Presenter video, regular quality (default) | 1 credit / second: 10 s = 10, 20 s = 20, 30 s = 30 | | Presenter video, `quality: "hd"` | 2 credits / second: 10 s = 20, 20 s = 40, 30 s = 60 | | Comic video (faceless) | 0.4 credit / second: 10 s = 4, 20 s = 8, 30 s = 12 (no quality option) | | Editing the user's footage | first 60 s free (once per account), then 10 credits / minute (1 credit per 6 s, rounded up after a 1-second tolerance) | | Script approval, status checks, presenters, balance | free | | Ad image (website only) | 3 credits | The charge happens **when the job is created**. If the script is never approved it expires and the credits return. A technical failure also returns the credits automatically. Credits are bought only on https://www.shottoai.com (subscriptions and credit packs); the API cannot buy. The free 10 s teaser (once per phone) and the ₪5 first full video are website flows, not API flows. ## Hard rules 1. **Never spend credits without an explicit yes.** Before `shotto_create_video` or `shotto_create_edit`, tell the user exactly what will be charged ("20-second presenter video, 20 credits; your balance is 85") and wait for a clear confirmation in this conversation. A general "go ahead" earlier does not cover a new paid job. 2. **Show the full script before approving.** After creation the script is written automatically. Show the hook and every line to the user, verbatim, in Hebrew. Call `shotto_approve_video` only after the user explicitly approves it. 3. **Approval is final.** Once approved, filming starts and the video cannot be remade or refunded for taste, style or a word that sounds different. Only small wording edits are possible, and only before approval. 4. **Never retry a paid call.** If `shotto_create_video` / `shotto_create_edit` errors or times out, call `shotto_list_jobs` first to see whether the job exists. Never call create again automatically. 5. **No invented claims.** The brief contains only facts the user gave you: no made-up prices, discounts, cities, durations, reviews or results. The user is responsible for what the video says. 6. Check `shotto_balance` before proposing a paid job. If it is too low, send the user to https://www.shottoai.com. ## Video flow (MCP) 1. `shotto_balance` → know what the user can afford. 2. `shotto_presenters` (optionally `gender`) → show a few names/thumbnails, let the user pick. Skip for comics. 3. Build the brief with the user (see below). Pick the length. State the cost. **Get a yes.** 4. `shotto_create_video` → returns `id`, `credits_charged`. 5. Poll `shotto_video_status` every 20-30 s until `status = awaiting_approval` (usually under a minute). 6. **Show the script** (`script.hook` + `script.lines`). Ask: approve as is, or change a word? 7. `shotto_approve_video` with `id` (and optionally an edited `script` with the same number of lines). 8. Poll `shotto_video_status` every 30-60 s until `done` (about 5 / 7 / 9 minutes after approval for 10 / 20 / 30 s; `estimated_seconds` is given). `in_review` means Shotto's team checks it before release; keep polling. Deliver `video_url`. ## Edit flow (MCP) 1. Get each clip's size in bytes and duration (e.g. `ffprobe`). MP4 or MOV, up to 250 MB per clip, up to 6 clips, up to 180 s total. 2. Compute the cost: free seconds left (from `shotto_balance`) first, then 10 credits/minute. State it. **Get a yes.** 3. `shotto_upload_url` per clip → `curl -X PUT -H "Content-Type: video/mp4" --data-binary @clip.mp4 ""`. 4. `shotto_create_edit` with `paths` (in order), `seconds` (total), optional `options` (`skin`: bold | clean | neon | comic; `captions`, `music`, `endcard`, `reframe`). 5. Poll `shotto_edit_status` until `done` → `video_url` (about 2 minutes + 1 per minute of footage). The same clip is never charged twice (`duplicate: true`). ## A brief that produces a good script Required fields: `business_name`, `vertical` (clinic, fitness, food, realestate, education, ecommerce, home, professional, other), `brief` (10-600 chars), `target_seconds`. Optional `quality`: `regular` (default, 1080x1920, fine for reels and stories) or `hd` (sharper, double the credits); ask only if the user cares about sharpness. The brief (Hebrew) should contain: - the business name as it should be spoken; - what they sell, and for whom; - **one** concrete fact or offer (e.g. "שיעור ניסיון ראשון במתנה", "משלוח חינם מעל מאתיים שקל"); - numbers written in words, never digits; - nothing the user did not say. Good: `סטודיו פילאטיס מכשירים ברמת גן לנשים אחרי לידה. שיעור ניסיון ראשון במתנה.` Bad: `best pilates studio, call now!!!` (English, no fact, no audience). Length: **10 s** = one message (hook + 1 line, ~22 words) · **20 s** = default (hook + 3 lines, ~40 words) · **30 s** = a short story (same 3-line script, filmed as 3 takes). Pick 20 unless the user asks otherwise. Optional: `tone` (friendly | energetic | calm | professional), `cta_type` (leads | whatsapp | website | call) with `whatsapp` or `website`, `cta` (custom Hebrew sentence), `presenter_gender` (voice for comics). ## Errors 401 bad/missing key → ask the user to create one at /settings/api. 402 `NO_CREDITS` → tell the user to buy credits at https://www.shottoai.com; do not retry. 409 `NOT_READY` → the script is not written yet, poll and try later; 409 `NOT_AWAITING` → already approved or expired, check status. 429 → wait `Retry-After` seconds (60 requests/min per key; 3 edits per 10 minutes). Messages come back in Hebrew; translate them for the user if needed. --- # Shotto reference for agents Product language: Hebrew. API messages (`error.message`, status labels, MCP summaries) are Hebrew; field names and codes are English. Human docs (Hebrew): https://www.shottoai.com/developers ## Endpoints - MCP: `POST https://www.shottoai.com/mcp` (Streamable HTTP, stateless, JSON responses, no SSE, no sessions). - REST base: `https://www.shottoai.com/api/v1` - Auth for both: `Authorization: Bearer sk_shotto_…` (key from https://www.shottoai.com/settings/api). - Rate limit: 60 requests per minute per key, REST and MCP together. Edits: at most 3 per 10 minutes. - Every action through a key counts as the account owner's action and spends the owner's credits. ## MCP tools and their REST equivalents | MCP tool | REST | Cost | |---|---|---| | `shotto_balance` | `GET /me` | free | | `shotto_presenters` (`gender?`) | `GET /presenters?gender=female\|male` | free | | `shotto_create_video` | `POST /videos` | presenter 1 credit/s (10/20/30), `quality: "hd"` 2 credits/s (20/40/60), comic 0.4 credit/s (4/8/12), charged at creation | | `shotto_video_status` (`id`) | `GET /videos/{id}` | free | | `shotto_approve_video` (`id`, `script?`) | `POST /videos/{id}/approve` | free (no extra charge) | | `shotto_upload_url` (`type`, `size`, `filename?`) | `POST /uploads` | free | | `shotto_create_edit` (`paths`, `seconds`, `options?`) | `POST /edits` | free seconds first, then 10 credits/min | | `shotto_edit_status` (`id`) | `GET /edits/{id}` | free | | `shotto_list_jobs` (`limit?`) | `GET /jobs?limit=20` | free | ## Create video: fields | Field | Required | Values | |---|---|---| | `business_name` | yes | up to 80 chars, as it should be spoken | | `vertical` | yes | clinic, fitness, food, realestate, education, ecommerce, home, professional, other | | `brief` | yes | 10-600 chars, Hebrew | | `target_seconds` | yes | 10, 20, 30 (decides the price) | | `presenter_id` | unless faceless | uuid from presenters | | `format` | no | `presenter` (default) or `faceless` (comic) | | `quality` | no | `regular` (default, 1 credit/s) or `hd` (2 credits/s); presenter videos only, ignored for faceless | | `presenter_gender` | no | female / male, the voice of a comic | | `tone` | no | friendly (default), energetic, calm, professional | | `cta_type` | no | leads (default), whatsapp (+`whatsapp`), website (+`website`), call | | `cta` | no | custom Hebrew CTA sentence, up to 80 chars | Script shape by length: 10 s = hook + 1 line; 20 s and 30 s = hook + 3 lines (30 s is filmed as 3 takes). Budgets enforced by Shotto: hook up to 17 words, each line up to 15, hook + first line up to 22 words, whole 20 s script up to 40 words, no digits (numbers in words), sentences up to 12 words. You do not write the script; Shotto does, from the brief. Only facts from the brief are used, so a vague brief gives a vague script. ## Writing the brief 1. Ask the user for: business name, what they sell, who the customer is, one concrete fact or offer, the CTA (WhatsApp number / website / leave details / call). 2. Write 1-2 Hebrew sentences. One offer, not five. Numbers in words ("שלוש מאות שקל", not "300"). 3. Do not add anything the user did not say: no prices, discounts, cities, guarantees, reviews or results. 4. Show the brief and the price together, and ask for confirmation before creating. Examples: - `מרפאת שיניים בפתח תקווה, הלבנת שיניים בטיפול אחד. בדיקה ראשונה בלי עלות.` - `חנות אונליין לקפה טרי קלוי, משלוח עד הבית תוך יומיים. מאה גרם ראשונים במתנה בהזמנה ראשונה.` ## Statuses Video: `queued` → `scripting` → `awaiting_approval` → `approved` → `generating` → `assembling` → `qa` → `in_review` (team check before release) → `done` (has `video_url`). Terminal: `failed` (credits return), `cancelled`, `expired` (script not approved in time; credits return). Edit: `approved` → … → `done` / `failed`. `video_url` is non-null only when `status = done`. Typical times: the script in under a minute; after approval a video is ready in about 5 / 7 / 9 minutes (10 / 20 / 30 s; `estimated_seconds` on create and approve); an edit takes about 2 minutes + 1 per minute of footage. Under load it can take a few minutes longer. Poll politely: every 20-30 s while waiting for the script, every 30-60 s while filming. Do not exceed the rate limit. ## Approving with edits `script` = `{ "hook": "…", "lines": ["…", "…"] }` with exactly the same number of lines as the written script. Small wording fixes only (a name, a word the user dislikes). Hebrew, no digits. A larger change → tell the user it is a new video (new charge) or that they can request new scripts on the website before paying. ## Errors Body: `{ "error": { "code": "…", "message": "", "details"?: {…} } }`. MCP tool errors return the same JSON with `isError: true`; MCP auth/rate errors are JSON-RPC errors (-32001 unauthorized, -32029 rate limit). | HTTP | Code | What to do | |---|---|---| | 400 | `VALIDATION`, `BAD_REQUEST`, `BAD_SCRIPT`, `BAD_TYPE`, `EMPTY` | fix the input; message says what | | 401 | `UNAUTHORIZED` | key missing/revoked: user creates one at /settings/api | | 402 | `NO_CREDITS` | not enough credits: user buys at https://www.shottoai.com; never retry | | 404 | `NOT_FOUND` | wrong id or another account's job | | 409 | `NOT_READY` | script not written yet: keep polling, approve later | | 409 | `NOT_AWAITING` | already approved, expired or failed: read the status | | 413 | `TOO_BIG` | clip over 250 MB | | 429 | `RATE_LIMIT` | wait `Retry-After` / `retry_after_seconds` | | 500 | `SERVER_ERROR` | for a paid call: check `GET /jobs` before anything else; never auto-retry | ## Policies (from https://www.shottoai.com/ugc/terms) - The script is approved before filming; after approval the video is produced as approved. - A produced video is not remade or refunded for taste, style or pronunciation. Only a technical failure returns credits, automatically. - The free 10 s teaser is once per phone number (plus one retry) and the ₪5 first full video is once per customer; both happen on the website, not through the API. - The content of the script speaks for the business; the account owner is responsible for it. ## REST quickstart (curl) ```bash export SHOTTO_API_KEY=sk_shotto_... B=https://www.shottoai.com/api/v1 H="Authorization: Bearer $SHOTTO_API_KEY" curl -s $B/me -H "$H" # balance curl -s "$B/presenters?gender=female" -H "$H" # pick a presenter id # after the user confirmed "20 s presenter video = 20 credits": curl -s -X POST $B/videos -H "$H" -H "Content-Type: application/json" -d '{ "business_name": "סטודיו נועה", "vertical": "fitness", "brief": "סטודיו פילאטיס בתל אביב לנשים. שיעור ניסיון ראשון במתנה.", "target_seconds": 20, "presenter_id": "", "cta_type": "whatsapp", "whatsapp": "0501234567" }' # → 201 { "id": "…", "credits_charged": 20, … } curl -s $B/videos/ -H "$H" # until status = awaiting_approval; show script curl -s -X POST $B/videos//approve -H "$H" # only after the user approved the script curl -s $B/videos/ -H "$H" # until status = done → video_url ``` Edit: ```bash curl -s -X POST $B/uploads -H "$H" -H "Content-Type: application/json" \ -d '{"type":"video/mp4","size":48211337,"filename":"clip.mp4"}' # → path, upload_url (valid 2 h) curl -X PUT -H "Content-Type: video/mp4" --data-binary @clip.mp4 "" # after the user confirmed the cost: curl -s -X POST $B/edits -H "$H" -H "Content-Type: application/json" \ -d '{"paths":[""],"seconds":42.5,"options":{"skin":"bold","captions":true,"music":true}}' curl -s $B/edits/ -H "$H" # until done → video_url ``` MCP smoke test: ```bash curl -s -X POST https://www.shottoai.com/mcp -H "$H" -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"shotto_balance","arguments":{}}}' ```