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

# Get Catalog

> The fixed values the create endpoints take: caption styles, visual styles, games, reactions, AI models, Cinematic options and more

## Overview

Many create fields take a value from a fixed list: a caption style, a visual style, a game, an AI model. This endpoint returns those lists, read from the same registries the create endpoints validate against. Every `id` a catalog returns is accepted where the table below says, and a value that is not in the list answers `400` with the allowed values. When Hooked adds a style or a model, it shows up here; you never have to copy a list from the docs.

Each item has an `id` (what you send) and a `name` (the label the dashboard shows), plus a few fields that depend on the catalog: a preview image for visual styles, the clips of a game, the media types and sound of a model. Catalogs your team can add to (`visual-styles` with your custom styles as `custom-<id>`, `reactions` with your own reactions) include your team's entries after the library ones, and only finished ones. The call is free and safe to repeat; caching the static catalogs on your side for a day is fine.

| `name` | Field it feeds | Endpoints |
| - | - | - |
| `caption-presets` | `caption.preset` | Every endpoint that burns captions |
| `text-styles` | `textSettings.preset` | Hook Demo |
| `visual-styles` | `presetSettings.preset`, `presetId`, `style` | Narrated formats with `ai-images` / `ai-videos`, Cinematic, Generate Image |
| `motion-styles` | `presetSettings.motionStyleId` | `motion-graphics` media type |
| `games` | `gameplaySettings.selectedGame`, and `selectedVideo` from its `clips` | `gameplay` media type |
| `reactions` | `avatarId` | Hook Demo |
| `video-models` | `presetSettings.aiModel`, `model` | `ai-videos` media type, [Generate Video](/api-reference/media/generate-video) (`durations`, `resolutions`, `aspectRatios`, `startFrame`, `endFrame`, `maxReferenceImages` and `makesSound` say what each model takes) |
| `image-models` | `presetSettings.aiModel`, `model` | `ai-images` media type, [Generate Image](/api-reference/media/generate-image) (`maxReferenceImages`) |
| `cinematic` | `model`, `imageModel`, `storyTone`, `presetId`, `durationSeconds`, `characterIds`, `language`, `aspectRatio` | Cinematic (one item per field) |
| `camera-moves` | `videoStyle.cameras` | Talking Avatar, UGC Studio (`ugcStudioFormats` says which formats allow each move) |
| `gestures` | `videoStyle.gestures` (send the `id`: the library's own words) | Talking Avatar, UGC Studio |
| `voice-presets` | `videoStyle.voice`, `hostVoice` | Talking Avatar, UGC Studio, Podcast Interview |
| `accents` | `videoStyle.accent`, `accent` | Talking Avatar, UGC Studio, Podcast Interview |

Avatars, voices, music, your media and your Cinematic characters have their own list endpoints: [List Avatars](/api-reference/avatar/list), [List Voices](/api-reference/voice/list), [List Music](/api-reference/music/list), [List Media](/api-reference/media/list) and [List Characters](/api-reference/character/list).

### The `cinematic` catalog

`cinematic` has one item per field of [Create Cinematic Video](/api-reference/video/cinematic) that takes a fixed value. An item has the accepted `values` (each model with its `durations`, `resolutions` and `aspectRatios`), or `min` / `max` bounds, and the `default` used when you leave the field out. The `presetId` item lists the photorealistic styles together with the models that refuse them (`excludedModels`); any other visual style works with every model.

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.hooked.so/v1/catalog/caption-presets" \
    -H "x-api-key: your_api_key_here"
  ```

  ```javascript JavaScript theme={null}
  async function getCatalog(name) {
    const response = await fetch(`https://api.hooked.so/v1/catalog/${name}`, {
      headers: { "x-api-key": process.env.HOOKED_API_KEY },
    });
    const { data } = await response.json();
    return data.items;
  }

  const styles = await getCatalog("visual-styles");
  console.log(styles.map((style) => `${style.id}: ${style.name}`));
  ```

  ```python Python theme={null}
  import os
  import requests

  def get_catalog(name):
      response = requests.get(
          f"https://api.hooked.so/v1/catalog/{name}",
          headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
      )
      return response.json()["data"]["items"]

  games = get_catalog("games")
  print([(game["id"], [clip["id"] for clip in game["clips"]]) for game in games])
  ```
</RequestExample>

<ResponseExample>
  ```json caption-presets theme={null}
  {
    "success": true,
    "data": {
      "items": [
        { "id": "default", "name": "Default" },
        { "id": "beast", "name": "Beast" },
        { "id": "tiktok", "name": "TikTok" },
        { "id": "wrap1", "name": "Wrap1" }
      ]
    }
  }
  ```

  ```json visual-styles theme={null}
  {
    "success": true,
    "data": {
      "items": [
        {
          "id": "pixar",
          "name": "Pixar",
          "description": "3D animated style inspired by Pixar with smooth rendering and expressive characters",
          "previewImageUrl": "https://assets.hooked.so/presets/pixar/1.webp",
          "source": "library"
        },
        {
          "id": "custom-cm4xb7c8d0001ef23gh45ij67",
          "name": "Our brand look",
          "description": null,
          "previewImageUrl": "https://files.hooked.so/team/public/brand-look--fid--4e5f.webp",
          "source": "custom"
        }
      ]
    }
  }
  ```

  ```json cinematic theme={null}
  {
    "success": true,
    "data": {
      "items": [
        {
          "id": "model",
          "name": "Video model",
          "values": [
            { "id": "veo_3_fast", "name": "Veo 3.1 Fast", "durations": [4, 6, 8], "resolutions": ["720p", "1080p"], "aspectRatios": ["ratio_9_16", "ratio_16_9"] },
            { "id": "gemini_omni_flash", "name": "Gemini Omni Flash", "durations": [4, 6, 8, 10], "resolutions": ["720p"], "aspectRatios": ["ratio_9_16", "ratio_16_9"] }
          ]
        },
        {
          "id": "storyTone",
          "name": "Story tone",
          "default": "drama",
          "values": [
            { "id": "drama", "name": "Drama", "description": "Emotionally charged scenes with high personal stakes. Slower pacing, meaningful pauses, weighty dialogue." },
            { "id": "comedy", "name": "Comedy", "description": "Light and funny. Quick pacing, punchlines, exaggerated reactions, situational humor and tight jokes." }
          ]
        },
        {
          "id": "presetId",
          "name": "Visual style",
          "default": "realistic",
          "description": "Any id of GET /v1/catalog/visual-styles (your own custom-<id> included). Photorealistic styles can't be filmed with every model: excludedModels lists the ones they refuse.",
          "values": [
            { "id": "realistic", "excludedModels": ["seedance_2_0", "seedance_2_0_fast", "seedance_2_0_mini"] }
          ]
        },
        { "id": "durationSeconds", "name": "Duration (seconds)", "min": 10, "max": 120, "default": 30 },
        { "id": "characterIds", "name": "Characters", "description": "Ids of GET /v1/character/list.", "max": 6 }
      ]
    }
  }
  ```

  ```json 404 theme={null}
  {
    "success": false,
    "message": "Catalog \"fonts\" not found. Valid names are: caption-presets, text-styles, visual-styles, motion-styles, games, reactions, video-models, image-models, cinematic, camera-moves, gestures, voice-presets, accents"
  }
  ```
</ResponseExample>

## Errors

| Status | When |
| - | - |
| 401 | Missing or invalid API key (`code: "not_authenticated"`) |
| 403 | The team does not have the Hooked app product (`code: "entitlement_required"`) |
| 404 | Unknown catalog name (the message lists the valid ones), or `cinematic` on a platform without Cinematic videos (`code: "feature_not_available"`) |


## OpenAPI

````yaml GET /v1/catalog/{name}
openapi: 3.0.0
info:
  title: Hooked API
  version: 1.0.0
  description: AI Video Generation API
servers:
  - url: https://api.hooked.so
security:
  - ApiKeyAuth: []
tags:
  - name: Videos
    description: Create projects, follow them and render videos
  - name: Account Analysis
    description: Analyze TikTok and YouTube accounts
  - name: Channels
    description: Connected social accounts you publish to
  - name: Publish
    description: Schedule videos to your connected accounts
  - name: Images
    description: 'Image editing: background removal and expansion'
  - name: Media
    description: 'Your media library: list, import from a URL, upload a file'
  - name: Avatars
    description: Your team's own avatars (Actors) and their Hook + Demo reactions
paths:
  /v1/catalog/{name}:
    get:
      tags: []
      summary: Get Catalog
      description: >
        The values a create endpoint takes from a fixed list, read from the same
        registries the endpoint validates against: every `id` listed is
        accepted, and a value missing from the list is refused with a 400.
        Team-scoped where your team can add its own (custom visual styles,
        reactions). Free and safe to call as often as you like.


        | `name` | Field it feeds | Endpoints |

        |---|---|---|

        | `caption-presets` | `caption.preset` | every endpoint that burns
        captions |

        | `text-styles` | `textSettings.preset` | Hook Demo |

        | `visual-styles` | `presetSettings.preset`, `presetId` | narrated
        formats with `ai-images` / `ai-videos`, Cinematic. Includes your team's
        own styles as `custom-<id>` |

        | `motion-styles` | `presetSettings.motionStyleId` | `motion-graphics`
        media type |

        | `games` | `gameplaySettings.selectedGame` (+ `selectedVideo` from
        `clips`) | `gameplay` media type |

        | `reactions` | `avatarId` | Hook Demo. Includes your team's own
        reactions |

        | `video-models` | `presetSettings.aiModel` | `ai-videos` media type |

        | `image-models` | `presetSettings.aiModel` | `ai-images` media type |

        | `cinematic` | `model`, `imageModel`, `storyTone`, `presetId`,
        `durationSeconds`, `characterIds`, `language`, `aspectRatio` | Cinematic
        (one item per field) |

        | `camera-moves` | `videoStyle.cameras` | Talking Avatar, UGC Studio
        (`ugcStudioFormats` says where each is allowed) |

        | `gestures` | `videoStyle.gestures` (send the `id`, the library's own
        words) | Talking Avatar, UGC Studio |

        | `voice-presets` | `videoStyle.voice`, `hostVoice` | Talking Avatar,
        UGC Studio, Podcast Interview |

        | `accents` | `videoStyle.accent`, `accent` | Talking Avatar, UGC
        Studio, Podcast Interview |
      operationId: getCatalog
      parameters:
        - name: name
          in: path
          required: true
          description: Which catalog.
          schema:
            type: string
            enum:
              - caption-presets
              - text-styles
              - visual-styles
              - motion-styles
              - games
              - reactions
              - video-models
              - image-models
              - cinematic
              - camera-moves
              - gestures
              - voice-presets
              - accents
      responses:
        '200':
          description: The catalog
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    required:
                      - items
                    properties:
                      items:
                        type: array
                        items:
                          $ref: '#/components/schemas/CatalogItem'
              example:
                success: true
                data:
                  items:
                    - id: default
                      name: Default
                    - id: beast
                      name: Beast
                    - id: tiktok
                      name: TikTok
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/EntitlementRequired'
        '404':
          description: >-
            Unknown catalog name (the message lists the valid ones), or
            `cinematic` where Cinematic is not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound404'
              example:
                success: false
                message: >-
                  Catalog "fonts" not found. Valid names are: caption-presets,
                  text-styles, visual-styles, motion-styles, games, reactions,
                  video-models, image-models, cinematic, camera-moves, gestures,
                  voice-presets, accents
        '429':
          $ref: '#/components/responses/RateLimited429'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    CatalogItem:
      type: object
      description: >-
        One value a create endpoint accepts. `id` is what you send; `name` is
        the label the dashboard shows. The other fields depend on the catalog.
      required:
        - id
        - name
      properties:
        id:
          type: string
          description: The value to send in the field the catalog feeds.
        name:
          type: string
          description: Human-readable name, as the dashboard shows it.
        description:
          type: string
          nullable: true
          description: Short description, when the catalog has one.
        source:
          type: string
          enum:
            - library
            - custom
          description: >-
            `visual-styles` and `reactions`: a Hooked library entry or one your
            team made.
        previewImageUrl:
          type: string
          nullable: true
          description: '`visual-styles`: a sample image of the style.'
        thumbnailUrl:
          type: string
          nullable: true
          description: '`reactions`: a still of the reaction.'
        videoUrl:
          type: string
          nullable: true
          description: '`reactions`: the reaction clip.'
        reaction:
          type: string
          nullable: true
          description: '`reactions`: the expression, e.g. `surprise`.'
        clips:
          type: array
          description: >-
            `games`: the clips of the game; pass one `id` as
            `gameplaySettings.selectedVideo`. Empty for `custom`, which takes a
            video of your media library.
          items:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
              thumbnailUrl:
                type: string
                nullable: true
        mediaTypes:
          type: array
          items:
            type: string
            enum:
              - ai-images
              - ai-videos
          description: >-
            `video-models` / `image-models`: the `mediaType` the model can be
            used with.
        quality:
          type: string
          nullable: true
          enum:
            - base
            - pro
            - ultra
          description: >-
            `video-models` / `image-models`: the quality tier the model belongs
            to.
        makesSound:
          type: boolean
          description: >-
            `video-models`: the model generates audio with the clip (needed for
            a speaking cast).
        durations:
          type: array
          items:
            type: number
          description: '`video-models`: clip lengths, in seconds, the model generates.'
        resolutions:
          type: array
          items:
            type: string
          description: '`video-models`: resolutions the model generates.'
        aspectRatios:
          type: array
          items:
            type: string
          description: '`video-models`: aspect ratios the model films.'
        maxReferenceImages:
          type: integer
          description: >-
            `image-models` / `video-models`: reference images the model takes (0
            = none), for `referenceMediaIds` of Generate Image / Generate Video.
        values:
          type: array
          items:
            type: object
          description: >-
            `cinematic`: the values the field accepts (`id`, `name`, and per
            value details).
        min:
          type: number
          description: '`cinematic`: lower bound of a numeric field.'
        max:
          type: number
          description: >-
            `cinematic`: upper bound of a numeric field, or the most items of a
            list.
        default:
          description: '`cinematic`: the value used when the field is left out.'
        group:
          type: string
          description: >-
            `camera-moves`: the section of the prompt library the move belongs
            to.
        ugcStudioFormats:
          type: array
          items:
            type: string
          description: '`camera-moves`: the UGC Studio endpoints that allow the move.'
        language:
          type: string
          description: >-
            `accents`: the language the accent speaks (`en`, `es`). An accent is
            only applied to a video in that language.
        defaultDuration:
          type: number
          description: >-
            `video-models`: the clip length used when `durationSeconds` is left
            out.
        defaultResolution:
          type: string
          nullable: true
          description: >-
            `video-models`: the resolution used when none is sent; null when the
            model has no choice.
        startFrame:
          type: boolean
          description: >-
            `video-models`: the model animates a start image (Generate Video
            `imageMediaId` / `imageUrl`).
        endFrame:
          type: boolean
          description: '`video-models`: the model takes an end image (`endImageMediaId`).'
    NotFound404:
      type: object
      description: >-
        Not found. Another team's resource answers the same way as a missing
        one.
      properties:
        success:
          type: boolean
          enum:
            - false
        message:
          type: string
      required:
        - success
        - message
      example:
        success: false
        message: Project not found
    Error401:
      type: object
      description: Missing or invalid `x-api-key`.
      properties:
        code:
          type: string
          enum:
            - not_authenticated
        message:
          type: string
          example: Not authenticated
        errorCode:
          type: string
          enum:
            - NOT_AUTHENTICATED
        details:
          type: object
          additionalProperties:
            type: string
      example:
        code: not_authenticated
        message: Not authenticated
        errorCode: NOT_AUTHENTICATED
        details:
          x-api-key: Header not provided or API Key invalid
    EntitlementRequired403:
      type: object
      description: >-
        Valid key, but the team does not have the product this endpoint belongs
        to.
      properties:
        code:
          type: string
          enum:
            - entitlement_required
        error:
          type: string
          enum:
            - entitlement_required
        message:
          type: string
        product:
          type: string
          example: app
      required:
        - code
        - error
        - message
        - product
      example:
        code: entitlement_required
        error: entitlement_required
        message: This endpoint requires the "app" product.
        product: app
    Error500:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
        message:
          type: string
        error:
          type: string
          description: Present on some endpoints
      example:
        success: false
        message: Internal server error
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error401'
    EntitlementRequired:
      description: The team does not have the product this endpoint needs
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EntitlementRequired403'
    RateLimited429:
      description: >-
        Your team is over a rate limit: 30 POST requests per minute, 120 other
        requests per minute, or 3 downloads of your URLs running at once.
        Nothing ran and nothing was charged: wait `Retry-After` seconds and send
        the request again. See [Rate
        limits](/guides/error-handling#rate-limits-429).
      headers:
        Retry-After:
          description: Seconds to wait before sending again.
          schema:
            type: integer
        X-RateLimit-Limit:
          description: The limit of the bucket you hit (not sent for the download cap).
          schema:
            type: integer
        X-RateLimit-Remaining:
          description: 'Requests left in this window: 0 (not sent for the download cap).'
          schema:
            type: integer
        X-RateLimit-Reset:
          description: >-
            When the window ends, in Unix seconds (not sent for the download
            cap).
          schema:
            type: integer
      content:
        application/json:
          schema:
            type: object
            properties:
              success:
                type: boolean
                enum:
                  - false
              errorCode:
                type: string
                enum:
                  - RATE_LIMITED
              message:
                type: string
              retryAfterSeconds:
                type: integer
            required:
              - success
              - errorCode
              - message
              - retryAfterSeconds
          example:
            success: false
            errorCode: RATE_LIMITED
            message: >-
              Rate limit exceeded: 30 POST requests per minute per team. Retry
              after 12 s.
            retryAfterSeconds: 12
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error500'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.