API Reference
Add Skryber-quality transcription to your own apps. A simple REST API over HTTPS: send a media URL, get back clean text with word-level timestamps. More endpoints (clip generation, export) are on the way.
Your API keys
Create a key below, then pass it as a Bearer token on every request. The full key is shown only once at creation — store it somewhere safe. Revoke a key any time; it stops working immediately.
Authentication
Authenticate every request with your secret key in the Authorization header. Keep your keys server-side — never ship them in a browser or mobile app.
Authorization: Bearer sky_live_xxxxxxxxxxxxxxxx
Rate limits
Requests are limited per key (default 60 per minute). Every response includes your current limit state; a 429 means you should retry after the window resets (see Retry-After).
X-RateLimit-Limit: 60 X-RateLimit-Remaining: 59 X-RateLimit-Reset: 42
Transcribe audio or video
/api/v1/transcribeTranscribes the media at a public URL and returns the full text plus word-level timestamps and confidence. Uses the same engine as the Skryber editor, including the automatic fallback for music-heavy audio.
Body parameters
urlstringrequiredA publicly reachable http(s) URL to an audio or video file. (Aliases: audio_url, media_url.)
modelstringoptionalSpeech model. Defaults to nova-2; pass nova-3 for hard audio (distant mics, crowd noise).
titlestringoptionalOptional label for your own bookkeeping.
Request
curl https://www.skryber.com/api/v1/transcribe \
-H "Authorization: Bearer sky_live_REPLACE_WITH_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/podcast.mp3"
}'const res = await fetch("https://www.skryber.com/api/v1/transcribe", {
method: "POST",
headers: {
"Authorization": "Bearer sky_live_REPLACE_WITH_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com/podcast.mp3" }),
});
const data = await res.json();
console.log(data.text);import requests
res = requests.post(
"https://www.skryber.com/api/v1/transcribe",
headers={"Authorization": "Bearer sky_live_REPLACE_WITH_YOUR_KEY"},
json={"url": "https://example.com/podcast.mp3"},
)
print(res.json()["text"])Response
{
"id": "txn_4e1c8b2a-...",
"object": "transcription",
"duration": 184.32,
"language": "en",
"text": "Welcome back to the show. Today we're talking about...",
"words": [
{ "word": "Welcome", "start": 0.08, "end": 0.42, "confidence": 0.99 },
{ "word": "back", "start": 0.42, "end": 0.71, "confidence": 0.98 }
]
}idstringoptionalUnique id for this transcription.
durationnumberoptionalMedia length in seconds.
languagestringoptionalDetected language code (e.g. en).
textstringoptionalThe full transcript as a single string.
wordsarrayoptionalPer-word objects with word, start, end (seconds), and confidence (0–1).
Viral clips pipeline
Import a video from a URL and Skryber runs the whole pipeline for you — download, transcription, AI viral-clip analysis, and auto-render of the top clips. Imports and renders are asynchronous: the call returns a job_id you poll until status is completed (queued means waiting for a worker slot — long waits are capacity, not failure).
POST/api/v1/videosImport a video from a public URL. Body: { url, title?, prompt?, caption_style? } — prompt is a creative brief for the analysis; caption_style sets the look of this project's clips (choose it here — the top clips auto-render during import). Idempotent per URL per hour. Returns { id, job_id }.
GET/api/v1/videosList your videos, newest first. ?limit= (max 50) ?offset=.
GET/api/v1/videos/{id}One video with its transcript summary and all of its clips.
GET/api/v1/videos/{id}/transcriptTranscript text. Add ?include=words for word-level timestamps.
GET/api/v1/clipsList AI clips. ?video_id= scopes to one project. status 'completed' rows carry the rendered MP4 in url; 'pending' rows are suggestions.
GET/api/v1/caption-stylesThe caption preset library (Hormozi, Karaoke, Beast Box, ...). Pass an id to render as caption_style.
POST/api/v1/clips/{id}/renderRender a pending clip to a real MP4 (smart reframing + animated captions). Body: { caption_style?, aspect_ratio? }. Without caption_style the render uses a plain default. Idempotent + single-flight.
GET/api/v1/metricsSynced platform performance: totals, per-platform rollup, top posts by views, and decided Hook-test winners. ?days=1-90 (default 30). Metrics sync every ~6h from X, Instagram and YouTube; unsupported platforms report supported_targets 0, never fabricated zeros.
GET/api/v1/jobs/{id}Poll an import or render job. result.url holds the output when the job produces one; failed jobs carry error.
Typical flow: POST /videos → GET /jobs/{job_id} until completed → GET /clips?video_id= → POST /clips/{id}/render for any pending clip you want as a file. The full machine-readable contract lives in the OpenAPI spec.
MCP server (for AI agents)
Every endpoint above is also exposed as a tool over the Model Context Protocol. The server is Streamable HTTP at https://www.skryber.com/api/mcp with two ways in: OAuth 2.1 — web connectors (claude.ai, ChatGPT) just add the server URL and you approve the connection in your browser — or the same Authorization: Bearer sky_live_... header as REST. Either way: identical plan, quota, and rate-limit rules. Manage OAuth-connected agents under Settings → Connected agents.
claude mcp add --transport http skryber https://www.skryber.com/api/mcp # then run /mcp and choose Authenticate — approve it in your browser
That runs the same OAuth flow as the web connectors: you approve it once and the token is stored by your client, never written into a config file. Prefer an API key (CI, servers, anything headless)? Add the header instead — replace the placeholder with a real key, or every call comes back 401 invalid API key.
claude mcp add --transport http skryber https://www.skryber.com/api/mcp \ --header "Authorization: Bearer sky_live_REPLACE_WITH_YOUR_KEY"
Tools: transcribe, import_video, list_videos, get_video, get_transcript, list_clips, list_caption_styles, render_clip, get_job, get_performance_metrics. Discovery card: /.well-known/mcp/server-card.json.
Register an OAuth app
Only needed when a connector's form asks for a Client ID ("bring your own OAuth app"). Most clients — claude.ai, ChatGPT — register themselves automatically and just need the server URL. Copy the redirect URI from the vendor's form into the field below.
Errors
Errors return the matching HTTP status and a JSON body of the form { "error": { "type", "message" } }.
400invalid_request_errorMalformed request — bad JSON, or a missing/invalid url.
401authentication_errorMissing, invalid, or revoked API key.
402quota_errorMonthly usage / minute limit reached for the account.
403permission_errorThe key lacks the scope this endpoint requires.
429rate_limit_errorToo many requests — back off and retry after Retry-After.
502transcription_errorThe media couldn't be fetched or transcribed.
Build with confidence
Live platform health and uptime are always available — wire the status endpoint into your own monitoring.