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

# Create clipping

> Submit a video for AI clipping. By default the AI auto-detects the most viral clips. Set query to switch to Find Moments mode: describe the moments you want in natural language (e.g. "funny reactions") and the AI extracts matching clips instead — targetDuration is ignored in that mode. Cost is charged per started minute of the source video either way.



## OpenAPI

````yaml POST /clippings/create
openapi: 3.1.0
info:
  title: Unsora API
  version: 1.2.0
  description: >-
    Public API for Unsora integrations. Authenticate with Clerk JWT or
    uns_live_* API key. API keys are rate-limited to 60 requests/minute and
    support idempotency keys. Async jobs complete via polling GET
    /image/status/{id}.
servers:
  - url: https://mvp.tryunsora.com/api/v1
    description: Versioned API (recommended)
security: []
tags:
  - name: Clippings
  - name: Connect
  - name: Image Generations
  - name: Music Generations
  - name: Influencer Studio
  - name: Posts
  - name: Thumbnails
  - name: User
  - name: Video Generations
paths:
  /clippings/create:
    post:
      tags:
        - Clippings
      summary: Create AI clipping job
      description: >-
        Submit a video for AI clipping. By default the AI auto-detects the most
        viral clips. Set query to switch to Find Moments mode: describe the
        moments you want in natural language (e.g. "funny reactions") and the AI
        extracts matching clips instead — targetDuration is ignored in that
        mode. Cost is charged per started minute of the source video either way.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                videoUrl:
                  type: string
                  description: >-
                    Public URL of the source video (YouTube link or direct video
                    URL).
                  example: https://www.youtube.com/watch?v=dQw4w9WgXcQ
                sourceLang:
                  type: string
                  nullable: true
                  description: >-
                    Source language code of the video (e.g. en, es). Omit or
                    null to auto-detect.
                targetLang:
                  type: string
                  nullable: true
                  description: >-
                    Target language for clip titles, descriptions, and captions.
                    Omit or null to keep the source language.
                targetDuration:
                  type: string
                  description: >-
                    Desired length range for each clip. Defaults to auto (up to
                    90s).
                  enum:
                    - auto
                    - lt30
                    - 30-60
                    - 60-90
                    - 90-3min
                    - gt3min
                  default: auto
                query:
                  type: string
                  maxLength: 500
                  nullable: true
                  description: >-
                    Find Moments mode: natural-language description of the
                    moments to extract (e.g. "funny reactions", "product demos",
                    "goal moments and key plays"). When set, targetDuration is
                    ignored. Omit to auto-detect the most viral clips.
                  example: funny reactions
                limit:
                  type: integer
                  minimum: 1
                  maximum: 20
                  nullable: true
                  description: >-
                    Maximum number of clips to return, ranked by virality score
                    (highest first). Omit to return all viral-worthy clips.
                ratio:
                  type: string
                  enum:
                    - '9:16'
                    - '1:1'
                    - '4:5'
                    - '16:9'
                    - original
                  default: original
                  description: >-
                    Output aspect ratio. AI reframe keeps the main subject
                    centered when cropping. Use 9:16 for TikTok/Reels/Shorts,
                    1:1 or 4:5 for feed posts, 16:9 for YouTube. Omit or use
                    original to keep the source ratio.
                enableCaption:
                  type: boolean
                  default: false
                  description: Burn animated captions into the exported clips.
                captionStyle:
                  type: string
                  description: >-
                    Caption style preset, named by look — the color is the
                    accent on the spoken word. glow-* styles add a soft glow,
                    static-* styles don't animate, gaming-* are bold streamer
                    styles, white-card/black-box place text on a card. Only used
                    when enableCaption is true. Defaults to classic-yellow.
                  enum:
                    - classic-yellow
                    - white-card
                    - black-box
                    - bold-white
                    - white-underline
                    - playful-green
                    - sketch-blue
                    - bubble-blue
                    - bubble-green
                    - glow-yellow
                    - duo-green
                    - duo-purple
                    - elegant-purple
                    - neon-cyan
                    - glow-pink
                    - bold-yellow
                    - soft-orange
                    - glow-green
                    - glow-orange
                    - retro-outline
                    - mint-bubble
                    - comic-duo
                    - static-outline
                    - static-comic
                    - static-minimal
                    - static-green
                    - static-yellow
                    - static-orange
                    - gaming-magenta
                    - gaming-green
                    - gaming-yellow
                    - gaming-white
                    - gaming-purple-box
                    - gaming-cyan
                    - gaming-orange-box
                  default: classic-yellow
              required:
                - videoUrl
      responses:
        '201':
          description: >-
            Job queued. Clips render asynchronously — poll GET
            /clippings/status/{clippingId} until status is COMPLETED.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClippingCreateResponse'
              example:
                success: true
                data:
                  id: cmcl0x2ab0001abcd1234efgh
                  status: QUEUED
                  videoUrl: https://www.youtube.com/watch?v=dQw4w9WgXcQ
                  config:
                    sourceLang: null
                    targetLang: null
                    targetDuration: DURATION_30_60
                    limit: 5
                    enableCaption: true
                    captionStyle: temp-7
                    ratio: RATIO_9_16
                  createdAt: '2026-06-10T12:00:00.000Z'
                  clips: []
                  creditsUsed: 40
                creditsDeducted: 40
                creditsRemaining: 960
        '400':
          description: >-
            Invalid input (bad videoUrl, targetDuration, limit, ratio, or
            captionStyle), or video length could not be determined.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error: Invalid ratio. Use 9:16, 1:1, 4:5, 16:9, or original
        '402':
          description: >-
            Insufficient credits. Cost is charged per started minute of the
            source video.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error: Insufficient credits. Need 40, have 10
                creditsRemaining: 10
      security:
        - bearerAuth: []
components:
  schemas:
    ClippingCreateResponse:
      type: object
      properties:
        success:
          type: boolean
        data:
          $ref: '#/components/schemas/ClippingJob'
        creditsDeducted:
          type: integer
        creditsRemaining:
          type: integer
      required:
        - success
        - data
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
        error:
          type: string
        code:
          type: string
        message:
          type: string
      required:
        - error
    ClippingJob:
      type: object
      additionalProperties: true
      properties:
        id:
          type: string
        status:
          type: string
          enum:
            - QUEUED
            - PROCESSING
            - COMPLETED
            - FAILED
        videoUrl:
          type: string
        error:
          anyOf:
            - type: string
            - type: 'null'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        clips:
          type: array
          items:
            $ref: '#/components/schemas/ClippingClip'
        config:
          $ref: '#/components/schemas/ClippingConfig'
        creditsUsed:
          type: integer
      required:
        - id
        - status
    ClippingClip:
      type: object
      additionalProperties: true
      properties:
        id:
          type: string
        order:
          type: integer
          description: Clip index, ranked by virality (0 = highest).
        title:
          type: string
          description: AI-generated clip title.
        startTime:
          type: number
          description: Start offset in the source video, seconds.
        endTime:
          type: number
          description: End offset in the source video, seconds.
        duration:
          type: number
          description: Clip length in seconds.
        status:
          type: string
        outputAsset:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Rendered clip video. Contains the downloadable url once the job
            completes.
        thumbnailAsset:
          type: object
          nullable: true
          additionalProperties: true
          description: Clip thumbnail image.
        metadata:
          type: object
          additionalProperties: true
          description: >-
            Extra AI output: tags, desc (suggested description), score
            (virality).
    ClippingConfig:
      type: object
      description: >-
        Job settings echoed back in resolved form: targetDuration as DURATION_*,
        ratio as RATIO_* (null when keeping the original ratio), captionStyle as
        the underlying template ID.
      properties:
        sourceLang:
          type: string
          nullable: true
        targetLang:
          type: string
          nullable: true
        targetDuration:
          type: string
          enum:
            - DURATION_0_30
            - DURATION_0_90
            - DURATION_30_60
            - DURATION_60_90
            - DURATION_90_180
            - DURATION_180_300
        query:
          type: string
          nullable: true
          description: >-
            Find Moments query the job was created with; null for regular
            viral-clip jobs.
        limit:
          type: integer
          nullable: true
        ratio:
          type: string
          nullable: true
          enum:
            - RATIO_9_16
            - RATIO_1_1
            - RATIO_4_5
            - RATIO_16_9
            - null
        enableCaption:
          type: boolean
        captionStyle:
          type: string
          nullable: true
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Clerk session JWT or Unsora API key (uns_live_*)

````