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

# Upload media file or URL

> Upload a video file directly, ingest from a URL, or request a signed upload URL for larger local files.
Returns a media_id that can be used for video generation.


## Usage Examples

### 1. Upload from URL

Ingest a video from a public URL.

```bash theme={null}
curl -X POST https://api.viddyscribe.com/enterprise/api/upload_media \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "type": "url",
      "url": "https://example.com/video.mp4"
    }
  }'
```

### 2. Upload Local File

Upload a video file directly.

For local files up to 32 MB, multipart upload is supported directly. For larger local files, see [Large Local File Upload](/large-local-file-upload).

```bash theme={null}
curl -X POST https://api.viddyscribe.com/enterprise/api/upload_media \
  -H "X-API-Key: YOUR_API_KEY" \
  -F 'input={"type": "file"}' \
  -F "file=@/path/to/video.mp4"
```

### 3. Request a Signed Upload URL

For larger local files, request a signed upload URL first.

```bash theme={null}
curl -X POST https://api.viddyscribe.com/enterprise/api/upload_media \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "type": "signed_url",
      "filename": "video.mp4",
      "content_type": "video/mp4"
    }
  }'
```

Then upload the file to `upload_url`, call `notify_upload_complete`, and poll `get_upload_status` until the upload is ready before generating with `media_id`. See [Large Local File Upload](/large-local-file-upload) for the full workflow.

## Common Upload Errors

| Error             | HTTP Status | Description                                                                                                    |
| ----------------- | ----------- | -------------------------------------------------------------------------------------------------------------- |
| `no_video_stream` | `415`       | The uploaded file is not a valid video stream for processing. This usually means the file contains audio only. |
| `video_too_long`  | `403`       | The uploaded video exceeds the maximum duration allowed by the current plan.                                   |
| `file_too_large`  | `403`       | The uploaded file exceeds the maximum file size allowed by the current plan.                                   |

Example response:

```json theme={null}
{
  "error": "no_video_stream",
  "message": "The uploaded file contains audio only. Please upload a video file with at least one video stream."
}
```


## OpenAPI

````yaml post /enterprise/api/upload_media
openapi: 3.0.3
info:
  title: ViddyScribe Enterprise API
  version: 1.0.0
  description: >
    Enterprise API for ViddyScribe video processing and audio description
    generation.


    ## Authentication

    All endpoints require API key authentication via the `X-API-Key` header.


    ## Workflow

    1. Upload media using `/upload_media` - Returns `media_id`

    2. Generate text with `/generate_ad_text`, video with `/generate_ad_video`,
    or audio with `/generate_ad_audio` - Returns `job_id`

    3. Poll for results using `/get_results` - Returns status and outputs when
    done
  contact:
    name: ViddyScribe Support
    email: hello@viddyscribe.com
servers:
  - url: https://api.viddyscribe.com
    description: Production server
security:
  - ApiKeyAuth: []
tags:
  - name: Media
    description: Media upload operations
  - name: Processing
    description: Video processing operations
  - name: Results
    description: Results retrieval operations
paths:
  /enterprise/api/upload_media:
    post:
      tags:
        - Media
      summary: Upload media file or URL
      description: >
        Upload a video file directly, ingest from a URL, or request a signed
        upload URL for larger local files.

        Returns a media_id that can be used for video generation.
      operationId: uploadMedia
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - input
              properties:
                input:
                  oneOf:
                    - type: object
                      title: Upload from URL
                      required:
                        - type
                        - url
                      properties:
                        type:
                          type: string
                          enum:
                            - url
                          description: Type of input provided
                        url:
                          type: string
                          format: uri
                          description: Public video URL
                        filename:
                          type: string
                          description: Optional filename override
                    - type: object
                      title: Request Signed Upload URL
                      required:
                        - type
                        - filename
                      properties:
                        type:
                          type: string
                          enum:
                            - signed_url
                          description: Request a signed upload URL for larger local files
                        filename:
                          type: string
                          description: Original filename for the upload
                        content_type:
                          type: string
                          default: video/mp4
                          description: >-
                            Content-Type that will be used for the signed PUT
                            upload
                        file_size:
                          type: integer
                          description: >-
                            Optional file size in bytes for plan-limit
                            prevalidation
                  discriminator:
                    propertyName: type
          multipart/form-data:
            schema:
              type: object
              required:
                - input
                - file
              properties:
                input:
                  type: string
                  description: 'JSON string {"type": "file"}'
                  example: '{"type": "file"}'
                file:
                  type: string
                  format: binary
                  description: Video file to upload
      responses:
        '200':
          description: Media uploaded successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  media_id:
                    type: string
                    format: uuid
                    description: Unique identifier for the uploaded media
                  status:
                    type: string
                    enum:
                      - created
                      - existing
                      - pending_upload
                    description: Upload status
                  duration_seconds:
                    type: number
                    nullable: true
                    description: Video duration in seconds
                  frame_rate:
                    type: number
                    nullable: true
                    description: Video frame rate (fps)
                  upload_url:
                    type: string
                    format: uri
                    nullable: true
                    description: Signed PUT URL returned for `signed_url` uploads
                  gcs_path:
                    type: string
                    nullable: true
                    description: Storage path associated with the uploaded media
                  content_type:
                    type: string
                    nullable: true
                    description: Content-Type associated with a signed upload
              examples:
                url_or_file:
                  summary: Direct upload or URL ingest
                  value:
                    media_id: 550e8400-e29b-41d4-a716-446655440000
                    status: created
                    duration_seconds: 45.5
                    frame_rate: 30
                signed_url:
                  summary: Signed upload URL for larger local file
                  value:
                    media_id: 550e8400-e29b-41d4-a716-446655440000
                    status: pending_upload
                    upload_url: >-
                      https://storage.googleapis.com/bucket/path/to/video.mp4?X-Goog-Signature=...
                    gcs_path: users/user_123/videos/video.mp4
                    content_type: video/mp4
        '400':
          description: Bad request - missing or invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            Forbidden - input exceeds plan limits such as video_too_long or
            file_too_large
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '415':
          description: Unsupported media type - uploaded media has no video stream
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: >-
            Primary error field. Many endpoints return a machine-readable value
            here, while some 409 media-state responses return a human-readable
            string and place the machine-readable identifier in code
        code:
          type: string
          description: >-
            Optional machine-readable identifier for responses that separate the
            human-readable error text from the stable error code, such as
            upload_not_ready or upload_failed
        upload_status:
          type: string
          description: >-
            Optional media upload status included on media-state conflict
            responses
        message:
          type: string
          description: Human-readable error message
        details:
          type: string
          description: Additional error details when available
      example:
        error: invalid_input
        message: video_id is required
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: >
        API key for authentication. Obtain from your team admin.


        Example: `X-API-Key:
        vsk_abc123def456ghi789jkl012mno345pqr678stu901vwx234yz`

````