{"openapi":"3.1.0","info":{"title":"ClipFox API","version":"1.0.0","description":"ClipFox turns long videos into short vertical clips. Authenticate with an API key from Settings → Connect your AI (Creator plan and above): Authorization: Bearer cfx_live_…. Limits: 60 requests/min and 2000/day per key; actions count toward the same plan quotas as the app (exports, transcriptions, AI calls). Importing requires rights_confirmed=true after the user confirms they own or have rights to the video. Transcription and MP4 rendering run in the user's browser: those endpoints return a link for the user to open. Errors: {\"error\":{\"code\",\"message\"}}. MCP server: https://clipfoxhq.com/mcp"},"servers":[{"url":"https://clipfoxhq.com/api/v1"}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"cfx_live_… API key"}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"action_url":{"type":"string"}}}}}}}}}},"paths":{"/me":{"get":{"operationId":"whoami","summary":"Who am I","description":"Returns the connected ClipFox account's plan, monthly limits and current usage (exports, transcriptions, AI calls today). Call this first to check what the user can still do.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/projects":{"post":{"operationId":"import_video_from_link","summary":"Import video from link","description":"Creates a project by importing a video file from a Google Drive, Dropbox, OneDrive/SharePoint share link or a direct https link to an .mp4/.mov/.webm/.m4v file (max 2 GB). Pages on YouTube, TikTok, Twitch, Instagram, Facebook, X, Kick or Vimeo are rejected — the user must download their own video and share it via Drive/Dropbox. BEFORE calling, ask the user to confirm they own the video or have the rights/permission to use it, and which source_type applies; only then set rights_confirmed=true. The confirmation is recorded as a legal rights attestation. Up to 10 imports per hour. Large files can take minutes.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source_url":{"description":"Share link or direct https video file URL.","type":"string","maxLength":2000,"format":"uri"},"title":{"description":"Project title (defaults to the file name).","type":"string","minLength":1,"maxLength":200},"source_type":{"description":"own = the user filmed/owns it; licensed = creator gave permission; campaign = official clipping campaign; creative_commons = CC / public domain.","type":"string","enum":["own","licensed","campaign","creative_commons"]},"cc_license":{"description":"Required when source_type is creative_commons.","type":"string","enum":["cc_by","cc_by_sa","cc_by_nd","cc_by_nc","cc0"]},"original_creator":{"type":"string","maxLength":120},"permission_link":{"description":"Link proving permission/license (defaults to source_url for Drive/Dropbox).","type":"string","maxLength":2000,"format":"uri"},"rights_confirmed":{"description":"Must be true: the user confirmed they own or have the rights to this video.","type":"boolean","const":true}},"required":["source_url","source_type","rights_confirmed"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}},"get":{"operationId":"list_projects","summary":"List projects","description":"Lists the user's projects (newest first) with status: importing, ready (not transcribed), transcribing, transcribed.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/projects/{id}":{"get":{"operationId":"get_project","summary":"Get project","description":"Gets one project's status, duration and whether a transcript is available.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"delete_project","summary":"Delete project","description":"Permanently deletes a project with its clips, exports, transcript and stored video files. Cannot be undone — confirm with the user first. Legal rights records are kept.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/projects/{id}/transcribe":{"post":{"operationId":"transcribe_project","summary":"Transcribe project","description":"Transcription needs the user's browser: audio is extracted and silence-checked on-device (ffmpeg.wasm), so it cannot run fully server-side. This returns 409 with action_url — give that link to the user; opening it (signed in) transcribes and finds clips automatically. If the project is already transcribed it returns the transcript summary instead. Then call get_project until status is 'transcribed'.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/projects/{id}/find-clips":{"post":{"operationId":"find_clips","summary":"Find clips","description":"Runs the AI clip finder on a transcribed project and saves 5–10 short-form clip candidates (15–60 s) with a virality score, hook title and reasons. Uses one AI call from the daily limit; once that is used up it spends 1 credit. Returns 402 with buy_url when no quota or credits are left.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":10},"max_seconds":{"type":"number","minimum":5,"maximum":180}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/projects/{id}/clips":{"get":{"operationId":"list_clips","summary":"List clips","description":"Lists a project's clips, best score first.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/clips/{id}":{"patch":{"operationId":"update_clip","summary":"Update clip","description":"Edits a clip: trim (start/end seconds, max 180 s), title, on-screen hook text, caption style and look preset. Other editor settings are kept.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"start":{"type":"number","minimum":0},"end":{"type":"number","minimum":0},"title":{"type":"string","maxLength":120},"hook_text":{"type":"string","maxLength":120},"caption_style":{"type":"string","enum":["bold_pop","minimal","karaoke","boxed","emoji"]},"look_preset":{"type":"string","enum":["none","vivid","cinematic","warm","cool","bw","retro","neon","clean"]},"captions_enabled":{"type":"boolean"},"progress_bar":{"type":"boolean"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/clips/{id}/publish-kit":{"post":{"operationId":"generate_publish_kit","summary":"Generate publish kit","description":"Writes per-platform posting copy (title, description, hashtags, best times; X thread + quote) for a clip, plus the required source credit line for licensed/campaign/Creative Commons content (always include it in the post). Uses one AI call. If the clip has no speech, returns honest generic copy.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"platforms":{"maxItems":7,"type":"array","items":{"type":"string","enum":["tiktok","instagram","youtube","x","facebook","snapchat","linkedin"]}},"about":{"type":"string","maxLength":200}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/clips/{id}/render":{"post":{"operationId":"get_render_link","summary":"Get render link","description":"Rendering the MP4 happens in the user's browser (ffmpeg.wasm), not on the server. Returns render_url — give it to the user; opening it signed in starts the export automatically (counts as one export from the plan). Afterwards list exports with get_export.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/exports/{id}":{"get":{"operationId":"get_export","summary":"Get export","description":"Gets an export's status and, when done, a signed download URL valid for 1 hour. Pass a clip id instead to get that clip's latest export.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/campaigns":{"get":{"operationId":"list_campaigns","summary":"List campaigns","description":"Lists live Creator Campaigns: creators pay clippers per 1,000 verified views. Shows CPM rate, allowed platforms and remaining budget.","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/campaigns/{id}/join":{"post":{"operationId":"join_campaign","summary":"Join campaign","description":"Joins a live campaign as a clipper. Requires accept_clipper_terms=true — first show the user the clipper terms (https://clipfoxhq.com/terms, section Creator Campaigns) and get their agreement; acceptance is recorded.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accept_clipper_terms":{"type":"boolean","const":true}},"required":["accept_clipper_terms"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/campaigns/{id}/submissions":{"post":{"operationId":"submit_campaign_post","summary":"Submit campaign post","description":"Submits a posted clip URL to a joined live campaign for review. The URL must be a real post on an allowed platform and can only be submitted once. Views are verified by ClipFox before payout.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"post_url":{"type":"string","maxLength":500,"format":"uri"},"platform":{"type":"string","enum":["tiktok","instagram","youtube","x","facebook","snapchat","linkedin"]},"reported_views":{"type":"integer","minimum":0,"maximum":10000000000}},"required":["post_url","platform"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/posts":{"post":{"operationId":"log_post","summary":"Log post","description":"Records that a clip was posted (for analytics, streaks and the leaderboard). Optionally link it to an export and report current views; views can be updated later in the app.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"export_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"},"platform":{"type":"string","enum":["tiktok","instagram","youtube","x","facebook","snapchat","linkedin"]},"post_url":{"type":"string","maxLength":500,"format":"uri"},"views":{"type":"integer","minimum":0,"maximum":10000000000}},"required":["platform","post_url"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}},"/stats":{"get":{"operationId":"get_stats","summary":"Get stats","description":"Summary analytics for the user's logged posts (views, posts per platform, best platform) and leaderboard rank (all-time by views).","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"4XX":{"$ref":"#/components/responses/Error"},"5XX":{"$ref":"#/components/responses/Error"}}}}}}