RaylightAPI

Webhooks

A production event, delivered to your endpoint

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.

POSTyour endpoint URL

Sent by Raylight, signed with your endpoint's secret. Check Raylight-Signature before trusting the body.

Headers

FieldInTypeDescription
raylight-signaturerequiredheaderstringt=<unix seconds>,v1=<hex HMAC-SHA256>[,v1=...]
raylight-event-idrequiredheaderstringStable across retries; dedupe on it.
raylight-event-typerequiredheaderstringThe payload's type.

Payload

application/json

FieldTypeDescription
idrequireduuid
typerequiredenumOne of: production.pitch_ready, production.skipped, production.greenlit, production.progress, production.delivered, production.failed, production.declined, production.cancelled, ping
createdAtrequireddatetime
workspaceIdrequireduuid
redeliveryOfuuid
datarequiredobject
data.productionobject
data.production.idrequireduuid
data.production.workspaceIdrequireduuid
data.production.stagerequiredenumOne of: queued, writing_pitch, pitch_ready, greenlit, making, exporting, delivered, skipped, declined, cancelled, failed
data.production.sourcerequiredobject
data.production.source.kindrequiredenumOne of: app, api, mcp
data.production.source.externalIdrequiredstring | null
data.production.source.originobject | nullDefault null
data.production.source.origin.providerrequiredstring
data.production.source.origin.labelrequiredstring
data.production.source.origin.urlurl | nullDefault null
data.production.source.origin.refstring | nullDefault null
data.production.source.origin.requestedBystring | nullDefault null
data.production.briefrequiredobject
data.production.brief.intentrequiredstring
data.production.brief.contextstring | nullDefault null
data.production.brief.mediaobject[]
data.production.brief.media[].idrequiredstring
data.production.brief.media[].kindrequiredenumOne of: image, video
data.production.brief.media[].urlrequiredurl
data.production.brief.media[].namerequiredstring
data.production.brief.media[].descriptionstring | nullDefault null
data.production.brief.codeobject[]
data.production.brief.code[].pathrequiredstring
data.production.brief.code[].sourcerequiredstring
data.production.brief.code[].statusenum | nullOne of: added, modified, removed, renamedDefault null
data.production.brief.code[].additionsintegerDefault 0
data.production.brief.code[].deletionsintegerDefault 0
data.production.brief.code[].patchstring | nullDefault null
data.production.brief.code[].digeststring | nullDefault null
data.production.brief.code[].scorenumberDefault 0
data.production.brief.code[].sourceOmittedboolean
data.production.brief.formatobject
data.production.brief.format.templateenumOne of: changelog, launch, feature, digest, customDefault changelog
data.production.brief.format.durationMsintegerDefault 10000
data.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
data.production.brief.format.soundobject
data.production.brief.brandobject
data.production.brief.brand.namestring | nullDefault null
data.production.brief.brand.logoUrlurl | nullDefault null
data.production.brief.brand.primaryColorstring | nullDefault null
data.production.brief.brand.backgroundColorstring | nullDefault null
data.production.brief.brand.fontFamilystring | nullDefault null
data.production.brief.brand.tonestring | nullDefault null
data.production.pitchrequiredobject | null
data.production.pitch.versionrequiredinteger
data.production.pitch.verdictenumOne of: video, skipDefault video
data.production.pitch.verdictReasonstring | nullDefault null
data.production.pitch.titlerequiredstring
data.production.pitch.summaryrequiredstring
data.production.pitch.shotsrequiredobject[]
data.production.pitch.shots[].indexrequiredinteger
data.production.pitch.shots[].titlerequiredstring
data.production.pitch.shots[].durationMsrequiredinteger
data.production.pitch.shots[].beatstring | nullDefault null
data.production.pitch.shots[].visualrequiredstring
data.production.pitch.shots[].textstring | nullDefault null
data.production.pitch.shots[].voiceoverstring | nullDefault null
data.production.pitch.shots[].mediaIdsstring[]
data.production.pitch.shots[].codePathsstring[]
data.production.pitch.musicstring | nullDefault null
data.production.pitch.estimatedCreditsrequiredinteger
data.production.pitch.createdAtrequireddatetime
data.production.greenlightrequiredobject | null
data.production.greenlight.moderequiredenumOne of: manual, auto
data.production.greenlight.actorrequiredstring
data.production.greenlight.actorNamestring | null
data.production.greenlight.atrequireddatetime
data.production.greenlight.pitchVersionrequiredinteger
data.production.greenlightModerequiredenumOne of: manual, auto
data.production.deliveryrequiredobject | null
data.production.delivery.shareUrlrequiredurl
data.production.delivery.projectIdrequireduuid
data.production.delivery.editUrlrequiredurl
data.production.delivery.exportIdrequireduuid
data.production.delivery.deliveredAtrequireddatetime
data.production.projectIdrequireduuid | null
data.production.creditsChargedrequiredinteger
data.production.errorrequiredstring | null
data.production.createdAtrequireddatetime
data.production.updatedAtrequireddatetime
data.production.terminalboolean
data.production.pageUrlurl
data.pitchMarkdownstring | null
data.statusstring | null
data.linksobject
data.links.pagerequiredurl
data.links.greenlightrequiredurl | null
data.links.commentrequiredurl | null
data.links.declinerequiredurl | null
data.links.sharerequiredurl | null
data.links.editrequiredurl | null
data.endpointIduuid
data.messagestring

Your answer

200Any 2xx acknowledges the delivery. Anything else is retried at 30s, 2m, 10m, 1h and 6h.

Example

production.pitch_ready
{  "id": "c1d2e3f4-5a6b-4c7d-8e9f-0a1b2c3d4e5f",  "type": "production.pitch_ready",  "createdAt": "2026-10-17T18:04:12.000Z",  "workspaceId": "0b9d8c7a-6e5f-4d3c-ab1a-09f8e7d6c5b4",  "data": {    "production": {      "id": "6f1c2b7e-3d4a-4c8e-9a2b-1f0e5d6c7b8a",      "workspaceId": "0b9d8c7a-6e5f-4d3c-ab1a-09f8e7d6c5b4",      "stage": "pitch_ready",      "source": {        "kind": "api",        "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"        }      },      "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": "",            "status": "modified",            "additions": 48,            "deletions": 9,            "patch": null,            "sourceOmitted": true,            "digest": "ThemeToggle: a pill switch with sun and moon icons, label \"Appearance\", brand purple when on.",            "score": 0.91          }        ],        "format": {          "template": "feature",          "durationMs": 10000,          "aspect": "16:9",          "sound": { "voiceover": true, "music": true, "sfx": true }        },        "brand": {          "name": "Acme",          "logoUrl": null,          "primaryColor": "#6C5CE7",          "backgroundColor": null,          "fontFamily": null,          "tone": "confident, plain"        }      },      "pitch": {        "version": 1,        "verdict": "video",        "verdictReason": null,        "title": "Dark mode, finally",        "summary": "A 10 second feature spot: the toggle flips, the dashboard follows, and an end card says it ships Thursday.",        "shots": [          {            "index": 0,            "title": "The flip",            "durationMs": 3000,            "beat": "The theme toggle flips and the whole settings page goes dark.",            "visual": "The ThemeToggle component rebuilt as layers at hero scale, centred, a slow push-in. On the flip the background sweeps from white to the brand dark.",            "text": "Dark mode",            "voiceover": "Dark mode is here.",            "mediaIds": [],            "codePaths": ["src/components/settings/theme-toggle.tsx"]          },          {            "index": 1,            "title": "The dashboard",            "durationMs": 4500,            "beat": "The analytics overview in dark, tilted, drifting left.",            "visual": "dashboard-dark on a device frame, 12 degree tilt, a lateral drift with a soft depth of field.",            "text": "Every chart. Every table.",            "voiceover": "Charts, tables and the sidebar all follow.",            "mediaIds": ["dashboard-dark"],            "codePaths": []          },          {            "index": 2,            "title": "Sign-off",            "durationMs": 2500,            "beat": "The Acme logo on the dark background with the ship date.",            "visual": "Logo centred on the brand dark, the date types on underneath, a short hold before the cut.",            "text": "Thursday, for everyone",            "voiceover": "Turn it on in Settings, Thursday.",            "mediaIds": [],            "codePaths": []          }        ],        "music": "Low, steady, electronic. No drop.",        "estimatedCredits": 600,        "createdAt": "2026-10-17T18:04:11.000Z"      },      "greenlight": null,      "greenlightMode": "manual",      "delivery": null,      "projectId": null,      "creditsCharged": 0,      "error": null,      "createdAt": "2026-10-17T18:02:40.000Z",      "updatedAt": "2026-10-17T18:04:11.000Z",      "terminal": false,      "pageUrl": "https://www.raylight.app/api/productions/6f1c2b7e-3d4a-4c8e-9a2b-1f0e5d6c7b8a"    },    "pitchMarkdown": "## Dark mode, finally\n\nA 10 second feature spot ...",    "status": null,    "links": {      "page": "https://www.raylight.app/api/productions/6f1c2b7e-3d4a-4c8e-9a2b-1f0e5d6c7b8a",      "greenlight": "https://www.raylight.app/go/v1.eyJqIjoiNmYxYzJiN2UiLCJ2IjoxfQ.q8Zt3VbY1mK0?action=greenlight",      "comment": "https://www.raylight.app/go/v1.eyJqIjoiNmYxYzJiN2UiLCJ2IjoxfQ.q8Zt3VbY1mK0?action=comment",      "decline": "https://www.raylight.app/go/v1.eyJqIjoiNmYxYzJiN2UiLCJ2IjoxfQ.q8Zt3VbY1mK0?action=decline",      "share": null,      "edit": null    }  }}