{"openapi":"3.1.0","info":{"title":"Raylight API","version":"1.0.0","description":"Make finished motion design videos from a brief over HTTP.\n\nRaylight never pulls from your systems. You push a brief (one sentence of intent, optional context, media links, UI source files) and get a production: Raylight writes a free pitch (script plus shot list), you greenlight it or send comments, and the video is delivered as a share link plus an editable project. Every update is pushed back through webhooks, email and signed greenlight links.\n\nAuthentication: send an API key as `Authorization: Bearer rl_live_...`. Create keys in the app (Raylight API, Keys) or through the device flow under /v1/keys, which needs no browser session to start. Each operation names the key scope it needs in `x-raylight-scope`.\n\nRate limits: per key, 120 requests a minute on /v1/productions and 60 on /v1/webhooks. A 429 carries Retry-After.\n\nErrors: every non-2xx body is `{ error, code? }`; validation failures add `issues`.\n\nCompatibility: new fields, enum values (stages, templates, aspects, event kinds) and webhook event types are added without a version bump. Ignore unknown fields, treat unknown enum values as opaque, and acknowledge unknown webhook events with a 2xx.","contact":{"name":"Raylight","url":"https://www.raylight.app/docs"}},"servers":[{"url":"https://api.raylight.app"}],"tags":[{"name":"Productions","description":"Brief in, share link out: pitch, greenlight, video."},{"name":"Webhooks","description":"Production events pushed to your URL."},{"name":"Greenlight links","description":"Login-free Greenlight / Send comments / Decline."},{"name":"API keys","description":"Device flow for tools without a browser."},{"name":"Renders","description":"Images in, video out."}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"An rl_live_ API key. Productions and webhooks need the `productions` scope; renders need `renders`."}},"schemas":{"ApiError":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"issues":{"type":"array","items":{}}},"required":["error"]},"Production":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"stage":{"type":"string","enum":["queued","writing_pitch","pitch_ready","greenlit","making","exporting","delivered","skipped","declined","cancelled","failed"]},"source":{"type":"object","properties":{"kind":{"type":"string","enum":["app","api","mcp"]},"externalId":{"type":["string","null"],"maxLength":200},"origin":{"type":["object","null"],"properties":{"provider":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string","minLength":1,"maxLength":200},"url":{"type":["string","null"],"maxLength":2000,"format":"uri","default":null},"ref":{"type":["string","null"],"maxLength":200,"default":null},"requestedBy":{"type":["string","null"],"maxLength":120,"default":null}},"default":null,"required":["provider","label"]}},"required":["kind","externalId"]},"brief":{"type":"object","properties":{"intent":{"type":"string","minLength":1,"maxLength":2000},"context":{"type":["string","null"],"maxLength":60000,"default":null},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":80},"kind":{"type":"string","enum":["image","video"]},"url":{"type":"string","format":"uri"},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":["string","null"],"maxLength":500,"default":null}},"required":["id","kind","url","name"]},"maxItems":20,"default":[]},"code":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":500},"source":{"type":"string","maxLength":200000},"status":{"type":["string","null"],"enum":["added","modified","removed","renamed"],"default":null},"additions":{"type":"integer","minimum":0,"default":0},"deletions":{"type":"integer","minimum":0,"default":0},"patch":{"type":["string","null"],"maxLength":20000,"default":null},"digest":{"type":["string","null"],"maxLength":1500,"default":null},"score":{"type":"number","minimum":0,"maximum":1,"default":0},"sourceOmitted":{"type":"boolean"}},"required":["path","source"]},"maxItems":40,"default":[]},"format":{"type":"object","properties":{"template":{"type":"string","enum":["changelog","launch","feature","digest","custom"],"default":"changelog"},"durationMs":{"type":"integer","minimum":5000,"maximum":120000,"default":10000},"aspect":{"type":"string","enum":["16:9","4:3","3:2","21:9","1:1","9:16","3:4","2:3","4:5"],"default":"16:9"},"sound":{"type":"object","properties":{"voiceover":{"type":"boolean","default":true},"music":{"type":"boolean","default":true},"sfx":{"type":"boolean","default":true}},"default":{}}},"default":{}},"brand":{"type":"object","properties":{"name":{"type":["string","null"],"maxLength":120,"default":null},"logoUrl":{"type":["string","null"],"format":"uri","default":null},"primaryColor":{"type":["string","null"],"maxLength":32,"default":null},"backgroundColor":{"type":["string","null"],"maxLength":32,"default":null},"fontFamily":{"type":["string","null"],"maxLength":120,"default":null},"tone":{"type":["string","null"],"maxLength":300,"default":null}},"default":{}}},"required":["intent"]},"pitch":{"type":["object","null"],"properties":{"version":{"type":"integer","minimum":1},"verdict":{"type":"string","enum":["video","skip"],"default":"video"},"verdictReason":{"type":["string","null"],"maxLength":1000,"default":null},"title":{"type":"string","minLength":1,"maxLength":160},"summary":{"type":"string","minLength":1,"maxLength":2000},"shots":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"title":{"type":"string","minLength":1,"maxLength":120},"durationMs":{"type":"integer","minimum":500,"maximum":60000},"beat":{"type":["string","null"],"maxLength":200,"default":null},"visual":{"type":"string","minLength":1,"maxLength":2000},"text":{"type":["string","null"],"maxLength":500,"default":null},"voiceover":{"type":["string","null"],"maxLength":1000,"default":null},"mediaIds":{"type":"array","items":{"type":"string"},"default":[]},"codePaths":{"type":"array","items":{"type":"string"},"default":[]}},"required":["index","title","durationMs","visual"]},"minItems":1,"maxItems":24},"music":{"type":["string","null"],"maxLength":500,"default":null},"estimatedCredits":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"}},"required":["version","title","summary","shots","estimatedCredits","createdAt"]},"greenlight":{"type":["object","null"],"properties":{"mode":{"type":"string","enum":["manual","auto"]},"actor":{"type":"string","minLength":1},"actorName":{"type":["string","null"]},"at":{"type":"string","format":"date-time"},"pitchVersion":{"type":"integer","minimum":1}},"required":["mode","actor","at","pitchVersion"]},"greenlightMode":{"type":"string","enum":["manual","auto"]},"delivery":{"type":["object","null"],"properties":{"shareUrl":{"type":"string","format":"uri"},"projectId":{"type":"string","format":"uuid"},"editUrl":{"type":"string","format":"uri"},"exportId":{"type":"string","format":"uuid"},"deliveredAt":{"type":"string","format":"date-time"}},"required":["shareUrl","projectId","editUrl","exportId","deliveredAt"]},"projectId":{"type":["string","null"],"format":"uuid"},"creditsCharged":{"type":"integer","minimum":0},"error":{"type":["string","null"],"description":"Why the production failed, in words you can show a person. Never the render machine's own diagnostics."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"terminal":{"type":"boolean","description":"True once the stage is one the production never leaves (delivered, skipped, declined, cancelled, failed, or a terminal stage added later). Stop polling when it is true; it is computed by the server, so it stays right for stages your client does not know yet. Absent from payloads stored before the field existed."},"pageUrl":{"type":"string","format":"uri","description":"The production's page in the Raylight app. Absent from payloads stored before the field existed."}},"required":["id","workspaceId","stage","source","brief","pitch","greenlight","greenlightMode","delivery","projectId","creditsCharged","error","createdAt","updatedAt"]},"ProductionEvent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"productionId":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["created","stage","pitch","comment","greenlit","declined","cancelled","delivered","failed","note"]},"actor":{"type":"string"},"actorName":{"type":["string","null"],"description":"The name a person reads for `actor`: the user's name or email, the email behind a link, \"Auto-greenlight\", \"Raylight\", or null when unknown."},"payload":{"type":"object","additionalProperties":{},"description":"The fields that kind of event carries for a reader: the stage, the comment, the credits charged or refunded, the error, your own `externalId` on `created`, and on a progress `note` the `phase` the production moved to. Nothing else is included."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","productionId","kind","actor","payload","createdAt"]},"ProductionQueueStatus":{"type":"object","properties":{"phase":{"anyOf":[{"type":"string","enum":["preparing","planning","building","reviewing","polishing","exporting"]},{"type":"null"},{"type":"null"}],"default":null},"startedAt":{"type":["string","null"],"format":"date-time"},"retrying":{"type":"boolean","default":false},"lastProgress":{"type":["string","null"]}},"required":["startedAt","lastProgress"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"description":{"type":["string","null"],"maxLength":200},"events":{"type":"array","items":{"type":"string","enum":["production.pitch_ready","production.skipped","production.greenlit","production.progress","production.delivered","production.failed","production.declined","production.cancelled","ping"]}},"enabled":{"type":"boolean"},"disabledReason":{"type":["string","null"]},"consecutiveFailures":{"type":"integer","minimum":0},"lastAttemptAt":{"type":["string","null"],"format":"date-time"},"lastSuccessAt":{"type":["string","null"],"format":"date-time"},"previousSecretExpiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","workspaceId","url","description","events","enabled","disabledReason","consecutiveFailures","lastAttemptAt","lastSuccessAt","previousSecretExpiresAt","createdAt","updatedAt"]},"WebhookEndpointWithSecret":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"description":{"type":["string","null"],"maxLength":200},"events":{"type":"array","items":{"type":"string","enum":["production.pitch_ready","production.skipped","production.greenlit","production.progress","production.delivered","production.failed","production.declined","production.cancelled","ping"]}},"enabled":{"type":"boolean"},"disabledReason":{"type":["string","null"]},"consecutiveFailures":{"type":"integer","minimum":0},"lastAttemptAt":{"type":["string","null"],"format":"date-time"},"lastSuccessAt":{"type":["string","null"],"format":"date-time"},"previousSecretExpiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"secret":{"type":"string"}},"required":["id","workspaceId","url","description","events","enabled","disabledReason","consecutiveFailures","lastAttemptAt","lastSuccessAt","previousSecretExpiresAt","createdAt","updatedAt","secret"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"endpointId":{"type":"string","format":"uuid"},"productionId":{"type":["string","null"],"format":"uuid"},"event":{"type":"string","enum":["production.pitch_ready","production.skipped","production.greenlit","production.progress","production.delivered","production.failed","production.declined","production.cancelled","ping"]},"status":{"type":"string","enum":["pending","succeeded","exhausted"]},"attempts":{"type":"integer","minimum":0},"nextAttemptAt":{"type":["string","null"],"format":"date-time"},"lastResponseStatus":{"type":["integer","null"]},"lastResponseBody":{"type":["string","null"]},"lastError":{"type":["string","null"]},"lastAttemptAt":{"type":["string","null"],"format":"date-time"},"deliveredAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","endpointId","productionId","event","status","attempts","nextAttemptAt","lastResponseStatus","lastResponseBody","lastError","lastAttemptAt","deliveredAt","createdAt"]},"WebhookPayload":{"oneOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["production.pitch_ready","production.skipped","production.greenlit","production.progress","production.delivered","production.failed","production.declined","production.cancelled"]},"createdAt":{"type":"string","format":"date-time"},"workspaceId":{"type":"string","format":"uuid"},"redeliveryOf":{"type":"string","format":"uuid"},"data":{"type":"object","properties":{"production":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid"},"stage":{"type":"string","enum":["queued","writing_pitch","pitch_ready","greenlit","making","exporting","delivered","skipped","declined","cancelled","failed"]},"source":{"type":"object","properties":{"kind":{"type":"string","enum":["app","api","mcp"]},"externalId":{"type":["string","null"],"maxLength":200},"origin":{"type":["object","null"],"properties":{"provider":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string","minLength":1,"maxLength":200},"url":{"type":["string","null"],"maxLength":2000,"format":"uri","default":null},"ref":{"type":["string","null"],"maxLength":200,"default":null},"requestedBy":{"type":["string","null"],"maxLength":120,"default":null}},"default":null,"required":["provider","label"]}},"required":["kind","externalId"]},"brief":{"type":"object","properties":{"intent":{"type":"string","minLength":1,"maxLength":2000},"context":{"type":["string","null"],"maxLength":60000,"default":null},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":80},"kind":{"type":"string","enum":["image","video"]},"url":{"type":"string","format":"uri"},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":["string","null"],"maxLength":500,"default":null}},"required":["id","kind","url","name"]},"maxItems":20,"default":[]},"code":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":500},"source":{"type":"string","maxLength":200000},"status":{"type":["string","null"],"enum":["added","modified","removed","renamed"],"default":null},"additions":{"type":"integer","minimum":0,"default":0},"deletions":{"type":"integer","minimum":0,"default":0},"patch":{"type":["string","null"],"maxLength":20000,"default":null},"digest":{"type":["string","null"],"maxLength":1500,"default":null},"score":{"type":"number","minimum":0,"maximum":1,"default":0},"sourceOmitted":{"type":"boolean"}},"required":["path","source"]},"maxItems":40,"default":[]},"format":{"type":"object","properties":{"template":{"type":"string","enum":["changelog","launch","feature","digest","custom"],"default":"changelog"},"durationMs":{"type":"integer","minimum":5000,"maximum":120000,"default":10000},"aspect":{"type":"string","enum":["16:9","4:3","3:2","21:9","1:1","9:16","3:4","2:3","4:5"],"default":"16:9"},"sound":{"type":"object","properties":{"voiceover":{"type":"boolean","default":true},"music":{"type":"boolean","default":true},"sfx":{"type":"boolean","default":true}},"default":{}}},"default":{}},"brand":{"type":"object","properties":{"name":{"type":["string","null"],"maxLength":120,"default":null},"logoUrl":{"type":["string","null"],"format":"uri","default":null},"primaryColor":{"type":["string","null"],"maxLength":32,"default":null},"backgroundColor":{"type":["string","null"],"maxLength":32,"default":null},"fontFamily":{"type":["string","null"],"maxLength":120,"default":null},"tone":{"type":["string","null"],"maxLength":300,"default":null}},"default":{}}},"required":["intent"]},"pitch":{"type":["object","null"],"properties":{"version":{"type":"integer","minimum":1},"verdict":{"type":"string","enum":["video","skip"],"default":"video"},"verdictReason":{"type":["string","null"],"maxLength":1000,"default":null},"title":{"type":"string","minLength":1,"maxLength":160},"summary":{"type":"string","minLength":1,"maxLength":2000},"shots":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"title":{"type":"string","minLength":1,"maxLength":120},"durationMs":{"type":"integer","minimum":500,"maximum":60000},"beat":{"type":["string","null"],"maxLength":200,"default":null},"visual":{"type":"string","minLength":1,"maxLength":2000},"text":{"type":["string","null"],"maxLength":500,"default":null},"voiceover":{"type":["string","null"],"maxLength":1000,"default":null},"mediaIds":{"type":"array","items":{"type":"string"},"default":[]},"codePaths":{"type":"array","items":{"type":"string"},"default":[]}},"required":["index","title","durationMs","visual"]},"minItems":1,"maxItems":24},"music":{"type":["string","null"],"maxLength":500,"default":null},"estimatedCredits":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"}},"required":["version","title","summary","shots","estimatedCredits","createdAt"]},"greenlight":{"type":["object","null"],"properties":{"mode":{"type":"string","enum":["manual","auto"]},"actor":{"type":"string","minLength":1},"actorName":{"type":["string","null"]},"at":{"type":"string","format":"date-time"},"pitchVersion":{"type":"integer","minimum":1}},"required":["mode","actor","at","pitchVersion"]},"greenlightMode":{"type":"string","enum":["manual","auto"]},"delivery":{"type":["object","null"],"properties":{"shareUrl":{"type":"string","format":"uri"},"projectId":{"type":"string","format":"uuid"},"editUrl":{"type":"string","format":"uri"},"exportId":{"type":"string","format":"uuid"},"deliveredAt":{"type":"string","format":"date-time"}},"required":["shareUrl","projectId","editUrl","exportId","deliveredAt"]},"projectId":{"type":["string","null"],"format":"uuid"},"creditsCharged":{"type":"integer","minimum":0},"error":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"terminal":{"type":"boolean"},"pageUrl":{"type":"string","format":"uri"}},"required":["id","workspaceId","stage","source","brief","pitch","greenlight","greenlightMode","delivery","projectId","creditsCharged","error","createdAt","updatedAt"]},"pitchMarkdown":{"type":["string","null"]},"status":{"type":["string","null"]},"links":{"type":"object","properties":{"page":{"type":"string","format":"uri"},"greenlight":{"type":["string","null"],"format":"uri"},"comment":{"type":["string","null"],"format":"uri"},"decline":{"type":["string","null"],"format":"uri"},"share":{"type":["string","null"],"format":"uri"},"edit":{"type":["string","null"],"format":"uri"}},"required":["page","greenlight","comment","decline","share","edit"]}},"required":["production","pitchMarkdown","status","links"]}},"required":["id","type","createdAt","workspaceId","data"]},{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["ping"]},"createdAt":{"type":"string","format":"date-time"},"workspaceId":{"type":"string","format":"uuid"},"redeliveryOf":{"type":"string","format":"uuid"},"data":{"type":"object","properties":{"endpointId":{"type":"string","format":"uuid"},"message":{"type":"string"}},"required":["endpointId","message"]}},"required":["id","type","createdAt","workspaceId","data"]}]},"ProductionLink":{"type":"object","properties":{"productionId":{"type":"string","format":"uuid"},"workspaceName":{"type":"string"},"stage":{"type":"string","enum":["queued","writing_pitch","pitch_ready","greenlit","making","exporting","delivered","skipped","declined","cancelled","failed"]},"state":{"type":"string","enum":["open","stale","expired"]},"pitchVersion":{"type":"integer","minimum":1},"currentPitchVersion":{"type":"integer","minimum":0},"intent":{"type":"string"},"origin":{"type":["object","null"],"properties":{"provider":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string","minLength":1,"maxLength":200},"url":{"type":["string","null"],"maxLength":2000,"format":"uri","default":null},"ref":{"type":["string","null"],"maxLength":200,"default":null},"requestedBy":{"type":["string","null"],"maxLength":120,"default":null}},"required":["provider","label"]},"format":{"type":"object","properties":{"template":{"type":"string","enum":["changelog","launch","feature","digest","custom"],"default":"changelog"},"durationMs":{"type":"integer","minimum":5000,"maximum":120000,"default":10000},"aspect":{"type":"string","enum":["16:9","4:3","3:2","21:9","1:1","9:16","3:4","2:3","4:5"],"default":"16:9"},"sound":{"type":"object","properties":{"voiceover":{"type":"boolean","default":true},"music":{"type":"boolean","default":true},"sfx":{"type":"boolean","default":true}},"default":{}}}},"pitch":{"type":["object","null"],"properties":{"version":{"type":"integer","minimum":1},"verdict":{"type":"string","enum":["video","skip"],"default":"video"},"verdictReason":{"type":["string","null"],"maxLength":1000,"default":null},"title":{"type":"string","minLength":1,"maxLength":160},"summary":{"type":"string","minLength":1,"maxLength":2000},"shots":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"title":{"type":"string","minLength":1,"maxLength":120},"durationMs":{"type":"integer","minimum":500,"maximum":60000},"beat":{"type":["string","null"],"maxLength":200,"default":null},"visual":{"type":"string","minLength":1,"maxLength":2000},"text":{"type":["string","null"],"maxLength":500,"default":null},"voiceover":{"type":["string","null"],"maxLength":1000,"default":null},"mediaIds":{"type":"array","items":{"type":"string"},"default":[]},"codePaths":{"type":"array","items":{"type":"string"},"default":[]}},"required":["index","title","durationMs","visual"]},"minItems":1,"maxItems":24},"music":{"type":["string","null"],"maxLength":500,"default":null},"estimatedCredits":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"}},"required":["version","title","summary","shots","estimatedCredits","createdAt"]},"pitchMarkdown":{"type":["string","null"]},"delivery":{"type":["object","null"],"properties":{"shareUrl":{"type":"string","format":"uri"},"projectId":{"type":"string","format":"uuid"},"editUrl":{"type":"string","format":"uri"},"exportId":{"type":"string","format":"uuid"},"deliveredAt":{"type":"string","format":"date-time"}},"required":["shareUrl","projectId","editUrl","exportId","deliveredAt"]},"pageUrl":{"type":"string","format":"uri"},"revisionsLeft":{"type":"integer","minimum":0},"expiresAt":{"type":"string","format":"date-time"},"channel":{"type":"string","enum":["email","webhook"]}},"required":["productionId","workspaceName","stage","state","pitchVersion","currentPitchVersion","intent","origin","format","pitch","pitchMarkdown","delivery","pageUrl","revisionsLeft","expiresAt"]},"Render":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","rendering","done","failed"]},"progress":{"type":"number","minimum":0,"maximum":1},"projectId":{"type":["string","null"],"format":"uuid"},"resolution":{"type":"string","enum":["480p","720p","1080p","4K"]},"error":{"type":["string","null"]},"videoUrl":{"type":"string","format":"uri"}},"required":["id","status","progress","projectId","resolution","error"]}},"parameters":{}},"paths":{"/v1/productions":{"post":{"operationId":"createProduction","tags":["Productions"],"summary":"Create a production","description":"Push a brief. Raylight writes a free pitch (script plus shot list) in the background; poll the production or receive `production.pitch_ready` on a webhook. `externalId` makes the call idempotent per key owner and workspace: repeating it with a key from the same owner, in the same workspace, answers 200 with the production the first call made and `Idempotent-Replayed: true`, and nothing new is created. `origin` is display only (the Productions pages and emails); Raylight never calls the provider.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceId":{"type":"string","format":"uuid"},"brief":{"type":"object","properties":{"intent":{"type":"string","minLength":1,"maxLength":2000},"context":{"type":["string","null"],"maxLength":60000,"default":null},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":80},"kind":{"type":"string","enum":["image","video"]},"url":{"type":"string","format":"uri"},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":["string","null"],"maxLength":500,"default":null}},"required":["id","kind","url","name"]},"maxItems":20,"default":[]},"code":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":500},"source":{"type":"string","maxLength":200000},"status":{"type":["string","null"],"enum":["added","modified","removed","renamed"],"default":null},"additions":{"type":"integer","minimum":0,"default":0},"deletions":{"type":"integer","minimum":0,"default":0},"patch":{"type":["string","null"],"maxLength":20000,"default":null},"digest":{"type":["string","null"],"maxLength":1500,"default":null},"score":{"type":"number","minimum":0,"maximum":1,"default":0},"sourceOmitted":{"type":"boolean"}},"required":["path","source"]},"maxItems":40,"default":[]},"format":{"type":"object","properties":{"template":{"type":"string","enum":["changelog","launch","feature","digest","custom"],"default":"changelog"},"durationMs":{"type":"integer","minimum":5000,"maximum":15000,"default":10000},"aspect":{"type":"string","enum":["16:9","4:3","3:2","21:9","1:1","9:16","3:4","2:3","4:5"],"default":"16:9"},"sound":{"type":"object","properties":{"voiceover":{"type":"boolean","default":true},"music":{"type":"boolean","default":true},"sfx":{"type":"boolean","default":true}},"default":{}}},"default":{}},"brand":{"type":"object","properties":{"name":{"type":["string","null"],"maxLength":120,"default":null},"logoUrl":{"type":["string","null"],"format":"uri","default":null},"primaryColor":{"type":["string","null"],"maxLength":32,"default":null},"backgroundColor":{"type":["string","null"],"maxLength":32,"default":null},"fontFamily":{"type":["string","null"],"maxLength":120,"default":null},"tone":{"type":["string","null"],"maxLength":300,"default":null}},"default":{}}},"required":["intent"]},"greenlightMode":{"type":"string","enum":["manual","auto"],"default":"manual"},"externalId":{"type":"string","maxLength":200},"origin":{"type":"object","properties":{"provider":{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z0-9][a-z0-9-]*$"},"label":{"type":"string","minLength":1,"maxLength":200},"url":{"type":["string","null"],"maxLength":2000,"format":"uri","default":null},"ref":{"type":["string","null"],"maxLength":200,"default":null},"requestedBy":{"type":["string","null"],"maxLength":120,"default":null}},"required":["provider","label"]}},"required":["brief"]}}}},"responses":{"200":{"description":"A repeat of an earlier create with the same `externalId`: the existing production.","headers":{"Idempotent-Replayed":{"description":"`true` when the production came from an earlier create with the same `externalId`.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"}},"required":["production"]}}}},"201":{"description":"The new production, queued for a pitch.","content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"}},"required":["production"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"The workspace owner's credits do not cover a video of the length asked for (code `credits`). A pitch is free, but it is only written when the video it asks for could be paid for. Nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Raylight can't write pitches right now (code `disabled`). Nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listProductions","tags":["Productions"],"summary":"List productions","description":"Newest first. Pass `externalId` to find the production an earlier create with that id made (the same match a repeated create replays), for example to check whether a pull request already has one before sending its brief again. Every code file in each brief has `source` and `patch` emptied and carries `sourceOmitted: true`; read one production for its full files.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"workspaceId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"stage","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"externalId","in":"query"}],"responses":{"200":{"description":"Productions, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"productions":{"type":"array","items":{"$ref":"#/components/schemas/Production"}}},"required":["productions"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/productions/usage":{"get":{"operationId":"getProductionUsage","tags":["Productions"],"summary":"This month's usage and pitch cap","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"workspaceId","in":"query"}],"responses":{"200":{"description":"Counts and caps for the calendar month.","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"},"productionsThisMonth":{"type":"integer","minimum":0},"pitchesThisMonth":{"type":"integer","minimum":0},"pitchesCap":{"type":"integer","minimum":0},"creditsCharged":{"type":"integer","minimum":0}},"required":["plan","productionsThisMonth","pitchesThisMonth","pitchesCap","creditsCharged"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/productions/{id}":{"get":{"operationId":"getProduction","tags":["Productions"],"summary":"Read a production","description":"The production with its full brief, its timeline (events and comments, each with `actorName`), and its place in the render queue.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The production id."},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The production with its timeline.","content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"},"events":{"type":"array","items":{"$ref":"#/components/schemas/ProductionEvent"}},"queue":{"type":["object","null"],"properties":{"phase":{"anyOf":[{"type":"string","enum":["preparing","planning","building","reviewing","polishing","exporting"]},{"type":"null"},{"type":"null"}],"default":null},"startedAt":{"type":["string","null"],"format":"date-time"},"retrying":{"type":"boolean","default":false},"lastProgress":{"type":["string","null"]}},"required":["startedAt","lastProgress"]},"pitchMarkdown":{"type":["string","null"]}},"required":["production","events","queue","pitchMarkdown"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/productions/{id}/greenlight":{"post":{"operationId":"greenlightProduction","tags":["Productions"],"summary":"Greenlight the pitch","description":"Charges the production credits once, creates the project and queues the video for a render machine. Pass `pitchVersion` to refuse the greenlight if the pitch changed since you read it.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The production id."},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pitchVersion":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"The greenlit production.","content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"}},"required":["production"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Not enough credits (code `credits`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The pitch is not ready, or its version is out of date (code `stage`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/productions/{id}/comments":{"post":{"operationId":"commentOnProduction","tags":["Productions"],"summary":"Send comments","description":"Send comments on the pitch and get the next pitch version, free. A production gets up to 6 pitch versions, so 5 rounds of comments; past that the answer is 429 with code `cap`. Pass `pitchVersion` to refuse the comments if the pitch changed meanwhile. If the next version cannot be written (the monthly pitch cap, or pitches being unavailable), the current pitch stands and a `note` event carries `revisionRefused` and `message`.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The production id."},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"comment":{"type":"string","minLength":1,"maxLength":4000},"pitchVersion":{"type":"integer","minimum":1}},"required":["comment"]}}}},"responses":{"200":{"description":"The production, writing its next pitch.","content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"}},"required":["production"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"The workspace owner's credits do not cover the video (code `credits`). The current pitch stands.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The pitch is not ready, or its version is out of date (code `stage`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Raylight can't write pitches right now (code `disabled`). The current pitch stands.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/productions/{id}/decline":{"post":{"operationId":"declineProduction","tags":["Productions"],"summary":"Decline the pitch","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The production id."},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":1000}}}}}},"responses":{"200":{"description":"The declined production.","content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"}},"required":["production"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The production is already greenlit (code `stage`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/productions/{id}/cancel":{"post":{"operationId":"cancelProduction","tags":["Productions"],"summary":"Cancel a production","description":"Free before the greenlight. Refunded if greenlit but still waiting for a render machine. A production being made cannot be cancelled.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The production id."},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The cancelled production.","content":{"application/json":{"schema":{"type":"object","properties":{"production":{"$ref":"#/components/schemas/Production"}},"required":["production"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The production is being made (code `stage`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/webhooks":{"get":{"operationId":"listWebhookEndpoints","tags":["Webhooks"],"summary":"List webhook endpoints","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"workspaceId","in":"query"}],"responses":{"200":{"description":"The workspace's endpoints.","content":{"application/json":{"schema":{"type":"object","properties":{"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}},"required":["endpoints"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"createWebhookEndpoint","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Registers an https URL. The signing secret is returned once and cannot be read again. Every delivery is signed with `Raylight-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\">` and carries `Raylight-Event-Id` (stable across retries) and `Raylight-Event-Type`. Failed deliveries retry at 30s, 2m, 10m, 1h and 6h; after 20 exhausted deliveries in a row the endpoint is switched off and the workspace owner emailed.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceId":{"type":"string","format":"uuid"},"url":{"type":"string","maxLength":2000,"format":"uri"},"description":{"type":"string","maxLength":200},"events":{"type":"array","items":{"type":"string","enum":["production.pitch_ready","production.skipped","production.greenlit","production.progress","production.delivered","production.failed","production.declined","production.cancelled"]},"minItems":1,"maxItems":8}},"required":["url"]}}}},"responses":{"201":{"description":"The endpoint with its secret.","content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}},"required":["endpoint"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The workspace has reached its endpoint limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/webhooks/{id}":{"get":{"operationId":"getWebhookEndpoint","tags":["Webhooks"],"summary":"Read a webhook endpoint","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The endpoint.","content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"}},"required":["endpoint"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"updateWebhookEndpoint","tags":["Webhooks"],"summary":"Update a webhook endpoint","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"description":{"type":["string","null"],"maxLength":200},"events":{"type":"array","items":{"type":"string","enum":["production.pitch_ready","production.skipped","production.greenlit","production.progress","production.delivered","production.failed","production.declined","production.cancelled"]},"minItems":1,"maxItems":8},"enabled":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated endpoint.","content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"}},"required":["endpoint"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteWebhookEndpoint","tags":["Webhooks"],"summary":"Delete a webhook endpoint","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted."},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/webhooks/{id}/roll-secret":{"post":{"operationId":"rollWebhookSecret","tags":["Webhooks"],"summary":"Roll the signing secret","description":"Mints a new secret. The old one keeps verifying for 24 hours, during which deliveries carry two `v1` signatures and `previousSecretExpiresAt` says when it stops. If Raylight could no longer read the old secret (the delivery log says so), it is dropped at once instead: deliveries carry only the new signature and `previousSecretExpiresAt` is null.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The endpoint with its new secret.","content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}},"required":["endpoint"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The secret was rolled somewhere else at the same moment (code `conflict`). Nothing changed from this call; try again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/webhooks/{id}/test":{"post":{"operationId":"testWebhookEndpoint","tags":["Webhooks"],"summary":"Send a test event","description":"Queues a signed `ping` to test your receiver and signature check.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"}],"responses":{"202":{"description":"The queued delivery.","content":{"application/json":{"schema":{"type":"object","properties":{"delivery":{"$ref":"#/components/schemas/WebhookDelivery"}},"required":["delivery"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The endpoint is switched off (code `endpoint_disabled`), or points at localhost on a server that cannot reach it (code `wrong_server`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","tags":["Webhooks"],"summary":"List deliveries","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Deliveries, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}},"required":["deliveries"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver":{"post":{"operationId":"redeliverWebhookDelivery","tags":["Webhooks"],"summary":"Redeliver an event","description":"Queues a copy of a delivery's event with a new `id` and `redeliveryOf` set to the original event's id.","security":[{"ApiKey":[]}],"x-raylight-scope":"productions","parameters":[{"schema":{"type":"string","format":"uuid","description":"The endpoint id."},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","description":"The delivery to copy."},"required":true,"name":"deliveryId","in":"path"}],"responses":{"202":{"description":"The new delivery.","content":{"application/json":{"schema":{"type":"object","properties":{"delivery":{"$ref":"#/components/schemas/WebhookDelivery"}},"required":["delivery"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the `productions` scope (code `api_key_missing_scope`), or its owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"No such endpoint or workspace for this key (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The endpoint is switched off (code `endpoint_disabled`), or points at localhost on a server that cannot reach it (code `wrong_server`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Webhooks are not switched on for this server (code `disabled`). Every webhook route answers this while they are off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/production-links/{token}":{"get":{"operationId":"readProductionLink","tags":["Greenlight links"],"summary":"Read a signed greenlight link","description":"Public. What the link points at and whether it can still act (`state`: open, stale, expired). An expired link still reads with 200 and `state: expired`. Links arrive in emails and in webhook payloads under `data.links`.","parameters":[{"schema":{"type":"string","description":"The signed token from the link."},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"The pitch behind the link.","content":{"application/json":{"schema":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/ProductionLink"}},"required":["link"]}}}},"403":{"description":"The link was sent to someone who can no longer greenlight in this workspace, or to a webhook endpoint that was deleted (code `revoked`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not a valid link (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited (30 a minute per address), or the workspace reached a monthly cap (code `cap`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Greenlight links are not switched on for this server (code `disabled`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/production-links/{token}/greenlight":{"post":{"operationId":"greenlightProductionLink","tags":["Greenlight links"],"summary":"Greenlight through a link","parameters":[{"schema":{"type":"string","description":"The signed token from the link."},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Greenlit.","content":{"application/json":{"schema":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/ProductionLink"}},"required":["link"]}}}},"402":{"description":"Not enough credits (code `credits`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The link was sent to someone who can no longer greenlight in this workspace, or to a webhook endpoint that was deleted (code `revoked`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not a valid link (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The pitch moved on since the link was minted, or was already answered (code `stale`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"The link expired (code `expired`). Reading it still works and says `state: expired`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited (30 a minute per address), or the workspace reached a monthly cap (code `cap`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Greenlight links are not switched on for this server (code `disabled`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/production-links/{token}/comments":{"post":{"operationId":"commentOnProductionLink","tags":["Greenlight links"],"summary":"Send comments through a link","parameters":[{"schema":{"type":"string","description":"The signed token from the link."},"required":true,"name":"token","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"comment":{"type":"string","minLength":1,"maxLength":4000}},"required":["comment"]}}}},"responses":{"200":{"description":"Writing the next pitch.","content":{"application/json":{"schema":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/ProductionLink"}},"required":["link"]}}}},"400":{"description":"The comment is missing or too long.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"The workspace owner's credits do not cover the video (code `credits`). The current pitch stands.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The link was sent to someone who can no longer greenlight in this workspace, or to a webhook endpoint that was deleted (code `revoked`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not a valid link (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The pitch moved on since the link was minted, or was already answered (code `stale`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"The link expired (code `expired`). Reading it still works and says `state: expired`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited (30 a minute per address), or the workspace reached a monthly cap (code `cap`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Greenlight links are not switched on for this server (code `disabled`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/production-links/{token}/decline":{"post":{"operationId":"declineProductionLink","tags":["Greenlight links"],"summary":"Decline through a link","parameters":[{"schema":{"type":"string","description":"The signed token from the link."},"required":true,"name":"token","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":1000}}}}}},"responses":{"200":{"description":"Declined.","content":{"application/json":{"schema":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/ProductionLink"}},"required":["link"]}}}},"400":{"description":"The reason is too long.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The link was sent to someone who can no longer greenlight in this workspace, or to a webhook endpoint that was deleted (code `revoked`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not a valid link (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"The pitch moved on since the link was minted, or was already answered (code `stale`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"The link expired (code `expired`). Reading it still works and says `state: expired`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited (30 a minute per address), or the workspace reached a monthly cap (code `cap`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Greenlight links are not switched on for this server (code `disabled`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/keys/request":{"post":{"operationId":"requestApiKey","tags":["API keys"],"summary":"Start a device-code key request","description":"Public. Returns a device code to poll with and an approval URL to show the user. Pick a `name` that says who is asking.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"default":"API key"}}}}}},"responses":{"201":{"description":"The pairing.","content":{"application/json":{"schema":{"type":"object","properties":{"deviceCode":{"type":"string"},"userCode":{"type":"string"},"approvalUrl":{"type":"string","format":"uri"},"expiresInSeconds":{"type":"integer","exclusiveMinimum":0},"pollIntervalSeconds":{"type":"integer","exclusiveMinimum":0}},"required":["deviceCode","userCode","approvalUrl","expiresInSeconds","pollIntervalSeconds"]}}}},"400":{"description":"Invalid body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited: 60 requests a minute per address. Carries Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/keys/poll":{"post":{"operationId":"pollApiKey","tags":["API keys"],"summary":"Poll a key request","description":"Public. `pending` until the user approves, then `approved` with the key, once. `denied` and `expired` are terminal. If the claim response was lost, poll again with `revokeClaimed: true` to revoke the key you never received.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceCode":{"type":"string","minLength":1},"revokeClaimed":{"type":"boolean"}},"required":["deviceCode"]}}}},"responses":{"200":{"description":"The request's state.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","approved","claimed","denied","expired"]},"apiKey":{"type":"string"}},"required":["status"]}}}},"400":{"description":"Invalid body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Unknown device code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited: 60 requests a minute per address. Carries Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/keys/current":{"delete":{"operationId":"revokeCurrentApiKey","tags":["API keys"],"summary":"Revoke the key making the call","description":"Signs a tool out: the API key in the `Authorization` header stops working at once. Needs no scope. Usage history for the key is kept.","security":[{"ApiKey":[]}],"responses":{"204":{"description":"Revoked."},"400":{"description":"The call was not made with an API key (code `not_api_key`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"The key is already revoked (code `not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited: 30 requests a minute per key. Carries Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/renders":{"post":{"operationId":"createRender","tags":["Renders"],"summary":"Render images into a video","description":"Multipart: 1 to 10 image files as repeated `images` fields plus optional form fields. With `wait=true` (default) the request holds until the video is ready (about 1 to 3 minutes) and answers 200; past the wait budget it answers 202 while the render continues. Needs the `renders` scope.","security":[{"ApiKey":[]}],"x-raylight-scope":"renders","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"resolution":{"type":"string","enum":["480p","720p","1080p","4K"],"default":"1080p"},"background":{"type":"string","enum":["black","white"],"default":"black"},"appName":{"type":"string","maxLength":24},"accent":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"wait":{"type":"string","enum":["true","false"],"default":"true"},"images":{"type":"array","items":{"type":"string","format":"binary"},"minItems":1,"maxItems":10}},"required":["images"]}}}},"responses":{"200":{"description":"The finished render with a signed video URL.","content":{"application/json":{"schema":{"type":"object","properties":{"render":{"$ref":"#/components/schemas/Render"}},"required":["render"]}}}},"202":{"description":"Still rendering; poll it.","content":{"application/json":{"schema":{"type":"object","properties":{"render":{"$ref":"#/components/schemas/Render"}},"required":["render"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/renders/{id}":{"get":{"operationId":"getRender","tags":["Renders"],"summary":"Read a render","security":[{"ApiKey":[]}],"x-raylight-scope":"renders","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The render, with a fresh video URL once done.","content":{"application/json":{"schema":{"type":"object","properties":{"render":{"$ref":"#/components/schemas/Render"}},"required":["render"]}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing, invalid or revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"The key lacks the scope, or the key's owner has view-only access to the workspace (code `forbidden`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limited, or a monthly cap reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"webhooks":{"productionEvent":{"post":{"operationId":"receiveRaylightEvent","tags":["Webhooks"],"summary":"A production event, delivered to your endpoint","description":"Raylight POSTs one event per delivery to each subscribed endpoint. Verify `Raylight-Signature` against the raw body before parsing (`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\">`, two `v1` entries while a rolled secret is live, 5 minute tolerance). Dedupe on `Raylight-Event-Id`. `data.production` is the production as the API returns it, except that every code file in the brief has `source` and `patch` emptied and carries `sourceOmitted: true`; read the production over the API for the full files. A redelivered event has its own `id` and `redeliveryOf` naming the original. New event types and enum values are added without a version bump; acknowledge types you do not know with a 2xx.","parameters":[{"schema":{"type":"string","description":"t=<unix seconds>,v1=<hex HMAC-SHA256>[,v1=...]"},"required":true,"name":"raylight-signature","in":"header"},{"schema":{"type":"string","description":"Stable across retries; dedupe on it."},"required":true,"name":"raylight-event-id","in":"header"},{"schema":{"type":"string","description":"The payload's `type`."},"required":true,"name":"raylight-event-type","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPayload"}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery. Anything else is retried at 30s, 2m, 10m, 1h and 6h."}}}}}}