RaylightAPI

Productions

Create a production

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.

POST/v1/productions

API key with the productions scope.

Request body

application/json

FieldTypeDescription
workspaceIduuid
briefrequiredobject
brief.intentrequiredstring
brief.contextstring | nullDefault null
brief.mediaobject[]
brief.media[].idrequiredstring
brief.media[].kindrequiredenumOne of: image, video
brief.media[].urlrequiredurl
brief.media[].namerequiredstring
brief.media[].descriptionstring | nullDefault null
brief.codeobject[]
brief.code[].pathrequiredstring
brief.code[].sourcerequiredstring
brief.code[].statusenum | nullOne of: added, modified, removed, renamedDefault null
brief.code[].additionsintegerDefault 0
brief.code[].deletionsintegerDefault 0
brief.code[].patchstring | nullDefault null
brief.code[].digeststring | nullDefault null
brief.code[].scorenumberDefault 0
brief.code[].sourceOmittedboolean
brief.formatobject
brief.format.templateenumOne of: changelog, launch, feature, digest, customDefault changelog
brief.format.durationMsintegerDefault 10000
brief.format.aspectenumOne of: 16:9, 4:3, 3:2, 21:9, 1:1, 9:16, 3:4, 2:3, 4:5Default 16:9
brief.format.soundobject
brief.format.sound.voiceoverbooleanDefault true
brief.format.sound.musicbooleanDefault true
brief.format.sound.sfxbooleanDefault true
brief.brandobject
brief.brand.namestring | nullDefault null
brief.brand.logoUrlurl | nullDefault null
brief.brand.primaryColorstring | nullDefault null
brief.brand.backgroundColorstring | nullDefault null
brief.brand.fontFamilystring | nullDefault null
brief.brand.tonestring | nullDefault null
greenlightModeenumOne of: manual, autoDefault manual
externalIdstring
originobject
origin.providerrequiredstring
origin.labelrequiredstring
origin.urlurl | nullDefault null
origin.refstring | nullDefault null
origin.requestedBystring | nullDefault null

Responses

200A repeat of an earlier create with the same externalId: the existing production.
201The new production, queued for a pitch.
400Invalid request.
401Missing, invalid or revoked key.
402The 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.
403The key lacks the scope, or the key's owner has view-only access to the workspace (code forbidden).
404Not found.
429Rate limited, or a monthly cap reached.
503Raylight can't write pitches right now (code disabled). Nothing was created.

200 response body

FieldTypeDescription
productionrequiredobject
production.idrequireduuid
production.workspaceIdrequireduuid
production.stagerequiredenumOne of: queued, writing_pitch, pitch_ready, greenlit, making, exporting, delivered, skipped, declined, cancelled, failed
production.sourcerequiredobject
production.source.kindrequiredenumOne of: app, api, mcp
production.source.externalIdrequiredstring | null
production.source.originobject | nullDefault null
production.source.origin.providerrequiredstring
production.source.origin.labelrequiredstring
production.source.origin.urlurl | nullDefault null
production.source.origin.refstring | nullDefault null
production.source.origin.requestedBystring | nullDefault null
production.briefrequiredobject
production.brief.intentrequiredstring
production.brief.contextstring | nullDefault null
production.brief.mediaobject[]
production.brief.media[].idrequiredstring
production.brief.media[].kindrequiredenumOne of: image, video
production.brief.media[].urlrequiredurl
production.brief.media[].namerequiredstring
production.brief.media[].descriptionstring | nullDefault null
production.brief.codeobject[]
production.brief.code[].pathrequiredstring
production.brief.code[].sourcerequiredstring
production.brief.code[].statusenum | nullOne of: added, modified, removed, renamedDefault null
production.brief.code[].additionsintegerDefault 0
production.brief.code[].deletionsintegerDefault 0
production.brief.code[].patchstring | nullDefault null
production.brief.code[].digeststring | nullDefault null
production.brief.code[].scorenumberDefault 0
production.brief.code[].sourceOmittedboolean
production.brief.formatobject
production.brief.format.templateenumOne of: changelog, launch, feature, digest, customDefault changelog
production.brief.format.durationMsintegerDefault 10000
production.brief.format.aspectenumOne of: 16:9, 4:3, 3:2, 21:9, 1:1, 9:16, 3:4, 2:3, 4:5Default 16:9
production.brief.format.soundobject
production.brief.format.sound.voiceoverbooleanDefault true
production.brief.format.sound.musicbooleanDefault true
production.brief.format.sound.sfxbooleanDefault true
production.brief.brandobject
production.brief.brand.namestring | nullDefault null
production.brief.brand.logoUrlurl | nullDefault null
production.brief.brand.primaryColorstring | nullDefault null
production.brief.brand.backgroundColorstring | nullDefault null
production.brief.brand.fontFamilystring | nullDefault null
production.brief.brand.tonestring | nullDefault null
production.pitchrequiredobject | null
production.pitch.versionrequiredinteger
production.pitch.verdictenumOne of: video, skipDefault video
production.pitch.verdictReasonstring | nullDefault null
production.pitch.titlerequiredstring
production.pitch.summaryrequiredstring
production.pitch.shotsrequiredobject[]
production.pitch.shots[].indexrequiredinteger
production.pitch.shots[].titlerequiredstring
production.pitch.shots[].durationMsrequiredinteger
production.pitch.shots[].beatstring | nullDefault null
production.pitch.shots[].visualrequiredstring
production.pitch.shots[].textstring | nullDefault null
production.pitch.shots[].voiceoverstring | nullDefault null
production.pitch.shots[].mediaIdsstring[]
production.pitch.shots[].codePathsstring[]
production.pitch.musicstring | nullDefault null
production.pitch.estimatedCreditsrequiredinteger
production.pitch.createdAtrequireddatetime
production.greenlightrequiredobject | null
production.greenlight.moderequiredenumOne of: manual, auto
production.greenlight.actorrequiredstring
production.greenlight.actorNamestring | null
production.greenlight.atrequireddatetime
production.greenlight.pitchVersionrequiredinteger
production.greenlightModerequiredenumOne of: manual, auto
production.deliveryrequiredobject | null
production.delivery.shareUrlrequiredurl
production.delivery.projectIdrequireduuid
production.delivery.editUrlrequiredurl
production.delivery.exportIdrequireduuid
production.delivery.deliveredAtrequireddatetime
production.projectIdrequireduuid | null
production.creditsChargedrequiredinteger
production.errorrequiredstring | nullWhy the production failed, in words you can show a person. Never the render machine's own diagnostics.
production.createdAtrequireddatetime
production.updatedAtrequireddatetime
production.terminalbooleanTrue 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.
production.pageUrlurlThe production's page in the Raylight app. Absent from payloads stored before the field existed.

201 response body

FieldTypeDescription
productionrequiredobject
production.idrequireduuid
production.workspaceIdrequireduuid
production.stagerequiredenumOne of: queued, writing_pitch, pitch_ready, greenlit, making, exporting, delivered, skipped, declined, cancelled, failed
production.sourcerequiredobject
production.source.kindrequiredenumOne of: app, api, mcp
production.source.externalIdrequiredstring | null
production.source.originobject | nullDefault null
production.source.origin.providerrequiredstring
production.source.origin.labelrequiredstring
production.source.origin.urlurl | nullDefault null
production.source.origin.refstring | nullDefault null
production.source.origin.requestedBystring | nullDefault null
production.briefrequiredobject
production.brief.intentrequiredstring
production.brief.contextstring | nullDefault null
production.brief.mediaobject[]
production.brief.media[].idrequiredstring
production.brief.media[].kindrequiredenumOne of: image, video
production.brief.media[].urlrequiredurl
production.brief.media[].namerequiredstring
production.brief.media[].descriptionstring | nullDefault null
production.brief.codeobject[]
production.brief.code[].pathrequiredstring
production.brief.code[].sourcerequiredstring
production.brief.code[].statusenum | nullOne of: added, modified, removed, renamedDefault null
production.brief.code[].additionsintegerDefault 0
production.brief.code[].deletionsintegerDefault 0
production.brief.code[].patchstring | nullDefault null
production.brief.code[].digeststring | nullDefault null
production.brief.code[].scorenumberDefault 0
production.brief.code[].sourceOmittedboolean
production.brief.formatobject
production.brief.format.templateenumOne of: changelog, launch, feature, digest, customDefault changelog
production.brief.format.durationMsintegerDefault 10000
production.brief.format.aspectenumOne of: 16:9, 4:3, 3:2, 21:9, 1:1, 9:16, 3:4, 2:3, 4:5Default 16:9
production.brief.format.soundobject
production.brief.format.sound.voiceoverbooleanDefault true
production.brief.format.sound.musicbooleanDefault true
production.brief.format.sound.sfxbooleanDefault true
production.brief.brandobject
production.brief.brand.namestring | nullDefault null
production.brief.brand.logoUrlurl | nullDefault null
production.brief.brand.primaryColorstring | nullDefault null
production.brief.brand.backgroundColorstring | nullDefault null
production.brief.brand.fontFamilystring | nullDefault null
production.brief.brand.tonestring | nullDefault null
production.pitchrequiredobject | null
production.pitch.versionrequiredinteger
production.pitch.verdictenumOne of: video, skipDefault video
production.pitch.verdictReasonstring | nullDefault null
production.pitch.titlerequiredstring
production.pitch.summaryrequiredstring
production.pitch.shotsrequiredobject[]
production.pitch.shots[].indexrequiredinteger
production.pitch.shots[].titlerequiredstring
production.pitch.shots[].durationMsrequiredinteger
production.pitch.shots[].beatstring | nullDefault null
production.pitch.shots[].visualrequiredstring
production.pitch.shots[].textstring | nullDefault null
production.pitch.shots[].voiceoverstring | nullDefault null
production.pitch.shots[].mediaIdsstring[]
production.pitch.shots[].codePathsstring[]
production.pitch.musicstring | nullDefault null
production.pitch.estimatedCreditsrequiredinteger
production.pitch.createdAtrequireddatetime
production.greenlightrequiredobject | null
production.greenlight.moderequiredenumOne of: manual, auto
production.greenlight.actorrequiredstring
production.greenlight.actorNamestring | null
production.greenlight.atrequireddatetime
production.greenlight.pitchVersionrequiredinteger
production.greenlightModerequiredenumOne of: manual, auto
production.deliveryrequiredobject | null
production.delivery.shareUrlrequiredurl
production.delivery.projectIdrequireduuid
production.delivery.editUrlrequiredurl
production.delivery.exportIdrequireduuid
production.delivery.deliveredAtrequireddatetime
production.projectIdrequireduuid | null
production.creditsChargedrequiredinteger
production.errorrequiredstring | nullWhy the production failed, in words you can show a person. Never the render machine's own diagnostics.
production.createdAtrequireddatetime
production.updatedAtrequireddatetime
production.terminalbooleanTrue 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.
production.pageUrlurlThe production's page in the Raylight app. Absent from payloads stored before the field existed.

Example

curl
curl -X POST https://api.raylight.app/v1/productions \  -H "Authorization: Bearer $RAYLIGHT_API_KEY" \  -H "Content-Type: application/json" \  -d '{  "brief": {    "intent": "Announce dark mode in the Acme dashboard to existing customers.",    "context": "PR #412 adds a theme toggle to Settings. Charts, tables and the sidebar all pick up the dark palette. Ships to everyone on Thursday.",    "media": [      {        "id": "dashboard-dark",        "kind": "image",        "url": "https://cdn.acme.dev/press/dashboard-dark.png",        "name": "Dashboard in dark mode",        "description": "The analytics overview with the new dark theme."      }    ],    "code": [      {        "path": "src/components/settings/theme-toggle.tsx",        "source": "export const ThemeToggle = () => { /* ... */ }"      }    ],    "format": {      "template": "feature",      "durationMs": 10000,      "aspect": "16:9",      "sound": { "voiceover": true, "music": true, "sfx": true }    },    "brand": {      "name": "Acme",      "primaryColor": "#6C5CE7",      "tone": "confident, plain"    }  },  "greenlightMode": "manual",  "externalId": "acme/web#412",  "origin": {    "provider": "github",    "label": "acme/web #412",    "url": "https://github.com/acme/web/pull/412",    "ref": "feat/dark-mode",    "requestedBy": "jane"  }}'