Skip to content

Add transcript download endpoint to REST API #1656

@abegong

Description

@abegong

There currently isn't a way to programmatically retrieve a video's transcript (VTT) via the Developer API or any public endpoint. The transcript data exists in S3 and is rendered in the share page UI, but it's only accessible through Next.js server actions — which can't be called externally with curl or similar tools.

Use case

I want to fetch transcripts for Cap recordings programmatically (e.g. to feed into documentation pipelines, search indexes, or note-taking workflows). Right now the only option is to open the share page in a browser and use the UI download button.

What exists today

The video object returned by GET /api/developer/v1/videos/:id already includes transcriptionStatus, but there's no endpoint to retrieve the actual transcript content.

Internally, the transcript is stored in S3 at {ownerId}/{videoId}/transcription.vtt and is fetched by the server action in apps/web/actions/videos/get-transcript.ts. The share page's Transcript tab (apps/web/app/s/[videoId]/_components/tabs/Transcript.tsx) consumes it via the useTranscript hook.

There is a code path in apps/web/app/api/playlist/route.ts that serves VTT when fileType=transcription is passed — but it's only reachable for videos stored in a custom S3 bucket, since the Option.isNone(customBucket) branch returns early with a redirect before the fileType check.

Proposal

Add a GET /api/developer/v1/videos/:id/transcript endpoint that returns the VTT content. Something like:

GET /api/developer/v1/videos/:id/transcript
Authorization: Bearer csk_...

200 OK
Content-Type: text/vtt

WEBVTT

1
00:00:01.000 --> 00:00:04.000
Hello, this is my recording...

Returning 404 when transcriptionStatus is not COMPLETE, and 202 if it's still PROCESSING.

This would follow the existing pattern in apps/web/app/api/developer/v1/[...route]/videos.ts and use the same S3Buckets.getBucketAccess + bucket.getObject approach that get-transcript.ts already uses.

A secondary (smaller) fix would be to also make the existing /api/playlist?videoId=...&fileType=transcription path work for default-bucket videos, not just custom-bucket ones.

Willingness to contribute

I'm happy to write the code for this if it's something you'd accept as a PR. Let me know if this aligns with your plans or if there's a preferred approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions