{"openapi":"3.1.0","info":{"title":"REQO API","version":"1.0.0","description":"Browser-based screen recorder and video editor. Authentication is a NextAuth session cookie obtained through an interactive sign-in; there is no client-credentials flow and no API keys. See /auth.md.","contact":{"email":"contact@reqo.me"}},"servers":[{"url":"https://reqo.me"}],"security":[{"sessionCookie":[]}],"tags":[{"name":"system"},{"name":"videos"},{"name":"projects"},{"name":"captions"},{"name":"upload"},{"name":"media"},{"name":"payments","description":"Operations an agent can pay for per call via x402."}],"paths":{"/api/health":{"get":{"tags":["system"],"summary":"Liveness check","security":[],"responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"service":{"type":"string"}}},"example":{"status":"ok","service":"reqo"}}}}},"operationId":"getApiHealth","description":"Liveness check"}},"/api/videos":{"get":{"tags":["videos"],"summary":"List videos in a workspace","parameters":[{"name":"workspaceId","in":"query","schema":{"type":"string"}},{"name":"folderId","in":"query","schema":{"type":"string"}},{"name":"origin","in":"query","schema":{"type":"string","enum":["recording","project","trim","upload"]}},{"name":"starred","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"sortBy","in":"query","schema":{"type":"string","default":"createdAt"}}],"responses":{"200":{"description":"Videos the caller can see"},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"getApiVideos","description":"List videos in a workspace"}},"/api/videos/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["videos"],"summary":"Fetch one video","responses":{"200":{"description":"The video"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}},"operationId":"getApiVideosById","description":"Fetch one video"},"patch":{"tags":["videos"],"summary":"Update video metadata","responses":{"200":{"description":"Updated"},"403":{"$ref":"#/components/responses/Forbidden"}},"operationId":"patchApiVideosById","description":"Update video metadata"},"delete":{"tags":["videos"],"summary":"Delete a video","responses":{"200":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"}},"operationId":"deleteApiVideosById","description":"Delete a video"}},"/api/videos/{id}/captions":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["captions"],"summary":"Caption status, subtitle download, or the caption track itself","description":"With no parameters, returns caption status as JSON. format=vtt or format=srt returns a subtitle file as an attachment. inline=1 returns the WebVTT track for a <track> element, served same-origin because the stored file is on a CDN that sends no CORS headers.","security":[],"parameters":[{"name":"format","in":"query","schema":{"type":"string","enum":["vtt","srt"]}},{"name":"inline","in":"query","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"Status JSON, a subtitle file, or a WebVTT track","content":{"application/json":{"schema":{"type":"object","properties":{"captionUrl":{"type":["string","null"]},"hasTranscript":{"type":"boolean"},"status":{"type":"string","enum":["ready","processing","none"]}}}},"text/vtt":{"schema":{"type":"string"}},"application/x-subrip":{"schema":{"type":"string"}}}},"304":{"description":"Caption track unchanged (ETag match)"},"403":{"description":"Private video, or a share password has not been satisfied"},"404":{"description":"No captions available for this video"},"410":{"description":"Share link has expired"}},"operationId":"getApiVideosByIdCaptions"},"post":{"tags":["captions"],"summary":"Generate or store captions for a video","responses":{"200":{"description":"Captions generated or saved"},"403":{"$ref":"#/components/responses/Forbidden"}},"operationId":"postApiVideosByIdCaptions","description":"Generate or store captions for a video"}},"/api/projects":{"get":{"tags":["projects"],"summary":"List projects","responses":{"200":{"description":"Projects the caller can see"},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"getApiProjects","description":"List projects"},"post":{"tags":["projects"],"summary":"Create a project","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"sourceUrl":{"type":"string","description":"Optional media URL to seed the first clip"},"duration":{"type":"number"},"clipTitle":{"type":"string"},"workspaceId":{"type":"string"}}},"example":{"title":"My Project"}}}},"responses":{"200":{"description":"The created project"},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"postApiProjects","description":"Create a project"}},"/api/transcribe":{"post":{"tags":["media"],"summary":"Transcribe REQO-hosted media","description":"Whisper large-v3, word timestamps on by default. sourceUrl must point at REQO media storage (*.b-cdn.net, video.bunnycdn.com or *.mediadelivery.net) over https: the route fetches the file server-side, so it only accepts hosts it owns. An arbitrary URL is rejected with 400. To transcribe your own media, use POST /api/agent/transcribe, which accepts any public https URL and is paid per call.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sourceUrl"],"properties":{"sourceUrl":{"type":"string","format":"uri","description":"https URL on a REQO media host. Other hosts are rejected with 400."},"word_timestamps":{"type":"boolean","default":true},"language":{"type":"string","description":"ISO-639-1 hint, or omit to auto-detect."}}},"example":{"sourceUrl":"https://reqo-media.b-cdn.net/uploads/clip.mp4"}}}},"responses":{"200":{"description":"Transcript","content":{"application/json":{"schema":{"type":"object","properties":{"segments":{"type":"array","items":{"type":"object","properties":{"start":{"type":"number"},"end":{"type":"number"},"text":{"type":"string"}}}},"language":{"type":"string"},"duration":{"type":"number"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"postApiTranscribe"}},"/api/videos/multipart/init":{"post":{"tags":["upload"],"summary":"Begin an upload","description":"Creates the video record and returns TUS credentials for Bunny Stream. Bytes are uploaded over the TUS protocol directly to Bunny using the returned auth, not to REQO.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceId":{"type":"string"}}}}}},"responses":{"200":{"description":"Upload created","content":{"application/json":{"schema":{"type":"object","properties":{"videoId":{"type":"string"},"bunnyVideoId":{"type":"string"},"tus":{"type":"object","description":"TUS endpoint and signed auth headers"},"title":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"postApiVideosMultipartInit"}},"/api/videos/multipart/complete":{"post":{"tags":["upload"],"summary":"Finalise an upload","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["videoId"],"properties":{"videoId":{"type":"string"},"duration":{"type":"number"},"thumbnailDataUrl":{"type":"string"},"guestToken":{"type":"string"},"skipGifPreview":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Upload finalised"},"403":{"$ref":"#/components/responses/Forbidden"}},"operationId":"postApiVideosMultipartComplete","description":"Finalise an upload"}},"/api/videos/multipart/abort":{"post":{"tags":["upload"],"summary":"Abandon an upload and clean up","responses":{"200":{"description":"Aborted"},"403":{"$ref":"#/components/responses/Forbidden"}},"operationId":"postApiVideosMultipartAbort","description":"Abandon an upload and clean up"}},"/api/agent/transcribe":{"get":{"tags":["payments"],"summary":"Price and payment details for paid transcription","description":"Discover the price without spending anything.","security":[],"responses":{"200":{"description":"Price, protocol and whether payments are enabled"}},"operationId":"getApiAgentTranscribe"},"post":{"tags":["payments","media"],"summary":"Transcribe any public media URL, paid per call","description":"Whisper large-v3 transcription of audio or video at any public https URL, with no account required. Unlike /api/transcribe this accepts media REQO does not host, which is why it is paid rather than session-authenticated.\n\nPayment is x402: call with no X-PAYMENT header to receive a 402 describing exactly what to pay, then retry with the header. The payment is verified before the transcription runs and settled only once it succeeds, so a failed call is not charged.\n\nThe URL is fetched server-side, so it must resolve to a public address: private, loopback and link-local ranges are rejected, and redirects are re-checked at every hop.","security":[],"x-payment-info":{"intent":"charge","method":"x402","amount":"0.05","currency":"USDC","decimals":6,"amount_base_units":"50000","enabled":false,"discovery":"https://reqo.me/.well-known/ucp","description":"Agent payments are not enabled on this deployment: this operation returns 503 until a receiving wallet is configured."},"parameters":[{"name":"X-PAYMENT","in":"header","required":false,"schema":{"type":"string"},"description":"Base64-encoded x402 payment payload. Omit it to receive the 402 challenge that tells you how to build it."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sourceUrl"],"properties":{"sourceUrl":{"type":"string","format":"uri","description":"Public https URL, max 200 MB."},"word_timestamps":{"type":"boolean","default":true},"language":{"type":"string","description":"ISO-639-1 hint, or omit to auto-detect."}}},"example":{"sourceUrl":"https://example.com/talk.mp4","word_timestamps":true}}}},"responses":{"200":{"description":"Transcription job accepted. X-PAYMENT-RESPONSE carries the settlement receipt."},"400":{"description":"Missing sourceUrl, or a URL that is not a public https address"},"402":{"description":"Payment required. The body lists what to pay, to whom, and on which network.","content":{"application/json":{"schema":{"type":"object","properties":{"x402Version":{"type":"integer"},"error":{"type":"string"},"accepts":{"type":"array","items":{"type":"object"}}}}}}},"502":{"description":"Source could not be fetched, or transcription failed. Not charged."},"503":{"description":"Agent payments are not configured on this deployment"}},"operationId":"postApiAgentTranscribe"}}},"components":{"securitySchemes":{"sessionCookie":{"type":"apiKey","in":"cookie","name":"next-auth.session-token","description":"httpOnly session cookie from an interactive sign-in at /api/auth/signin. REQO issues no API keys. See /auth.md."}},"responses":{"Unauthorized":{"description":"No valid session"},"Forbidden":{"description":"Session is valid but lacks access to this resource"},"NotFound":{"description":"No such resource"}}}}