SKRYBER//AI
← Back to Home

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.

Base URL: https://www.skryber.comGet an API key ↓

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.

HTTP header
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).

Response headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 42

Transcribe audio or video

POST/api/v1/transcribe

Transcribes 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

urlstringrequired

A publicly reachable http(s) URL to an audio or video file. (Aliases: audio_url, media_url.)

modelstringoptional

Speech model. Defaults to nova-2; pass nova-3 for hard audio (distant mics, crowd noise).

titlestringoptional

Optional label for your own bookkeeping.

Request

cURL
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"
  }'
JavaScript
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);
Python
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

200 application/json
{
  "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 }
  ]
}
idstringoptional

Unique id for this transcription.

durationnumberoptional

Media length in seconds.

languagestringoptional

Detected language code (e.g. en).

textstringoptional

The full transcript as a single string.

wordsarrayoptional

Per-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).

Import & transcripts

GET/api/v1/start

The first-contact briefing for an AI assistant: results this week, accounts that can post, clips waiting, the calendar, the first step and what to say next (try_saying). MCP: get_started.

POST/api/v1/transcribe

Synchronous speech-to-text from a public URL: { url, model?, title? } → text + word timestamps. MCP: transcribe.

POST/api/v1/source-preflight

Check a link before importing: { url } (any public link) or { video_id } (YouTube) → duration, whether it can be read, and whether it is already in the library. MCP: preflight_source.

POST/api/v1/uploads

Open an upload for a video file: returns upload_page_url (give it to the user to pick the file) and upload_url (a signed PUT for agents that send bytes). Open 24 hours. MCP: create_upload.

GET/api/v1/uploads/{id}

Whether the file has arrived: status waiting | uploaded, size_bytes. Then pass upload_id to POST /api/v1/videos or /api/v1/social-posts. MCP: get_upload.

POST/api/v1/videos

Import a video from a public URL or an upload: { url | upload_id, title?, prompt?, caption_style?, force? }. Google Drive, Dropbox and OneDrive share links work. Runs download, transcription and clip analysis; returns { id, job_id }. A URL already in the library is refused (409 duplicate_import, with the existing video) unless force is true. MCP: import_video.

GET/api/v1/videos

Your videos, newest first. ?limit= (max 50) ?offset=. MCP: list_videos.

POST/api/v1/videos/{id}

Change a project: { action: "update", title } | { action: "delete", confirm: true } (removes its transcript and clips). MCP: update_video, delete_video.

POST/api/v1/videos/{id}/analyze

Find clips again: no body re-reads a finished analysis (or retries a failed one); { prompt } or { force: true } runs a fresh AI analysis (AI credits) whose clips are added next to the old ones. Returns job_id. MCP: reanalyze_video.

POST/api/v1/videos/{id}/transcript

Correct misheard words: { replacements: [{ find, replace }], start?, end? }. Clips rendered afterwards caption the fixed words. MCP: fix_transcript.

POST/api/v1/library/search

Find a moment across the library: { query, workspace_id? } → videos that talk about it, each with timestamped moments for create_clip. MCP: search_library.

GET/api/v1/videos/{id}

One video with its transcript summary, all of its AI clips and analysis_status (importing, transcribing, analyzing, complete, no_clips, failed + analysis_error). MCP: get_video.

GET/api/v1/videos/{id}/transcript

A video's transcript. ?include=words adds word timestamps.

GET/api/v1/transcripts

A transcript by ?clip_id= (just that clip's words) or ?video_id= (the whole video). &include_words=true adds timestamps. MCP: get_transcript.

GET/api/v1/jobs/{id}

Poll an import or render job. result.url holds the output when there is one; failed jobs carry error. MCP: get_job.

Clips & rendering

GET/api/v1/clips

Your AI clips. ?video_id= scopes to one project; ?posted=false lists clips never posted or queued (each clip carries posting.state: posted, scheduled or unposted). MCP: list_clips.

POST/api/v1/clips

Cut your own clip by time range: { video_id, start_time, end_time ("2:14" or seconds), title?, aspect_ratio? } → a pending clip to render. MCP: create_clip.

POST/api/v1/supercut

Supercut every time a phrase is said: { video_id, phrases, speaker?, padding?, max_clips?, max_duration?, order?, vibe?, hook?, dry_run? } → a clip of the cuts back to back, rendering (the word highlighted, a counting hook). MCP: create_supercut.

POST/api/v1/custom-video

v860 AI video editor: several raw clips → one finished, branded 9:16 video (listing tours first). { workspace, upload_ids? | video_ids? | urls? | sources?, notes?, brief, style?, target_seconds? (15-90), logo_upload_id?, agent_name?, phone?, brokerage?, address?, price?, details?, cta?, website?, brand_color?, font?, music_url?, music_mood?, no_music?, stabilize?, dry_run? } → job_id; get_job result.url is the MP4 and result.verified says what is in it. AI credits on delivery. MCP: create_custom_video.

GET/api/v1/caption-styles

The caption preset library. Pass an id as caption_style. MCP: list_caption_styles.

POST/api/v1/clips/{id}

Change a clip: { action: "update", title?, description?, start_time?, end_time?, aspect_ratio? } (a new cut makes it pending — render again) | { action: "delete", confirm: true }. MCP: update_clip, delete_clip.

POST/api/v1/clips/{id}/render

Render a clip to MP4: { caption_style?, aspect_ratio?, vibe?, studio_sound?, steady_shot?, hook_thumbnail_url?, generate_hook?, music_url?, music_volume?, overlays? (GIFs, elements, text and B-roll cut-ins), force? }. Idempotent and single-flight; music or overlays make a new version of an already-rendered clip, and force: true re-renders it even when nothing changed. MCP: render_clip, director_pass.

POST/api/v1/videos/{id}/studio-swap

Studio Swap: { set } replaces the video's background with an AI set (clips rendered afterwards use it); { revert_job_id } restores the original. AI credits by length; returns job_id. MCP: studio_swap, revert_studio_swap.

POST/api/v1/clips/{id}/hdr

HDR Master: convert a rendered clip to true HDR (when available). Returns job_id; result.url is the HDR file. MCP: hdr_master.

POST/api/v1/clips/{id}/cutout

Matte the person out of a rendered clip into a transparent WebM: { shadow? }. AI credits on delivery; returns job_id. MCP: remove_background.

POST/api/v1/videos/{id}/export

Export a whole video (or a range) like the editor: { caption_style?, aspect_ratio?, start_time?, end_time?, remove_silence?, remove_fillers?, bleep_profanity?, audio?, music_url?, music_volume?, caption_language?, dub_audio_url?, dub_language?, speaker_layout? } → job_id. MCP: export_video.

POST/api/v1/videos/{id}/dub

Dub a video into another language: { language, voice_id? | voice_match? } → audio_url for export_video. AI credits per minute. MCP: dub_video.

GET/api/v1/voices

Voices for dub_video. MCP: list_voices.

GET/api/v1/videos/{id}/captions

Subtitles for a video: ?format=srt|vtt &start= &end= → the file as text. MCP: get_captions_file.

GET/api/v1/clips/{id}/captions

Subtitles for one clip, timed from its start: ?format=srt|vtt. MCP: get_clip_captions_file.

POST/api/v1/clips/{id}/translate

Captions in another language on the clip's next render: { language: "es" } (or "none"). 1 AI credit per source minute. MCP: translate_clip.

POST/api/v1/clips/{id}/formats

Render one clip in several aspect ratios in one call: { aspect_ratios: ["9:16","1:1","16:9"] } → a clip_id and job_id per format. MCP: render_formats.

POST/api/v1/clips/{id}/posted

Mark a clip posted elsewhere, or clear the mark: { posted, platforms?, url?, note? }. MCP: mark_clip_posted.

GET/api/v1/clips/{id}/share

Watch page, stable download link and thumbnail for a rendered clip. MCP: get_share_assets.

POST/api/v1/clips/{id}/thumbnail

Generate the AI hook thumbnail for a rendered clip. MCP: generate_share_thumbnail.

Design library

GET/api/v1/clips/{id}/broll

Stock footage matched to the clip's words (or ?q=), free to use, in the clip's orientation. ?limit=. MCP: suggest_broll.

POST/api/v1/broll

AI-generated B-roll from a prompt: { prompt, seconds?, aspect_ratio?, quality? } → job_id; get_job result.url is the MP4. MCP: generate_broll.

POST/api/v1/ugc

UGC Studio: an AI actor speaks your line, voice and lip-sync included. { dialogue, actor_description?, setting?, emotion?, aspect_ratio?, duration_seconds?, model? veo|flux-3, character_id? | actor_image_url?, product_name?, product_image_url? } → jobId. Billed in AI credits on delivery. MCP: create_ugc_clip.

GET/api/v1/ugc

A UGC Studio job: ?job_id= → status running | done (result.url, duration, word-timed transcript) | error. Without job_id: your recent UGC clips. MCP: get_ugc_clip, list_ugc_clips.

POST/api/v1/ugc/script

UGC Studio script writer: { description, scene_count?, clip_seconds?, vibe?, gender?, style?, hook?, character_id? } → actor_description and scenes (dialogue, setting, emotion) plus a caption. MCP: write_ugc_script.

GET/api/v1/ugc/characters

Saved UGC characters (people you can cast again): id, name, image_url. MCP: list_ugc_characters.

POST/api/v1/ugc/characters

{ action: "create", name, image_url, has_rights: true } saves a character; { action: "delete", character_id } removes one. MCP: save_ugc_character, delete_ugc_character.

POST/api/v1/ugc/stitch

Join 2-8 finished UGC clips into one video: { job_ids } → url, duration, scene starts. MCP: stitch_ugc_clips.

POST/api/v1/ugc/project

Join UGC clips and save them as a dashboard project that opens in UGC Studio: { job_ids, title?, caption?, actor_description? } → video_id, url, editor_url. MCP: create_ugc_project.

POST/api/v1/music

An original AI music track: { mood?, genre?, energy?, bpm?, prompt?, duration_seconds?, instrumental?, lyrics?, quality? studio|fast } → track.url for render_clip music_url. AI credits per 30 s. MCP: generate_music.

POST/api/v1/clips/{id}/auto-gifs

Reaction GIFs timed to what is said in the clip → ready overlays for render_clip. Paid plans. MCP: auto_gifs.

POST/api/v1/clips/{id}/auto-motion

Animated graphics timed to what is said in the clip → ready element overlays for render_clip. Paid plans. MCP: auto_motion.

POST/api/v1/clips/{id}/broll-plan

Where B-roll cutaways help in a clip and what each should show: shots { at_sec, seconds, prompt, reason }. MCP: plan_broll.

GET/api/v1/archive-broll

B-roll from your own library: ?q= &exclude_video_id= → moments in your other videos. MCP: find_archive_broll.

POST/api/v1/archive-broll

Cut a moment from your library as B-roll: { video_id, at_sec, seconds, label? } → job_id; result.url for a broll overlay. MCP: cut_archive_broll.

GET/api/v1/music

Background music: your AI tracks plus royalty-free tracks cleared for commercial posts (CC0, or CC BY with the credit line). ?query= &source=all|yours|library. MCP: list_music.

GET/api/v1/gifs

GIFs and transparent stickers for overlays. ?q= &type=gifs|stickers. MCP: search_gifs.

GET/api/v1/elements

Animated templates (with settable params) and ready-made designs (with replaceable texts) for overlays. ?category= &q=. MCP: list_elements.

Captions & planning

GET/api/v1/twitch/trending

The most viewed Twitch clips or past broadcasts from any channel: ?view=clips|videos &period=day|week|month, &game= or &channel= (Twitch ids), &after=; also games[] and live[]. ?search= finds channels. In the user's language by default (&language= a code or all), for_you on items matching their interests, saved_searches. No Twitch connection needed; each item url goes to import_video. MCP: get_twitch_trending.

GET/api/v1/kick/trending

The most watched live Kick streams now (?category= a Kick category id), with categories[]; ?search= finds channels (live or not) and categories by name. In the user's language by default (&language= a code or all), for_you on streams matching their interests, saved_searches. No Kick connection needed. A stream's live_url goes to import_video (records 10 minutes); Kick has no clips or past-video listing, so videos_url and clips_url are where the user copies a past video or clip link. MCP: get_kick_trending.

GET/api/v1/twitch/videos

The connected Twitch channel's past broadcasts, highlights and uploads, newest first (?after=). Not connected: { connected: false, connect_url }. MCP: list_twitch_videos.

GET/api/v1/trends

Today's top search trends, each with a recent public video to import, in the user's order (their interests) and country. ?geo= (default: the user's country, else US) &limit=. Each item adds topic and reason; niche[] has rising videos in the user's topics. MCP: get_trending.

GET/api/v1/interests

The topics the user picked, the ones learned from their Clipperverse activity, and every topic available. MCP: get_interests.

POST/api/v1/interests

Change the picked topics: { topics } replaces them, { add } / { remove } edit them (ids or names). MCP: set_interests.

POST/api/v1/hooks

Hook Factory: three ranked hooks (curiosity, bold claim, callout) from a clip_id or transcript; schedule_test posts the clip three times, one hook each. MCP: generate_hooks.

POST/api/v1/captions

Write a caption (hook, CTA, hashtags) from a clip_id or transcript, under the tightest limit of the given platforms, in an optional tone. MCP: generate_caption.

GET/api/v1/post-voice

The creator's posting voice: call to action, signature hashtags and their most reused hashtags. MCP: get_post_voice.

POST/api/v1/post-voice

Set the call to action added to posts: { cta } ("" clears it). MCP: set_post_voice.

POST/api/v1/publish-check

Pre-publish check of a caption against the clip: { caption, title?, clip_id? | video_id?, platforms? } → verdict pass | info | warn and findings (overclaims, ad disclosure, hashtag limits, campaign requirements). Free. MCP: publish_check.

POST/api/v1/videos/{id}/chapters

YouTube chapters for a long video: { regenerate? } → chapters and the description block. AI credits by length; cached. MCP: generate_chapters.

POST/api/v1/videos/{id}/packaging

Titles, thumbnail texts, cold opens and clip hooks for a long video, with a readiness check. 2 AI credits. MCP: package_video.

GET/api/v1/posting-times

Best hours and days per platform in a timezone, from your own results (or labelled general slots), plus the next free slots. ?platforms= &tz= &days= &count=. MCP: get_best_posting_times.

GET/api/v1/plan

The best unposted clips paired with the next free good time slots. Changes nothing. ?count= &platforms= &tz= &days= &rendered_only=. MCP: plan_posts.

Publishing & scheduling

GET/api/v1/social-accounts

Your connected accounts: id (for account_ids), platform, handle, can_post and a note when it cannot (e.g. TikTok public accounts during its app review). MCP: list_social_accounts.

GET/api/v1/social-accounts/connect

A link the user opens to connect a social account: ?platform=youtube|instagram|facebook|x|tiktok|linkedin|threads|bluesky|mastodon, or an import source (twitch|kick: import_only, opens the import box). MCP: get_connect_link.

POST/api/v1/social-accounts/{id}

Disconnect an account: { action: "disconnect", confirm: true }. Removes it from Skryber everywhere; an account linked to a team is refused (409 account_in_team). MCP: disconnect_social_account.

GET/api/v1/social-accounts/quota

Per account: ok / low / exhausted / refilling / reconnect / blocked, posts in the last 24h and the remaining daily limit where the platform has one. MCP: get_posting_quota.

POST/api/v1/social-posts

Publish or schedule: account_ids (or groups) + one of clip_id, job_id, video_url (share links work) or upload_id (posted as is); caption, title, scheduled_for, draft, idempotency_key, labels (up to 5 calendar Labels). Every post has a preview_url and its labels. MCP: publish_post.

POST/api/v1/social-posts/batch

Schedule several clips in one call (the in-app bulk scheduler): { items: [{ clip_id | job_id, caption? }] (1-52), account_ids, start_at (ISO with timezone), interval_minutes? (15-10080, default 60), workspace?, content_type?, rush? (agency client accounts only), draft?, allow_repost?, idempotency_key?, labels? }. Captions left out are written automatically. Each item returns its post (post_id, scheduled_for, caption, preview_url, status) or its own error (already_posted, slot_taken with next_free, not_rendered, not_found). MCP: schedule_batch.

GET/api/v1/social-posts

Your calendar: ?status=scheduled (default) | comma list | all, ?from / ?to, ?order=asc|desc (queue soonest first, history newest first), ?label= (one calendar Label). MCP: list_scheduled_posts.

GET/api/v1/social-posts/{id}

One post: status, per-account results with live links and synced performance, preview_url. MCP: get_post, preview_post.

POST/api/v1/social-posts/{id}

Change a post: { action: "update", scheduled_for?, caption?, title?, labels? ([] clears) } | { action: "cancel" } | { action: "retry", account_ids?, include_uncertain? } | { action: "delete", account_ids? }. MCP: update_scheduled_post, cancel_scheduled_post, retry_post, delete_post.

Results & events

GET/api/v1/social-posts/{id}/replies

The replies to a published post, per platform post: id, text, username, timestamp, permalink, hidden, can_hide. Threads today; other platforms say not supported yet. A Threads account connected before replies were added says to reconnect Threads. MCP: list_post_replies.

POST/api/v1/social-posts/{id}/replies

Hide or unhide one reply on the post's Threads post: { reply_id, hide? (default true), account_id? }. Only replies on your own post. MCP: hide_reply.

GET/api/v1/social-posts/events

Long-poll for post.published / post.failed / post.requeued since a cursor: ?since= &wait= (max 50s) &post_ids=. Returns next_since. MCP: wait_for_post_events.

GET/api/v1/metrics

Synced performance: totals, per-platform rollup, top posts, Hook-test winners. ?days=1-90. MCP: get_performance_metrics.

GET/api/v1/metrics/accounts

The Performance page per connected account: totals and each post's numbers for posts published through Skryber, only the metrics each platform returns. ?account_id= one account (a YouTube channel adds live subscribers, the last 28 days and its latest videos; youtube_channel=false skips it), ?workspace=, ?posts=0-50. MCP: get_account_performance.

Webhooks

POST/api/v1/webhooks

Register an https endpoint for post.published / post.failed / post.requeued. Returns the signing secret once. MCP: create_webhook.

GET/api/v1/webhooks

Your webhooks with their last success and last error. MCP: list_webhooks.

POST/api/v1/webhooks/{id}

{ action: "test" } sends a signed webhook.test now; { action: "delete" } removes it. MCP: test_webhook, delete_webhook.

DELETE/api/v1/webhooks/{id}

Remove a webhook.

Agencies

GET/api/v1/brand-kit

Your brand kit: the logo exports carry and your default caption style. MCP: get_brand_kit.

POST/api/v1/brand-kit

{ action: "set_logo", logo_url } | { action: "remove_logo" } | { action: "set_caption_style", caption_style } | { action: "clear_caption_style" }. MCP: set_brand_logo, remove_brand_logo, set_default_caption_style.

POST/api/v1/workspaces/{id}/library

Move your projects into a team library, or back to their creator's Personal: { video_ids, action: "add" | "remove" }. MCP: move_to_workspace.

GET/api/v1/workspaces/{id}/reviews

A team's review queue: ?status=pending|approved|changes_requested|all. MCP: list_reviews.

POST/api/v1/workspaces/{id}/reviews

Ask the team to review a clip: { clip_id }. MCP: request_review.

GET/api/v1/reviews/{id}

One review: the clip to watch, its status and comments. MCP: get_review.

POST/api/v1/reviews/{id}

{ action: "decide", decision: "approved" | "changes_requested" } (admins) | { action: "comment", body, timecode_sec? }. MCP: decide_review, comment_on_review.

GET/api/v1/workspaces

Your workspaces with their linked accounts: your teams (one per client) and, once it has members, your Personal account first (name "Personal", personal: true). MCP: list_workspaces.

GET/api/v1/posts

One item per platform post made in a workspace (a team, or Personal): ?workspace_id= &from= &to= &status=. MCP: list_workspace_posts.

GET/api/v1/posts/{id}

One platform post.

Outreach delivery

POST/api/v1/delivery/claims

Acquire the exclusive right to send one customer delivery email. MCP: acquire_delivery_claim.

GET/api/v1/delivery/claims/{attemptId}

Inspect a delivery claim without contending for it. MCP: get_delivery_claim.

POST/api/v1/delivery/claims/{attemptId}

Settle a claim with the sent message id, or recover an unsettled one after checking Sent mail. MCP: settle_delivery_claim, recover_delivery_claim.

Platforms

GET/api/v1/promo

Promo Studio drafts (when Promo Studio is enabled for the account). MCP: list_promos.

POST/api/v1/promo

Start a promo video for a product or site: { site_url?, brief?, mode? template|director, aspect?, length?, tone?, voice_id?, music? }. MCP: create_promo.

GET/api/v1/promo/{id}

A promo draft: phase, running job and, when done, the video. MCP: get_promo.

POST/api/v1/promo/{id}

{ action: capture | storyboard | render (credits) | concept (concept_action, note?) | revise (kind, scene_id?, text?) }. MCP: capture_promo, storyboard_promo, render_promo, promo_concept, revise_promo.

GET/api/v1/promo/{id}/quote

What rendering the promo costs in AI credits; nothing is charged. MCP: quote_promo.

GET/api/v1/campaigns

Clipper Studio: paid clipping campaigns open to you (needs a Whop connection). ?cursor= &sort=newest|reward|spots. MCP: list_campaigns.

GET/api/v1/campaigns/{id}

One campaign: reward, rules, approved sources and the original instructions. MCP: get_campaign.

POST/api/v1/campaigns/{id}

{ action: brief | confirm_brief (decisions, acknowledged_original_instructions) | source (workflow_type, original_url?) | plan (specs) }. MCP: extract_campaign_brief, confirm_campaign_brief, choose_campaign_source, plan_campaign_deliverables.

GET/api/v1/campaigns/{id}/workspace

Working a campaign: brief, deliverables, linked projects and clips, next action, workspace id. MCP: get_campaign_workspace.

POST/api/v1/campaign-projects

Import the chosen campaign source as a linked project: { source_selection_id, request_id? } → projectId, jobId. MCP: create_campaign_project.

POST/api/v1/deliverables/{id}

{ action: "assign", clip_id } | { action: "evidence", url, ownership_acknowledged: true }. MCP: assign_clip_to_deliverable, record_post_evidence.

GET/api/v1/campaign-workspaces/{id}/submission

Exactly what a campaign submission would send: ?caption= → intent id, request_hash, warnings. MCP: preview_campaign_submission.

POST/api/v1/campaign-workspaces/{id}/submission

{ action: "review", intent_id } | { action: "confirm" | "send" | "reconcile", request_hash } (live payout submission). MCP: review_campaign_submission, submit_campaign.

GET/api/v1/clipperverse/renders

Your renders that can be attached to a Clipperverse post. MCP: list_clipperverse_renders.

GET/api/v1/clipperverse/feed

Your Clipperverse home feed (For you, personalized), or ?community=<slug>; &topic= narrows For you to one topic; &cursor=. Each For you post carries reasons and topics. MCP: get_clipperverse_feed.

POST/api/v1/clipperverse/posts

Post to a Clipperverse community: { community, content, clip_id? | video_url?, media_urls? }. MCP: post_to_clipperverse.

POST/api/v1/video-cleanup

Remove on-screen text from your clip or video: { clip_id | video_id, region, authorization_confirmed: true } → job_id. MCP: start_video_cleanup.

GET/api/v1/video-cleanup/{id}

Cleanup status, the free watermarked preview and the unlock price. MCP: get_video_cleanup.

POST/api/v1/video-cleanup/{id}

{ action: "unlock", expected_credits } | { action: "retry" }. MCP: unlock_video_cleanup, retry_video_cleanup.

GET/api/v1/video-cleanup/{id}/download

A short-lived link to the clean file once unlocked. MCP: get_video_cleanup_download.

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 Code — recommended, no key to handle
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 Code — 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, get_account_performance, list_social_accounts, publish_post, get_post, list_scheduled_posts, update_scheduled_post, cancel_scheduled_post, delete_post, generate_caption, mark_clip_posted, preview_post, get_best_posting_times, get_posting_quota, render_formats, wait_for_post_events, list_music, search_gifs, list_elements, create_webhook, list_webhooks, test_webhook, delete_webhook, plan_posts, retry_post. 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_error

Malformed request — bad JSON, or a missing/invalid url.

401authentication_error

Missing, invalid, or revoked API key.

402quota_error

Monthly usage / minute limit reached for the account.

403permission_error

The key lacks the scope this endpoint requires.

429rate_limit_error

Too many requests — back off and retry after Retry-After.

502transcription_error

The 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.