> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reap.video/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Captions

> Add AI-generated captions to your videos with customizable styling

> **For AI agents:** a documentation index is at [/llms.txt](/llms.txt). Every page is also available as markdown, just append `.md` to the URL.

## Overview

Add professional captions to your videos using AI-powered transcription. This endpoint generates accurate captions with various styling options, emoji support, and keyword highlighting. Perfect for making content accessible and engaging on social media platforms.

## Rate Limiting

This endpoint is rate limited to 10 requests per minute per API key.

<Note>
  You must provide either `sourceUrl` or `uploadId`, but not both.
</Note>

## Video Requirements

<CardGroup cols={2}>
  <Card title="Duration" icon="clock">
    **Minimum:** 3 seconds\
    **Maximum:** 15 minutes
  </Card>

  <Card title="File Size" icon="scale-balanced">
    **Maximum:** 5 GB
  </Card>

  <Card title="Format" icon="file-video">
    MP4 or MOV with valid video and audio streams
  </Card>

  <Card title="Audio Quality" icon="microphone">
    Clear speech produces best transcription results
  </Card>
</CardGroup>

## Plan Limits

| Plan    | Max Resolution | Concurrent Projects |
| ------- | -------------- | ------------------- |
| Creator | 1080p          | 3                   |
| Studio  | 4K (2160p)     | 10                  |

Higher-tier plans allow you to process more videos simultaneously and export at higher resolutions.

<Note>
  The Automation API requires an active subscription. [View pricing](https://reap.video/pricing) to compare plans.
</Note>

## Response

<ResponseField name="id" type="string">
  Unique project identifier
</ResponseField>

<ResponseField name="title" type="string">
  Project title (usually the filename)
</ResponseField>

<ResponseField name="thumbnail" type="string">
  Thumbnail URL for the project
</ResponseField>

<ResponseField name="billedDuration" type="number">
  Duration in seconds that will be billed to your account
</ResponseField>

<ResponseField name="status" type="string">
  Current processing status

  * `processing` - Video is being transcribed and captions are being generated
  * `completed` - Captions have been generated successfully
  * `failed` - Processing failed due to an error
</ResponseField>

<ResponseField name="projectType" type="string">
  Type of project (always "captions" for this endpoint)
</ResponseField>

<ResponseField name="source" type="string">
  Source of the video content

  * `Upload` - Uploaded file
  * `Generic` - External URL
</ResponseField>

<ResponseField name="captionsPreset" type="string">
  Caption style preset ID used
</ResponseField>

<ResponseField name="enableCaptions" type="boolean">
  Whether captions are enabled (always true for caption projects)
</ResponseField>

<ResponseField name="enableEmojis" type="boolean">
  Whether emojis are added to captions
</ResponseField>

<ResponseField name="enableHighlights" type="boolean">
  Whether keyword highlighting is enabled
</ResponseField>

<ResponseField name="language" type="string">
  Primary language of the video content
</ResponseField>

<ResponseField name="translateTranscription" type="boolean">
  Whether transcription will be translated
</ResponseField>

<ResponseField name="translationLanguages" type="array">
  Array of languages for translation
</ResponseField>

<ResponseField name="transcriptionScript" type="string">
  Script format for transcription ("native" or "roman")
</ResponseField>

<ResponseField name="metadata" type="object">
  Video file metadata including duration, resolution, format, etc.
</ResponseField>

<ResponseField name="urls" type="object">
  Project URLs and assets (populated when processing completes)
</ResponseField>

<ResponseField name="createdAt" type="integer">
  Unix timestamp when the project was created
</ResponseField>

<ResponseField name="updatedAt" type="integer">
  Unix timestamp when the project was last updated
</ResponseField>

## Example Request

<CodeGroup>
  ```bash cURL with Upload theme={"system"}
  curl -X POST "https://public.reap.video/api/v1/automation/create-captions" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "uploadId": "65f1a2b3c4d5e6f7a8b9c0d1",
      "captionsPreset": "system_beasty",
      "language": "en",
      "enableEmojis": true,
      "enableHighlights": true
    }'
  ```

  ```bash cURL with URL theme={"system"}
  curl -X POST "https://public.reap.video/api/v1/automation/create-captions" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "sourceUrl": "https://example.com/video.mp4",
      "captionsPreset": "system_minimal",
      "resolution": 1080
    }'
  ```

  ```javascript JavaScript theme={"system"}
  const response = await fetch('https://public.reap.video/api/v1/automation/create-captions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      uploadId: '65f1a2b3c4d5e6f7a8b9c0d1',
      captionsPreset: 'system_beasty',
      language: 'en',
      enableEmojis: true,
      enableHighlights: true
    })
  });

  const project = await response.json();
  console.log('Caption project created:', project.id);
  ```

  ```python Python theme={"system"}
  import requests

  headers = {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
  }

  data = {
      'uploadId': '65f1a2b3c4d5e6f7a8b9c0d1',
      'captionsPreset': 'system_beasty',
      'language': 'en',
      'enableEmojis': True,
      'enableHighlights': True
  }

  response = requests.post(
      'https://public.reap.video/api/v1/automation/create-captions',
      headers=headers,
      json=data
  )

  project = response.json()
  print(f'Caption project created: {project["id"]}')
  ```

  ```php PHP theme={"system"}
  <?php
  $data = [
      'uploadId' => '65f1a2b3c4d5e6f7a8b9c0d1',
      'captionsPreset' => 'system_beasty',
      'language' => 'en',
      'enableEmojis' => true,
      'enableHighlights' => true
  ];

  $ch = curl_init('https://public.reap.video/api/v1/automation/create-captions');
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer YOUR_API_KEY',
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $response = curl_exec($ch);
  curl_close($ch);
  $project = json_decode($response, true);
  echo 'Caption project created: ' . $project['id'] . "\n";
  ?>
  ```

  ```go Go theme={"system"}
  package main
  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io/ioutil"
      "net/http"
  )
  func main() {
      url := "https://public.reap.video/api/v1/automation/create-captions"
      data := map[string]interface{}{
          "uploadId": "65f1a2b3c4d5e6f7a8b9c0d1",
          "captionsPreset": "system_beasty",
          "language": "en",
          "enableEmojis": true,
          "enableHighlights": true,
      }
      payload, _ := json.Marshal(data)
      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload))
      req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
      req.Header.Set("Content-Type", "application/json")
      client := &http.Client{}
      resp, _ := client.Do(req)
      defer resp.Body.Close()
      body, _ := ioutil.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```

  ```java Java theme={"system"}
  import java.io.*;
  import java.net.HttpURLConnection;
  import java.net.URL;
  public class CreateCaptionsExample {
      public static void main(String[] args) throws Exception {
          URL url = new URL("https://public.reap.video/api/v1/automation/create-captions");
          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
          conn.setRequestMethod("POST");
          conn.setRequestProperty("Authorization", "Bearer YOUR_API_KEY");
          conn.setRequestProperty("Content-Type", "application/json");
          conn.setDoOutput(true);
          String jsonInputString = "{" +
              "\"uploadId\": \"65f1a2b3c4d5e6f7a8b9c0d1\"," +
              "\"captionsPreset\": \"system_beasty\"," +
              "\"language\": \"en\"," +
              "\"enableEmojis\": true," +
              "\"enableHighlights\": true}";
          try(OutputStream os = conn.getOutputStream()) {
              byte[] input = jsonInputString.getBytes("utf-8");
              os.write(input, 0, input.length);
          }
          BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
          StringBuilder response = new StringBuilder();
          String responseLine;
          while ((responseLine = br.readLine()) != null) {
              response.append(responseLine.trim());
          }
          System.out.println("Caption project: " + response.toString());
      }
  }
  ```
</CodeGroup>

## Example Response

<CodeGroup>
  <CodeGroup.Tab label="200 OK">
    ```json theme={"system"}
    {
      "id": "65f1a2b3c4d5e6f7a8b9c0d2",
      "title": "my-video.mp4",
      "thumbnail": "https://cdn.reap.video/thumbnails/65f1a2b3c4d5e6f7a8b9c0d2.jpg",
      "billedDuration": 180.5,
      "status": "processing",
      "projectType": "captions",
      "source": "Upload",
      "genre": "talking",
      "topics": [],
      "clipDurations": [],
      "selectedStart": 0,
      "selectedEnd": null,
      "reframeClips": false,
      "exportResolution": 1080,
      "exportOrientation": "landscape",
      "captionsPreset": "system_beasty",
      "enableCaptions": true,
      "enableEmojis": true,
      "enableHighlights": true,
      "language": "en",
      "dubbingLanguage": null,
      "translateTranscription": false,
      "translationLanguages": [],
      "transcriptionScript": "native",
      "metadata": {
        "duration": 180.5,
        "width": 1920,
        "height": 1080,
        "fps": 30,
        "bitrate": 5000000,
        "size": 45000000,
        "codec": "h264"
      },
      "urls": {},
      "createdAt": 1710000000,
      "updatedAt": 1710000000
    }
    ```
  </CodeGroup.Tab>

  <CodeGroup.Tab label="400 Bad Request">
    ```json theme={"system"}
    {
      "detail": "Missing source URL or upload ID."
    }
    ```
  </CodeGroup.Tab>

  <CodeGroup.Tab label="401 Unauthorized">
    ```json theme={"system"}
    {
      "detail": "Unauthorized - Invalid or missing API key"
    }
    ```
  </CodeGroup.Tab>

  <CodeGroup.Tab label="404 Not Found">
    ```json theme={"system"}
    {
      "detail": "Upload not found."
    }
    ```
  </CodeGroup.Tab>

  <CodeGroup.Tab label="429 Too Many Requests">
    ```json theme={"system"}
    {
      "detail": "Maximum concurrent projects reached. Please wait for the current projects to complete."
    }
    ```
  </CodeGroup.Tab>

  <CodeGroup.Tab label="500 Internal Server Error">
    ```json theme={"system"}
    {
      "detail": "Failed to create project. Please contact support."
    }
    ```
  </CodeGroup.Tab>
</CodeGroup>

## Processing Workflow

1. **Audio Extraction** - Audio is extracted from the video file
2. **Transcription** - AI transcribes the speech with precise timing
3. **Caption Generation** - Captions are formatted with your chosen style
4. **Enhancement** - Emojis and highlights are added if enabled
5. **Rendering** - Final video is rendered with embedded captions

## Caption Features

<CardGroup cols={2}>
  <Card title="AI Transcription" icon="microphone">
    Accurate speech-to-text with word-level timing
  </Card>

  <Card title="Style Presets" icon="paint-brush">
    Multiple caption styles for different content types
  </Card>

  <Card title="Emoji Support" icon="face-smile">
    Contextual emojis added automatically
  </Card>

  <Card title="Keyword Highlights" icon="highlighter">
    Important words highlighted for emphasis
  </Card>
</CardGroup>

## Best Practices

* **Audio Quality**: Clear audio produces more accurate transcriptions
* **Language Selection**: Specify the language for better accuracy
* **Style Matching**: Choose presets that match your brand and content type
* **Translation**: Use translation for multilingual audiences

## Use Cases

<CardGroup cols={2}>
  <Card title="Video Platforms" icon="play-circle">
    Auto-generate captions for all uploaded content at scale
  </Card>

  <Card title="Accessibility Compliance" icon="universal-access">
    Meet accessibility requirements with accurate, styled captions
  </Card>

  <Card title="Social Media Tools" icon="share">
    Add caption generation to your social media management platform
  </Card>

  <Card title="Learning Management" icon="graduation-cap">
    Caption educational content for better comprehension and searchability
  </Card>
</CardGroup>

## Next Steps

After creating a caption project:

1. Monitor progress with [Get Project Status](/api-reference/get-project-status)
2. Retrieve the captioned video with [Get Project Clips](/api-reference/get-project-clips)
3. Download and distribute your captioned content


## OpenAPI

````yaml POST /automation/create-captions
openapi: 3.1.0
info:
  title: Reap Automation API
  description: AI-powered video processing automation API
  version: 1.0.0
servers:
  - url: https://public.reap.video/api/v1
security:
  - bearerAuth: []
paths:
  /automation/create-captions:
    post:
      summary: Create Captions
      description: Add AI-generated captions to your videos
      operationId: createCaptions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCaptionsRequest'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AutomationProject'
components:
  schemas:
    CreateCaptionsRequest:
      type: object
      properties:
        sourceUrl:
          type: string
          description: Direct URL to a video file (alternative to uploadId)
        uploadId:
          type: string
          description: Upload ID from a previously uploaded file (alternative to sourceUrl)
        captionsPreset:
          type: string
          nullable: true
          description: Caption style preset ID. Defaults to system_beasty if not specified.
        language:
          type: string
          nullable: true
          description: >-
            Primary language of the video content (auto-detected if not
            provided)
        translationLanguage:
          type: string
          nullable: true
          description: Language to translate captions to
        transcriptionScript:
          type: string
          enum:
            - native
            - roman
          default: native
          description: Script format for transcription output
        enableEmojis:
          type: boolean
          default: false
          description: Whether to add contextual emojis to captions
        enableHighlights:
          type: boolean
          default: false
          description: Whether to highlight keywords in captions
        resolution:
          type: integer
          enum:
            - 720
            - 1080
            - 1440
            - 2160
          default: 720
          description: Output resolution (only applicable when sourceUrl is provided)
    AutomationProject:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        thumbnail:
          type: string
        billedDuration:
          type: number
        status:
          type: string
          enum:
            - queued
            - prepped
            - draft
            - processing
            - finalizing
            - completed
            - invalid
            - expired
            - failed
            - error
        projectType:
          type: string
          enum:
            - clipping
            - captions
            - reframe
            - dubbing
            - transcription
        source:
          type: string
          enum:
            - Upload
            - Youtube
            - Vimeo
            - TwitchVod
            - Twitter
            - RumbleEmbed
            - Generic
        genre:
          $ref: '#/components/schemas/VideoGenre'
        topics:
          type: array
          items:
            type: string
        clipDurations:
          type: array
          items:
            type: array
            items:
              type: integer
        selectedStart:
          type: number
          nullable: true
        selectedEnd:
          type: number
          nullable: true
        reframeClips:
          type: boolean
        exportResolution:
          type: integer
        exportOrientation:
          $ref: '#/components/schemas/VideoOrientation'
        captionsPreset:
          type: string
          nullable: true
        enableCaptions:
          type: boolean
        enableEmojis:
          type: boolean
        enableHighlights:
          type: boolean
        language:
          type: string
          nullable: true
        dubbingLanguage:
          type: string
          nullable: true
        translateTranscription:
          type: boolean
        translationLanguages:
          type: array
          items:
            type: string
        transcriptionScript:
          $ref: '#/components/schemas/TranscriptionScript'
        metadata:
          $ref: '#/components/schemas/VideoFileMeta'
        urls:
          type: object
        createdAt:
          type: integer
        updatedAt:
          type: integer
    VideoGenre:
      type: string
      enum:
        - talking
        - screenshare
        - gaming
      default: talking
    VideoOrientation:
      type: string
      enum:
        - landscape
        - portrait
        - square
    TranscriptionScript:
      type: string
      enum:
        - native
        - roman
      default: native
    VideoFileMeta:
      type: object
      properties:
        width:
          type: integer
        height:
          type: integer
        aspectRatio:
          type: string
        size:
          type: number
        bitrate:
          type: number
        fps:
          type: number
        duration:
          type: number
        rotation:
          type: integer
        resolution:
          type: integer
        codec:
          type: string
        codecFullName:
          type: string
        codecTag:
          type: string
        format:
          type: string
        formatFullName:
          type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````