GET/v1/me
The key making the request: its name, permissions, workspace and expiry. Handy as a first call to check a key works. Any valid key.
curl https://preshow.link/api/v1/me \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{
"object": "api_key",
"id": "key_7Qm2x9K4pT0aZ1bC",
"name": "Render farm uploader",
"scopes": [
"projects:read"
],
"workspace": {
"kind": "team",
"id": "team_abc123",
"name": "Northlight Studio"
},
"created_at": "2026-09-23T15:04:05.000Z",
"expires_at": "2026-12-22T15:04:05.000Z"
}GET/v1/projects
The projects in the key’s workspace that its owner can open, oldest id first. Requires projects:read.
limit (query) Page size, 1 to 100. Default 25.cursor (query) The next_cursor from the previous page. Omit for the first page.
curl "https://preshow.link/api/v1/projects?limit=10" \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{
"object": "list",
"data": [
{
"object": "project",
"id": "proj-1790130227580-2c6a1f827",
"name": "Arena tour 2027",
"workspace": {
"kind": "team",
"id": "team_abc123"
},
"role": "editor",
"visibility": "team",
"created_at": "2026-09-01T09:30:00.000Z",
"updated_at": "2026-09-22T18:12:44.000Z",
"app_url": "https://preshow.link/app?project=proj-1790130227580-2c6a1f827"
}
],
"has_more": true,
"next_cursor": "proj-1790130227580-2c6a1f827"
}GET/v1/projects/{projectId}
One project. Answers 404 alike for a project that does not exist, is in another workspace, or the owner cannot open, so a key cannot probe for ids. Requires projects:read.
projectId (path) The project’s id, as returned by the list.
curl https://preshow.link/api/v1/projects/proj-1790130227580-2c6a1f827 \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "project", "id": "proj-1790130227580-2c6a1f827", … }GET/v1/projects/{projectId}/stages
A project’s stages, each with the screens a comp can use. A screen is known once it is the stage’s default screen or a comp in Preshow already uses it; a stage with none yet needs one of those first. Requires projects:read.
limit (query) Page size, 1 to 100. Default 25.cursor (query) The next_cursor from the previous page. Omit for the first page.
curl https://preshow.link/api/v1/projects/$PROJECT_ID/stages \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{
"object": "list",
"data": [
{
"object": "stage",
"id": "scene-1790130230112-8d1e0b4c2",
"name": "Arena main stage",
"default_screen": "Main_LED_Wall",
"known_screens": [
"Main_LED_Wall",
"Side_LED_Left",
"Side_LED_Right"
],
"thumbnail_url": "https://preshow.link/media/…/thumbnail.jpg"
}
],
"has_more": false,
"next_cursor": null
}GET/v1/projects/{projectId}/media
A project’s media library: videos, stills and audio, with the processing status of each. Requires projects:read.
limit (query) Page size, 1 to 100. Default 25.cursor (query) The next_cursor from the previous page. Omit for the first page.
curl https://preshow.link/api/v1/projects/$PROJECT_ID/media \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "list", "data": [{ "object": "media", … }], "has_more": false, "next_cursor": null }POST/v1/projects/{projectId}/media
Adds a video to the project and returns a one-time upload URL. Then PUT the file’s bytes to upload.url (it stays valid for an hour) and poll the media item until its status is ready. The video appears in Preshow at once, marked as processing, and in open tabs without a reload. Send an Idempotency-Key so a retry cannot add it twice. Requires media:write.
name (body) Required. Shown in the media library.filename (body) Optional. Defaults to name.duration_seconds (body) Optional but recommended: checked against your plan’s video minutes before anything is uploaded.width, height (body) Optional pixel size. 4K and wide LED content keeps its full resolution.size_bytes (body) Optional. The file’s size.
curl -X POST https://preshow.link/api/v1/projects/$PROJECT_ID/media \
-H "Authorization: Bearer $PRESHOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name": "Opener v3", "filename": "opener_v3.mov", "duration_seconds": 42.5, "width": 3840, "height": 2160}'
# then send the file itself to the upload url from the response
curl -X PUT --upload-file opener_v3.mov "$UPLOAD_URL"{
"object": "media",
"id": "asset-1790131002211-4be09a7d1",
"project_id": "proj-1790130227580-2c6a1f827",
"name": "Opener v3",
"type": "video",
"status": "processing",
"duration_seconds": 42.5,
"width": null,
"height": null,
"thumbnail_url": null,
"version": {
"id": "ver-1790131002211-0c5f2e9ab",
"created_at": "2026-09-23T21:03:22.211Z"
},
"versions_count": 1,
"created_at": "2026-09-23T21:03:22.211Z",
"upload": {
"url": "https://storage.googleapis.com/video-storage-…",
"method": "PUT",
"expires_at": "2026-09-23T22:03:22.211Z"
}
}GET/v1/projects/{projectId}/media/{mediaId}
One media item. Poll this after uploading: status goes from processing to ready (usually well under a minute per minute of video), or to error if the file could not be read. Requires projects:read.
curl https://preshow.link/api/v1/projects/$PROJECT_ID/media/$MEDIA_ID \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "media", "id": "asset-1790131002211-4be09a7d1", "status": "ready", "duration_seconds": 42.5, "width": 3840, "height": 2160, … }GET/v1/projects/{projectId}/comps
A project’s comps, with the media on each screen and a link that opens the comp in Preshow. Requires projects:read.
limit (query) Page size, 1 to 100. Default 25.cursor (query) The next_cursor from the previous page. Omit for the first page.
curl https://preshow.link/api/v1/projects/$PROJECT_ID/comps \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "list", "data": [{ "object": "comp", … }], "has_more": false, "next_cursor": null }POST/v1/projects/{projectId}/comps
Makes a comp on a stage, putting media on its screens. Each screen must be one of the stage’s known_screens and each media item must be ready. The comp opens in Preshow as a draft, like one made by hand. Send an Idempotency-Key so a retry cannot make it twice. Requires comps:write.
stage_id (body) Required. From the stages list.screens (body) Required, 1 to 32 of { screen, media_id, start_seconds }. start_seconds defaults to 0.name (body) Optional. Defaults to the first media item’s name.
curl -X POST https://preshow.link/api/v1/projects/$PROJECT_ID/comps \
-H "Authorization: Bearer $PRESHOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name": "Opener look A", "stage_id": "scene-1790130230112-8d1e0b4c2",
"screens": [{"screen": "Main_LED_Wall", "media_id": "asset-1790131002211-4be09a7d1"}]}'{
"object": "comp",
"id": "comp-1790131090418-a93d0c1e7",
"project_id": "proj-1790130227580-2c6a1f827",
"name": "Opener look A",
"stage_id": "scene-1790130230112-8d1e0b4c2",
"status": "draft",
"duration_seconds": 42.5,
"screens": [
{
"screen": "Main_LED_Wall",
"media_id": "asset-1790131002211-4be09a7d1",
"start_seconds": 0,
"duration_seconds": 42.5
}
],
"created_at": "2026-09-23T21:04:50.418Z",
"updated_at": "2026-09-23T21:04:50.418Z",
"app_url": "https://preshow.link/app?project=proj-1790130227580-2c6a1f827&view=editor&composition=comp-1790131090418-a93d0c1e7"
}GET/v1/projects/{projectId}/comps/{compId}
One comp. Requires projects:read.
curl https://preshow.link/api/v1/projects/$PROJECT_ID/comps/$COMP_ID \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "comp", "id": "comp-1790131090418-a93d0c1e7", … }GET/v1/webhook_endpoints
The webhook endpoints the key’s owner added to the key’s workspace, in Settings or through the API. Requires webhooks:manage.
limit (query) Page size, 1 to 100. Default 25.cursor (query) The next_cursor from the previous page. Omit for the first page.
curl https://preshow.link/api/v1/webhook_endpoints \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "list", "data": [{ "object": "webhook_endpoint", … }], "has_more": false, "next_cursor": null }POST/v1/webhook_endpoints
Starts sending the chosen events to a URL. The response holds the signing secret, the only time it is shown. This is how an automation platform subscribes itself; people usually add endpoints in Settings instead. Requires webhooks:manage.
url (body) Required. An https URL on the public internet.events (body) Required. Event types from the list below, or ["*"] for all of them, including ones added later.description (body) Optional, up to 100 characters.
curl -X POST https://preshow.link/api/v1/webhook_endpoints \
-H "Authorization: Bearer $PRESHOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/preshow-events", "events": ["media.ready", "comp.status_changed"]}'{
"object": "webhook_endpoint",
"id": "we_4hQ8mZ2rT6yV0bN3cX7k",
"url": "https://example.com/preshow-events",
"description": "",
"events": [
"comp.status_changed",
"media.ready"
],
"status": "enabled",
"disabled_reason": null,
"created_at": "2026-09-23T21:10:00.000Z",
"last_success_at": null,
"last_failure_at": null,
"secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}GET/v1/webhook_endpoints/{endpointId}
One endpoint, with when it last delivered and whether it is failing. The secret is never returned again. Requires webhooks:manage.
curl https://preshow.link/api/v1/webhook_endpoints/$ENDPOINT_ID \
-H "Authorization: Bearer $PRESHOW_API_KEY"
{ "object": "webhook_endpoint", "id": "we_4hQ8mZ2rT6yV0bN3cX7k", "status": "enabled", … }DELETE/v1/webhook_endpoints/{endpointId}
Stops sending to the endpoint at once, including retries already scheduled. Answers 204 with no body. Requires webhooks:manage.
curl -X DELETE https://preshow.link/api/v1/webhook_endpoints/$ENDPOINT_ID \
-H "Authorization: Bearer $PRESHOW_API_KEY"
HTTP/1.1 204 No Content