# Transloadit

> Transloadit is a versatile file uploading and processing API that allows developers to create complex media processing workflows through declarative JSON recipes called Assembly Instructions.

## Uploading and importing (INPUT)

Transloadit handles file uploads over XHR or tus.io (our open source protocol for resumable file uploads) and can process files through various "Robots" (specialized processing steps) that can be chained together to create customized workflows.

## Encoding workflows (PROCESS)

Assembly Instructions at a glance:

```json
{
  "steps": {
    ":original": {
      "robot": "/upload/handle"
    },
    "browser720_webm_encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "webm",
      "width": 1280,
      "height": 720
    },
    "browser720_h264_encoded": {
      "use": ":original",
      "robot": "/video/encode",
      "preset": "mp4",
      "width": 1280,
      "height": 720
    },
    "thumbed": {
      "use": "browser720_h264_encoded",
      "robot": "/video/thumbs",
      "width": 1280,
      "height": 720,
      "format": "jpg",
      "resize_strategy": "fit",
      "count": 1,
    },
    "exported": {
      "use": ["browser720_webm_encoded", "browser720_h264_encoded", "thumbed", ":original"],
      "robot": "/s3/store",
      "credentials": "demo_s3_credentials",
      "url_prefix": "https://demos.transloadit.com/"
    }
  }
}
```

As you can see, our features are called Robots, and each Step inside
the Assembly Instructions can refer one. Robots can pass files to each other
with the `use` keyword. This means you can create complex workflows
unique to your application.

## Exporting to cloud storage or downloading results (OUTPUT)

Transloadit can export to all the major cloud storage providers.
Customers first need to store their credentials in their Transloadit account and
then refer to them in the Assembly Instructions.

Alternatively, Transloadit keeping 24h of temporary storage, you can directly download
resulting files when an Assembly is finished.

All meta data is available on a unique Assembly URL which contains the Assembly Status JSON.

## Example integration code with Node.js

```js
// npm install transloadit
const { Transloadit } = require('transloadit')

const transloadit = new Transloadit({
  authKey: 'TRANSLOADIT_KEY',
  authSecret: 'TRANSLOADIT_SECRET',
})

const options = {
  files: {
    file1: '/PATH/TO/FILE.jpg',
  },
  params: {
    steps: {
      // You can have many Steps. In this case we will just resize any inputs (:original)
      ':original': {
        robot: '/upload/handle',
      },
      resize: {
        use: ':original',
        robot: '/image/resize',
        result: true,
        width: 75,
        height: 75,
      },
    },
    // OR if you already created a template, you can use it instead of "steps":
    // template_id: 'YOUR_TEMPLATE_ID',
  },
  waitForCompletion: true, // Wait for the Assembly (job) to finish executing before returning
}

const status = await transloadit.createAssembly(options)
console.log('✅ Success - Your resized image:', status?.results?.resize?.[0]?.ssl_url)
```

## SDKs

- [Uppy](https://uppy.io/): Our open source browser UI for uploading files
- [Node.js SDK](https://github.com/transloadit/node-sdk): Official Node.js integration
- [Python SDK](https://github.com/transloadit/python-sdk): Official Python integration
- [Ruby SDK](https://github.com/transloadit/ruby-sdk): Official Ruby integration
- [All SDKs](https://transloadit.com/docs/sdks/): Complete list of available SDKs

## Robots

### Available Robots

- `/audio/artwork` - extracts the embedded cover artwork from audio files and allows you to pipe it into other Steps, for example into /image/resize Steps. It can also insert images into audio files as cover artwork
- `/audio/concat` - concatenates several audio files together
- `/audio/encode` - converts audio files into all kinds of formats for you. We provide encoding presets for the most common formats
- `/audio/loop` - loops one audio file as often as is required to match a given duration
- `/audio/merge` - overlays several audio files on top of each other
- `/audio/waveform` - generates waveform images for your audio files and allows you to change their colors and dimensions
- `/azure/import` - imports whole directories of files from your Azure container
- `/azure/store` - exports encoding results to Microsoft Azure
- `/backblaze/import` - imports whole directories of files from your Backblaze bucket
- `/backblaze/store` - exports encoding results to Backblaze
- `/cloudfiles/import` - imports whole directories of files from your Rackspace Cloud Files container
- `/cloudfiles/store` - exports encoding results to Rackspace Cloud Files
- `/cloudflare/import` - imports whole directories of files from your cloudflare r2 bucket
- `/cloudflare/store` - exports encoding results to cloudflare r2 buckets
- `/digitalocean/import` - imports whole directories of files from DigitalOcean Spaces
- `/digitalocean/store` - exports encoding results to DigitalOcean Spaces
- `/document/autorotate` - corrects the orientation of documents
- `/document/convert` - converts documents into different formats
- `/document/merge` - concatenates several PDF documents into a single file
- `/document/ocr` - recognizes text in documents and returns it in a machine-readable format
- `/document/split` - extracts pages from documents
- `/document/thumbs` - generates an image for each page in a PDF file or an animated GIF file that loops through all pages
- `/dropbox/import` - imports whole directories of files from your Dropbox
- `/dropbox/store` - exports encoding results to Dropbox
- `/edgly/deliver` - caches and delivers files globally
- `/file/compress` - creates archives of files or file conversion results
- `/file/decompress` - extracts entire archives of files to be consumed by other Robots or exported as individual files
- `/file/filter` - directs files to different encoding Steps based on your conditions
- `/file/hash` - hashes files in Assemblies
- `/file/preview` - generates a thumbnail for any uploaded file to preview its content, similar to the thumbnails in desktop file managers
- `/file/read` - reads file contents from supported file-types
- `/file/serve` - serves files to web browsers
- `/file/verify` - verifies your files are the type that you want
- `/file/virusscan` - rejects millions of trojans, viruses, malware & other malicious threats before they reach your platform
- `/ftp/import` - imports whole libraries of files from your FTP servers into Transloadit. This Robot relies on password access. For more security, consider our /sftp/import Robot
- `/ftp/store` - exports encoding results to your FTP servers. This Robot relies on password access. For more security, consider our /sftp/store Robot
- `/google/import` - imports whole directories of files from Google Storage
- `/google/store` - exports encoding results to Google Storage
- `/html/convert` - takes screenshots of web pages or uploaded HTML pages
- `/http/import` - imports any file that is publicly available via a web URL into Transloadit
- `/image/describe` - recognizes objects in images and returns them as English words
- `/image/facedetect` - detects faces in images and can return either their coordinates or the faces themselves as new images
- `/image/merge` - merges several images into a single spritesheet
- `/image/ocr` - recognizes text in images and returns it in a machine-readable format
- `/image/optimize` - reduces the size of images while maintaining the same visual quality
- `/image/resize` - resizes, crops, changes colorization, rotation, and applies text and watermarks to images
- `/meta/write` - writes metadata into files
- `/minio/import` - imports whole directories of files from your MinIO bucket
- `/minio/store` - exports encoding results to MinIO buckets
- `/s3/import` - imports whole directories of files from your S3 bucket
- `/s3/store` - exports encoding results to Amazon S3
- `/script/run` - runs scripts in Assemblies
- `/sftp/import` - imports whole libraries of files from your SFTP servers into Transloadit. This Robot relies on public key authentication
- `/sftp/store` - exports encoding results to your own SFTP server
- `/speech/transcribe` - transcribes speech in audio or video files
- `/supabase/import` - imports whole directories of files from your Supabase bucket
- `/supabase/store` - exports encoding results to supabase buckets
- `/swift/import` - imports whole directories of files from your Openstack/Swift bucket
- `/swift/store` - exports encoding results to OpenStack Swift buckets
- `/text/speak` - synthesizes speech in documents
- `/text/translate` - translates text in documents
- `/tigris/import` - imports whole directories of files from your Tigris bucket
- `/tigris/store` - exports encoding results to Tigris buckets
- `/tlcdn/deliver` - caches and delivers files globally
- `/tus/store` - exports encoding results to any Tus-compatible server
- `/upload/handle` - receives uploads that your users throw at you from browser or apps, or that you throw at us programmatically
- `/video/adaptive` - encodes videos into HTTP Live Streaming (HLS) and MPEG-Dash supported formats and generates the necessary manifest and playlist files
- `/video/concat` - concatenates several videos together
- `/video/encode` - encodes, resizes, applies watermarks to videos and animated GIFs
- `/video/merge` - composes a new video by adding an audio track to existing still image(s) or video
- `/video/subtitle` - adds subtitles and closed captions to videos
- `/video/thumbs` - extracts any number of images from videos for use as previews
- `/vimeo/store` - exports encoding results to vimeo
- `/wasabi/import` - imports whole directories of files from your wasabi bucket
- `/wasabi/store` - exports encoding results to Wasabi buckets
- `/youtube/store` - exports encoding results to YouTube

### Robot Parameter Schemas

#### Common Schemas

These schema definitions are shared across multiple robots:

```ts
const FfmpegSchema = z.object({
  ffmpeg: z
    .object({
      af: z.string().optional(),
      'b:a': z.union([z.string(), z.number()]).optional(),
      'b:v': z.union([z.string(), z.number()]).optional(),
      'c:a': z.string().optional(),
      'c:v': z.string().optional(),
      'codec:a': z.string().optional(),
      'codec:v': z.string().optional(),
      'filter:v': z.string().optional(),
      'filter:a': z.string().optional(),
      bits_per_mb: z.union([z.string(), z.number()]).optional(),
      ss: z.union([z.string(), z.number()]).optional(),
      t: z.union([z.string(), z.number()]).optional(),
      to: z.union([z.string(), z.number()]).optional(),
      vendor: z.string().optional(),
      shortest: z.union([z.boolean(), z.null()]).optional(),
      filter_complex: z.union([z.string(), z.record(z.string())]).optional(),
      'level:v': z.union([z.string(), z.number()]).optional(),
      'profile:v': z
        .union([z.number(), z.enum(['baseline', 'main', 'high'])])
        .optional(),
      'qscale:a': z.number().optional(),
      'qscale:v': z.number().optional(),
      'x264-params': z.string().optional(),
      'overshoot-pct': z.number().optional(),
      deadline: z.string().optional(),
      'cpu-used': z.string().optional(),
      'undershoot-pct': z.number().optional(),
      'row-mt': z.number().optional(),
      'x265-params': z
        .object({
          'vbv-maxrate': z.number().optional(),
          'vbv-bufsize': z.number().optional(),
          'rc-lookahead': z.number().optional(),
          'b-adapt': z.number().optional(),
        })
        .strict()
        .optional(),
      ac: z
        .union([
          z.number(),
          z.string().regex(new RegExp('^[\\d.]*\\${.+}[\\d.]*$')),
        ])
        .optional(),
      an: z.boolean().optional(),
      ar: z.union([z.number(), z.any()]).optional(),
      async: z.number().optional(),
      b: z
        .union([
          z
            .object({ v: z.number().optional(), a: z.number().optional() })
            .strict(),
          z.string(),
        ])
        .optional(),
      bt: z.union([z.number(), z.string()]).optional(),
      bufsize: z.union([z.string(), z.number()]).optional(),
      c: z.string().optional(),
      codec: z
        .object({ v: z.string().optional(), a: z.string().optional() })
        .strict()
        .optional(),
      coder: z.number().optional(),
      crf: z.number().optional(),
      f: z.string().optional(),
      flags: z.string().optional(),
      g: z.number().optional(),
      i_qfactor: z.union([z.string(), z.number()]).optional(),
      keyint_min: z.number().optional(),
      level: z.union([z.string(), z.number()]).optional(),
      map: z.union([z.string(), z.array(z.string())]).optional(),
      maxrate: z.union([z.string(), z.number()]).optional(),
      me_range: z.number().optional(),
      movflags: z.string().optional(),
      partitions: z.string().optional(),
      pix_fmt: z.string().optional(),
      preset: z.string().optional(),
      profile: z.string().optional(),
      'q:a': z.number().optional(),
      qcomp: z.union([z.string(), z.number()]).optional(),
      qdiff: z.number().optional(),
      qmax: z.number().optional(),
      qmin: z.number().optional(),
      r: z.union([z.number(), z.any()]).optional(),
      rc_eq: z.string().optional(),
      refs: z.number().optional(),
      s: z.string().optional(),
      sc_threshold: z.number().optional(),
      sws_flags: z.string().optional(),
      threads: z.number().optional(),
      trellis: z.number().optional(),
      transloaditffpreset: z.literal('empty').optional(),
      vn: z.boolean().optional(),
      vf: z.string().optional(),
      x264opts: z.string().optional(),
      vbr: z.union([z.string(), z.number()]).optional(),
    })
    .catchall(z.any())
    .describe(
      '\nA parameter object to be passed to FFmpeg. If a preset is used, the options specified are merged on top of the ones from the preset. For available options, see the [FFmpeg documentation](https://ffmpeg.org/ffmpeg-doc.html). Options specified here take precedence over the preset options.\n',
    ),
})


const UseSchema = z.object({
  use: z
    .union([
      z.union([
        z.string(),
        z.array(z.any()),
        z.array(
          z
            .object({
              name: z.string(),
              fields: z.string().optional(),
              as: z.string().optional(),
            })
            .strict(),
        ),
      ]),
      z
        .object({
          steps: z.any(),
          bundle_steps: z.boolean().optional(),
          group_by_original: z.boolean().optional(),
        })
        .strict(),
    ])
    .describe(
      '\nSpecifies which Step(s) to use as input.\n\n- You can pick any names for Steps except `":original"` (reserved for user uploads handled by Transloadit)\n- You can provide several Steps as input with arrays:\n  ```json\n  {\n    "use": [\n      ":original",\n      "encoded",\n      "resized"\n    ]\n  }\n  ```\n\n💡That’s likely all you need to know about `use`, but you can view [Advanced use cases](https://transloadit.com/docs/topics/use-parameter/).\n',
    ),
})


const FfmpegStackSchema = z.object({
  ffmpeg_stack: z
    .union([
      z.enum(['v5', 'v6']),
      z.string().regex(new RegExp('^v?[56](\\.\\d+)?(\\.\\d+)?$')),
    ])
    .describe(
      '\nSelects the FFmpeg stack version to use for encoding. These versions reflect real FFmpeg versions. We currently recommend to use "v6.0.0".\n',
    )
    .default('v5.0.0'),
})


const ResultSchema = z.object({
  result: z
    .boolean()
    .describe(
      'Whether the results of this Step should be present in the Assembly Status JSON',
    )
    .default(false),
})


const OutputMetaSchema = z.object({
  output_meta: z
    .union([z.record(z.boolean()), z.boolean()])
    .describe(
      '\nAllows you to specify a set of metadata that is more expensive on CPU power to calculate, and thus is disabled by default to keep your Assemblies processing fast.\n\nFor images, you can add `"has_transparency": true` in this object to extract if the image contains transparent parts and `"dominant_colors": true` to extract an array of hexadecimal color codes from the image.\n\nFor videos, you can add the `"colorspace: true"` parameter to extract the colorspace of the output video.\n\nFor audio, you can add `"mean_volume": true` to get a single value representing the mean average volume of the audio file.\n\nYou can also set this to `false` to skip metadata extraction and speed up transcoding.\n',
    ),
})


const IgnoreErrorsSchema = z.object({
  ignore_errors: z
    .union([z.boolean(), z.array(z.enum(['meta', 'import']))])
    .default([]),
})


const CredentialsSchema = z.object({
  credentials: z
    .string()
    .describe(
      '\nPlease create your associated <dfn>Template Credentials</dfn> in your Transloadit account and use the name of your [Template Credentials](https://transloadit.com/c/template-credentials/) as this parameter\'s value. They will contain the values for your Azure Container, Account and Key.\n\nWhile we recommend to use <dfn>Template Credentials</dfn> at all times, some use cases demand dynamic credentials for which using <dfn>Template Credentials</dfn> is too unwieldy because of their static nature. If you have this requirement, feel free to use the following parameters instead: `"account"`, `"key"`, `"container"`.\n',
    ),
})


const AudioPresetSchema = z.object({
  preset: z
    .enum([
      'aac',
      'alac',
      'audio/aac',
      'audio/alac',
      'audio/flac',
      'audio/mp3',
      'audio/ogg',
      'dash/32k-audio',
      'dash/64k-audio',
      'dash/128k-audio',
      'dash/256k-audio',
      'dash-32k-audio',
      'dash-64k-audio',
      'dash-128k-audio',
      'dash-256k-audio',
      'empty',
      'flac',
      'gif',
      'hg-transformers-audio',
      'mp3',
      'ogg',
      'opus',
      'speech',
      'wav',
    ])
    .describe(
      "\nPerforms conversion using pre-configured settings.\n\nIf you specify your own FFmpeg parameters using the <dfn>Robot</dfn>'s `ffmpeg` parameter and you have not specified a preset, then the default `mp3` preset is not applied. This is to prevent you from having to override each of the MP3 preset's values manually.\n\nFor a list of audio presets, see [audio presets](https://transloadit.com/docs/transcoding/audio-encoding/audio-presets/).\n",
    ),
})


const VideoPresetSchema = z.object({
  preset: z
    .enum([
      'android-high',
      'android-low',
      'android',
      'dash/270p-video',
      'dash/360p-video',
      'dash/480p-video',
      'dash/540p-video',
      'dash/576p-video',
      'dash/720p-video',
      'dash/1080p-video',
      'dash-270p-video',
      'dash-360p-video',
      'dash-480p-video',
      'dash-540p-video',
      'dash-576p-video',
      'dash-720p-video',
      'dash-1080p-video',
      'empty',
      'flash',
      'hevc',
      'hls/270p',
      'hls/360p',
      'hls/480p',
      'hls/540p',
      'hls/720p',
      'hls/1080p',
      'hls/4k',
      'hls-1080p',
      'hls-360p',
      'hls-480p',
      'hls-540p',
      'hls-576p',
      'hls-720p',
      'hls-270p',
      'ipad-high',
      'ipad-low',
      'ipad',
      'iphone-high',
      'iphone-low',
      'iphone',
      'ogv',
      'vp9',
      'vp9-270p',
      'vp9-360p',
      'vp9-480p',
      'vp9-540p',
      'vp9-576p',
      'vp9-720p',
      'vp9-1080p',
      'web/mp4-x265/240p',
      'web/mp4-x265/360p',
      'web/mp4-x265/480p',
      'web/mp4-x265/720p',
      'web/mp4-x265/1080p',
      'web/mp4-x265/4k',
      'web/mp4-x265/8k',
      'web/mp4/240p',
      'web/mp4/360p',
      'web/mp4/480p',
      'web/mp4/540p',
      'web/mp4/720p',
      'web/mp4/1080p',
      'web/mp4/4k',
      'web/webm/240p',
      'web/webm/360p',
      'web/webm/480p',
      'web/webm/720p',
      'web/webm/1080p',
      'web/webm/4k',
      'web/webm/8k',
      'webm-270p',
      'webm-360p',
      'webm-480p',
      'webm-540p',
      'webm-576p',
      'webm-720p',
      'webm-1080p',
      'webm',
      'wmv',
      'aac',
      'alac',
      'audio/aac',
      'audio/alac',
      'audio/flac',
      'audio/mp3',
      'audio/ogg',
      'dash/32k-audio',
      'dash/64k-audio',
      'dash/128k-audio',
      'dash/256k-audio',
      'dash-32k-audio',
      'dash-64k-audio',
      'dash-128k-audio',
      'dash-256k-audio',
      'empty',
      'flac',
      'gif',
      'hg-transformers-audio',
      'mp3',
      'ogg',
      'opus',
      'speech',
      'wav',
    ])
    .describe(
      "\nConverts a video according to [pre-configured settings](https://transloadit.com/docs/transcoding/video-encoding/video-presets/).\n\nIf you specify your own FFmpeg parameters using the <dfn>Robot</dfn>'s and/or do not not want Transloadit to set any encoding setting, starting `ffmpeg_stack: \"v6\"`,  you can use the value `'empty'` here.\n",
    ),
})

```

#### `/audio/artwork`

[/audio/artwork docs](https://transloadit.com/docs/transcoding/audio-artwork/)

Robot Parameter Zod Schema:

```ts
const audioArtworkSchema = z
  .object({
    preset: AudioPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z
      .literal('/audio/artwork')
      .describe(
        '\nFor extraction, this <dfn>Robot</dfn> uses the image format embedded within the audio file — most often, this is JPEG.\n\nIf you need the image in a different format, pipe the result of this <dfn>Robot</dfn> into [🤖/image/resize](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/).\n\nThe `method` parameter determines whether to extract or insert.\n',
      ),
    method: z
      .enum(['extract', 'insert'])
      .describe(
        '\nWhat should be done with the audio file. A value of `"extract"` means audio artwork will be extracted. A value of `"insert"` means the provided image will be inserted as audio artwork.\n',
      )
      .default('extract'),
    change_format_if_necessary: z
      .boolean()
      .describe(
        '\nWhether the original file should be transcoded into a new format if there is an issue with the original file.\n',
      )
      .default(false),
  })
  .strict()

```

#### `/audio/concat`

[/audio/concat docs](https://transloadit.com/docs/transcoding/audio-concat/)

Robot Parameter Zod Schema:

```ts
const audioConcatSchema = z
  .object({
    preset: AudioPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z
      .literal('/audio/concat')
      .describe(
        '\nThis Robot can concatenate an almost infinite number of audio files.\n',
      ),
    bitrate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nBit rate of the resulting audio file, in bits per second. If not specified will default to the bit rate of the input audio file.\n',
      )
      .optional(),
    sample_rate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nSample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.\n',
      )
      .optional(),
    audio_fade_seconds: z
      .number()
      .describe(
        '\nWhen used this adds an audio fade in and out effect between each section of your concatenated audio file. The float value is used, so if you want an audio delay effect of 500 milliseconds between each video section, you would select 0.5. Integer values can also be represented.\n\nThis parameter does not add an audio fade effect at the beginning or end of your result audio file. If you want to do so, create an additional [🤖/audio/encode](https://transloadit.com/docs/transcoding/audio-encoding/audio-encode/) <dfn>Step</dfn> and use our `ffmpeg` parameter as shown in this [demo](https://transloadit.com/demos/audio-encoding/ffmpeg-fade-in-and-out/).\n',
      )
      .default(1),
  })
  .strict()

```

#### `/audio/encode`

[/audio/encode docs](https://transloadit.com/docs/transcoding/audio-encode/)

Robot Parameter Zod Schema:

```ts
const audioEncodeSchema = z
  .object({
    preset: AudioPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z.literal('/audio/encode'),
    bitrate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nBit rate of the resulting audio file, in bits per second. If not specified will default to the bit rate of the input audio file.\n',
      )
      .optional(),
    sample_rate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nSample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/audio/loop`

[/audio/loop docs](https://transloadit.com/docs/transcoding/audio-loop/)

Robot Parameter Zod Schema:

```ts
const audioLoopSchema = z
  .object({
    preset: AudioPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z.literal('/audio/loop'),
    bitrate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nBit rate of the resulting audio file, in bits per second. If not specified will default to the bit rate of the input audio file.\n',
      )
      .optional(),
    sample_rate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nSample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.\n',
      )
      .optional(),
    duration: z
      .number()
      .describe(
        '\nTarget duration for the whole process in seconds. The <dfn>Robot</dfn> will loop the input audio file for as long as this target duration is not reached yet.\n',
      )
      .default(60),
  })
  .strict()

```

#### `/audio/merge`

[/audio/merge docs](https://transloadit.com/docs/transcoding/audio-merge/)

Robot Parameter Zod Schema:

```ts
const audioMergeSchema = z
  .object({
    preset: AudioPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z.literal('/audio/merge'),
    bitrate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nBit rate of the resulting audio file, in bits per second. If not specified will default to the bit rate of the input audio file.\n',
      )
      .optional(),
    sample_rate: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nSample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.\n',
      )
      .optional(),
    duration: z
      .enum(['first', 'longest', 'shortest'])
      .describe(
        '\nDuration of the output file compared to the duration of all merged audio files. Can be `"first"` (duration of the first input file), `"shortest"` (duration of the shortest audio file) or `"longest"` for the duration of the longest input file.\n',
      )
      .default('longest'),
    loop: z
      .boolean()
      .describe(
        '\nSpecifies if any input files that do not match the target duration should be looped to match it. Useful for audio merging where your overlay file is typically much shorter than the main audio file.\n',
      )
      .default(false),
    volume: z
      .enum(['average', 'sum'])
      .describe(
        '\nValid values are `"average"` and `"sum"` here. `"average"` means each input is scaled 1/n (n is the number of inputs) or `"sum"` which means each individual audio stays on the same volume, but since we merge tracks \'on top\' of each other, this could result in very loud output.\n',
      )
      .default('average'),
  })
  .strict()

```

#### `/audio/waveform`

[/audio/waveform docs](https://transloadit.com/docs/transcoding/audio-waveform/)

Robot Parameter Zod Schema:

```ts
const audioWaveformSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z
      .literal('/audio/waveform')
      .describe(
        '\nWe recommend that you use an [🤖/audio/encode](https://transloadit.com/docs/transcoding/audio-encoding/audio-encode/) <dfn>Step</dfn> prior to your waveform <dfn>Step</dfn> to convert audio files to MP3. This way it is guaranteed that [🤖/audio/waveform](https://transloadit.com/docs/transcoding/audio-encoding/audio-waveform/) accepts your audio file and you can also down-sample large audio files and save some money.\n\nSimilarly, if you need the output image in a different format, please pipe the result of this <dfn>Robot</dfn> into [🤖/image/resize](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/).\n',
      ),
    format: z
      .enum(['image', 'json'])
      .describe(
        '\nThe format of the result file. Can be `"image"` or `"json"`. If `"image"` is supplied, a PNG image will be created, otherwise a JSON file.\n',
      )
      .default('image'),
    width: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nThe width of the resulting image if the format `"image"` was selected.\n',
      )
      .default(256),
    height: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nThe height of the resulting image if the format `"image"` was selected.\n',
      )
      .default(64),
    style: z
      .union([z.literal(0), z.literal(1)])
      .describe(
        '\nEither a value of `0` or `1`, corresponding to using either the legacy waveform tool, or the new tool respectively, with the new tool offering an improved style. Other Robot parameters still function as described, with either tool.\n',
      )
      .default(0),
    antialiasing: z
      .union([z.literal(0), z.literal(1)])
      .describe(
        '\nEither a value of `0` or `1`, corresponding to if you want to enable antialiasing to achieve smoother edges in the waveform graph or not.\n',
      )
      .default(0),
    background_color: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{8}$'))
      .describe(
        '\nThe background color of the resulting image in the "rrggbbaa" format (red, green, blue, alpha), if the format `"image"` was selected.\n',
      )
      .default('#00000000'),
    center_color: z
      .any()
      .describe(
        '\nThe color used in the center of the gradient. The format is "rrggbbaa" (red, green, blue, alpha).\n',
      )
      .default('000000ff'),
    outer_color: z
      .any()
      .describe(
        '\nThe color used in the outer parts of the gradient. The format is "rrggbbaa" (red, green, blue, alpha).\n',
      )
      .default('000000ff'),
  })
  .strict()

```

#### `/azure/import`

[/azure/import docs](https://transloadit.com/docs/transcoding/azure-import/)

Robot Parameter Zod Schema:

```ts
const azureImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    account: z.string().optional(),
    container: z.string().optional(),
    key: z.string().optional(),
    robot: z.literal('/azure/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your container to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are descendants of this directory are recursively imported. For example: `images/`.\n\nIf you want to import all files from the root directory, please use `/` as the value here.\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    next_page_token: z
      .string()
      .describe(
        '\nA string token used for pagination. The returned files of one paginated call have the next page token inside of their meta data, which needs to be used for the subsequent paging call.\n',
      )
      .default(''),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/azure/store`

[/azure/store docs](https://transloadit.com/docs/transcoding/azure-store/)

Robot Parameter Zod Schema:

```ts
const azureStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    account: z.string().optional(),
    container: z.string().optional(),
    key: z.string().optional(),
    robot: z.literal('/azure/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    content_type: z
      .string()
      .describe(
        '\nThe content type with which to store the file. By default this will be guessed by Azure.\n',
      )
      .optional(),
    content_encoding: z
      .string()
      .describe(
        '\nThe content encoding with which to store the file. By default this will be guessed by Azure.\n',
      )
      .optional(),
    content_language: z
      .string()
      .describe(
        '\nThe content language with which to store the file. By default this will be guessed by Azure.\n',
      )
      .optional(),
    cache_control: z
      .string()
      .describe('\nThe cache control header with which to store the file.\n')
      .optional(),
    metadata: z
      .record(z.string())
      .describe(
        '\nA JavaScript object containing a list of metadata to be set for this file on Azure, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default({}),
    sas_expires_in: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nSet this to a number to enable shared access signatures for your stored object. This reflects the number of seconds that the signature will be valid for once the object is stored. Enabling this will attach the shared access signature (SAS) to the result URL of your object.\n',
      )
      .optional(),
    sas_permissions: z
      .string()
      .regex(new RegExp('^[rdw]+$'))
      .min(0)
      .max(3)
      .describe(
        '\nSet this to a combination of `r` (read), `w` (write) and `d` (delete) for your shared access signatures (SAS) permissions.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/backblaze/import`

[/backblaze/import docs](https://transloadit.com/docs/transcoding/backblaze-import/)

Robot Parameter Zod Schema:

```ts
const backblazeImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    app_key_id: z.string().optional(),
    app_key: z.string().optional(),
    robot: z.literal('/backblaze/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive a 404 `BACKBLAZE_IMPORT_NOT_FOUND` error.\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `start_file_name` and `files_per_page` wisely here.\n',
      )
      .default(false),
    start_file_name: z
      .string()
      .describe(
        '\nThe name of the last file from the previous paging call. This tells the <dfn>Robot</dfn> to ignore all files up to and including this file.\n',
      )
      .default(''),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/backblaze/store`

[/backblaze/store docs](https://transloadit.com/docs/transcoding/backblaze-store/)

Robot Parameter Zod Schema:

```ts
const backblazeStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    app_key_id: z.string().optional(),
    app_key: z.string().optional(),
    robot: z.literal('/backblaze/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on backblaze, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\n[Here](https://www.backblaze.com/b2/docs/b2_upload_file.html) you can find a list of available headers.\n\nObject Metadata can be specified using `X-Bz-Info-*` headers.\n',
      )
      .default({}),
  })
  .strict()

```

#### `/cloudfiles/import`

[/cloudfiles/import docs](https://transloadit.com/docs/transcoding/cloudfiles-import/)

Robot Parameter Zod Schema:

```ts
const cloudfilesImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    account_type: z.enum(['uk', 'us']).optional(),
    data_center: z.string().optional(),
    user: z.string().optional(),
    key: z.string().optional(),
    container: z.string().optional(),
    robot: z.literal('/cloudfiles/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page`wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/cloudfiles/store`

[/cloudfiles/store docs](https://transloadit.com/docs/transcoding/cloudfiles-store/)

Robot Parameter Zod Schema:

```ts
const cloudfilesStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    account_type: z.enum(['uk', 'us']).optional(),
    data_center: z.string().optional(),
    user: z.string().optional(),
    key: z.string().optional(),
    container: z.string().optional(),
    robot: z.literal('/cloudfiles/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which to store the file. This value can also contain [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
  })
  .strict()

```

#### `/cloudflare/import`

[/cloudflare/import docs](https://transloadit.com/docs/transcoding/cloudflare-import/)

Robot Parameter Zod Schema:

```ts
const cloudflareImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/cloudflare/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subfolders and sub-subfolders, etc. of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/cloudflare/store`

[/cloudflare/store docs](https://transloadit.com/docs/transcoding/cloudflare-store/)

Robot Parameter Zod Schema:

```ts
const cloudflareStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/cloudflare/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on cloudflare Spaces, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/digitalocean/import`

[/digitalocean/import docs](https://transloadit.com/docs/transcoding/digitalocean-import/)

Robot Parameter Zod Schema:

```ts
const digitaloceanImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    space: z.string().optional(),
    region: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/digitalocean/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/digitalocean/store`

[/digitalocean/store docs](https://transloadit.com/docs/transcoding/digitalocean-store/)

Robot Parameter Zod Schema:

```ts
const digitaloceanStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    space: z.string().optional(),
    region: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/digitalocean/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    url_prefix: z
      .string()
      .describe(
        '\nThe URL prefix used for the returned URL, such as `"https://my.cdn.com/some/path"`.\n',
      )
      .default('https://{space}.{region}.digitaloceanspaces.com/'),
    acl: z
      .enum(['private', 'public-read'])
      .describe('\nThe permissions used for this file.\n')
      .default('public-read'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on DigitalOcean Spaces, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\n[Here](https://developers.digitalocean.com/documentation/spaces/#object) you can find a list of available headers.\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/document/autorotate`

[/document/autorotate docs](https://transloadit.com/docs/transcoding/document-autorotate/)

Robot Parameter Zod Schema:

```ts
const documentAutorotateSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/document/autorotate'),
  })
  .strict()

```

#### `/document/convert`

[/document/convert docs](https://transloadit.com/docs/transcoding/document-convert/)

Robot Parameter Zod Schema:

```ts
const documentConvertSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/document/convert'),
    format: z
      .enum([
        'ai',
        'csv',
        'doc',
        'docx',
        'eps',
        'gif',
        'html',
        'jpeg',
        'jpg',
        'latex',
        'oda',
        'odd',
        'odt',
        'ott',
        'pdf',
        'png',
        'pot',
        'pps',
        'ppt',
        'pptx',
        'ppz',
        'ps',
        'rtf',
        'rtx',
        'srt',
        'svg',
        'text',
        'txt',
        'vtt',
        'xhtml',
        'xla',
        'xls',
        'xlsx',
        'xml',
      ])
      .describe('\nThe desired format for document conversion.\n'),
    markdown_format: z
      .enum(['commonmark', 'gfm'])
      .describe(
        '\nMarkdown can be represented in several [variants](https://www.iana.org/assignments/markdown-variants/markdown-variants.xhtml), so when using this Robot to transform Markdown into HTML please specify which revision is being used.\n',
      )
      .default('gfm'),
    markdown_theme: z
      .enum(['bare', 'github'])
      .describe(
        '\nThis parameter overhauls your Markdown files styling based on several canned presets.\n',
      )
      .default('github'),
    pdf_margin: z
      .string()
      .describe(
        '\nPDF Paper margins, separated by `,` and with units.\n\nWe support the following unit values: `px`, `in`, `cm`, `mm`.\n\nCurrently this parameter is only supported when converting from `html`.\n',
      )
      .default('6.25mm,6.25mm,14.11mm,6.25mm'),
    pdf_print_background: z
      .boolean()
      .describe(
        '\nPrint PDF background graphics.\n\nCurrently this parameter is only supported when converting from `html`.\n',
      )
      .default(true),
    pdf_format: z
      .enum([
        'A0',
        'A1',
        'A2',
        'A3',
        'A4',
        'A5',
        'A6',
        'Ledger',
        'Legal',
        'Letter',
        'Tabloid',
      ])
      .describe(
        '\nPDF paper format.\n\nCurrently this parameter is only supported when converting from `html`.\n',
      )
      .default('Letter'),
    pdf_display_header_footer: z
      .boolean()
      .describe(
        '\nDisplay PDF header and footer.\n\nCurrently this parameter is only supported when converting from `html`.\n',
      )
      .default(false),
    pdf_header_template: z
      .string()
      .describe(
        '\nHTML template for the PDF print header.\n\nShould be valid HTML markup with following classes used to inject printing values into them:\n- `date` formatted print date\n- `title` document title\n- `url` document location\n- `pageNumber` current page number\n- `totalPages` total pages in the document\n\nCurrently this parameter is only supported when converting from `html`, and requires `pdf_display_header_footer` to be enabled.\n\nTo change the formatting of the HTML element, the `font-size` must be specified in a wrapper. For example, to center the page number at the top of a page you\'d use the following HTML for the header template:\n\n```html\n<div style="font-size: 15px; width: 100%; text-align: center;"><span class="pageNumber"></span></div>\n```\n',
      )
      .optional(),
    pdf_footer_template: z
      .string()
      .describe(
        '\nHTML template for the PDF print footer.\n\nShould use the same format as the `pdf_header_template`.\n\nCurrently this parameter is only supported when converting from `html`, and requires `pdf_display_header_footer` to be enabled.\n\nTo change the formatting of the HTML element, the `font-size` must be specified in a wrapper. For example, to center the page number in the footer you\'d use the following HTML for the footer template:\n\n```html\n<div style="font-size: 15px; width: 100%; text-align: center;"><span class="pageNumber"></span></div>\n```\n',
      )
      .optional(),
  })
  .strict()

```

#### `/document/merge`

[/document/merge docs](https://transloadit.com/docs/transcoding/document-merge/)

Robot Parameter Zod Schema:

```ts
const documentMergeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/document/merge'),
    input_passwords: z
      .array(z.string())
      .describe(
        '\nAn array of passwords for the input documents, in case they are encrypted. The order of passwords must match the order of the documents as they are passed to the /document/merge step.\n\nThis can be achieved via our as-syntax using "document_1", "document_2", etc if provided. See the demos below.\n\nIf the as-syntax is not used in the "use" parameter, the documents are sorted alphanumerically based on their filename, and in that order input passwords should be provided.\n',
      )
      .default([]),
    output_password: z
      .string()
      .describe(
        '\nIf not empty, encrypts the output file and makes it accessible only by typing in this password.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/document/ocr`

[/document/ocr docs](https://transloadit.com/docs/transcoding/document-ocr/)

Robot Parameter Zod Schema:

```ts
const documentOcrSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/document/ocr')
      .describe(
        '\nWith this <dfn>Robot</dfn>, you can detect and extract text from PDFs using optical character recognition (OCR).\n\nFor example, you can use the results to obtain the content of invoices, legal documents or restaurant menus. You can also pass the text down to other <dfn>Robots</dfn> to filter documents that contain (or do not contain) certain phrases.\n',
      ),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage. Valid values are `"aws"` and `"gcp"`.\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n\nAWS supports detection for the following languages: English, Arabic, Russian, German, French, Italian, Portuguese and Spanish. GCP allows for a wider range of languages, with varying levels of support which can be found on the [official documentation](https://cloud.google.com/vision/docs/languages/).\n',
      ),
    granularity: z
      .enum(['full', 'list'])
      .describe(
        '\nWhether to return a full response including coordinates for the text (`"full"`), or a flat list of the extracted phrases (`"list"`). This parameter has no effect if the `format` parameter is set to `"text"`.\n',
      )
      .default('full'),
    format: z
      .enum(['json', 'meta', 'text'])
      .describe(
        '\nIn what format to return the extracted text.\n- `"json"` returns a JSON file.\n- `"meta"` does not return a file, but stores the data inside Transloadit\'s file object (under `${file.meta.recognized_text}`, which is an array of strings) that\'s passed around between encoding <dfn>Steps</dfn>, so that you can use the values to burn the data into videos, filter on them, etc.\n- `"text"` returns the recognized text as a plain UTF-8 encoded text file.\n',
      )
      .default('json'),
  })
  .strict()

```

#### `/document/split`

[/document/split docs](https://transloadit.com/docs/transcoding/document-split/)

Robot Parameter Zod Schema:

```ts
const documentSplitSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/document/split'),
    pages: z
      .union([z.string(), z.array(z.string())])
      .describe(
        'The pages to select from the input PDF and to be included in the output PDF. Each entry can be a single page number (e.g. 5), or a range (e.g. `5-10`). Page numbers start at 1.',
      ),
  })
  .strict()

```

#### `/document/thumbs`

[/document/thumbs docs](https://transloadit.com/docs/transcoding/document-thumbs/)

Robot Parameter Zod Schema:

```ts
const documentThumbsSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    imagemagick_stack: z
      .union([
        z.literal('v3'),
        z.string().regex(new RegExp('^v?[23](\\.\\d+)?(\\.\\d+)?$')),
      ])
      .default('v3'),
    robot: z
      .literal('/document/thumbs')
      .describe(
        '\n## Things to keep in mind\n\n- If you convert a multi-page PDF file into several images, all result images will be sorted with the first image being the thumbnail of the first document page, etc.\n- You can also check the `meta.thumb_index` key of each result image to find out which page it corresponds to. Keep in mind that these thumb indices **start at 0,** not at 1.\n',
      ),
    page: z
      .union([z.number().int(), z.null()])
      .describe(
        '\nThe PDF page that you want to convert to an image. By default the value is `null` which means that all pages will be converted into images.\n',
      )
      .default(null),
    format: z
      .enum(['gif', 'jpeg', 'jpg', 'png'])
      .describe(
        '\nThe format of the extracted image(s).\n\nIf you specify the value `"gif"`, then an animated gif cycling through all pages is created. Please check out [this demo](https://transloadit.com/demos/document-processing/convert-all-pages-of-a-document-into-an-animated-gif/) to learn more about this.\n',
      )
      .default('png'),
    delay: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nIf your output format is `"gif"` then this parameter sets the number of 100th seconds to pass before the next frame is shown in the animation. Set this to `100` for example to allow 1 second to pass between the frames of the animated gif.\n\nIf your output format is not `"gif"`, then this parameter does not have any effect.\n',
      )
      .optional(),
    width: z
      .number()
      .int()
      .gte(1)
      .lte(5000)
      .describe(
        '\nWidth of the new image, in pixels. If not specified, will default to the width of the input image\n',
      )
      .optional(),
    height: z
      .number()
      .int()
      .gte(1)
      .lte(5000)
      .describe(
        '\nHeight of the new image, in pixels. If not specified, will default to the height of the input image\n',
      )
      .optional(),
    resize_strategy: z
      .enum(['crop', 'fillcrop', 'fit', 'min_fit', 'pad', 'stretch'])
      .describe(
        '\nOne of the [available resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
      )
      .default('pad'),
    background: z
      .string()
      .describe(
        '\nEither the hexadecimal code or [name](https://www.imagemagick.org/script/color.php#color_names) of the color used to fill the background (only used for the pad resize strategy).\n\nBy default, the background of transparent images is changed to white. For details about how to preserve transparency across all image types, see [this demo](https://transloadit.com/demos/image-manipulation/properly-preserve-transparency-across-all-image-types/).\n',
      )
      .default('#FFFFFF'),
    alpha: z
      .enum(['Remove', 'Set'])
      .describe(
        '\nChange how the alpha channel of the resulting image should work. Valid values are `"Set"` to enable transparency and `"Remove"` to remove transparency.\n\nFor a list of all valid values please check the ImageMagick documentation [here](http://www.imagemagick.org/script/command-line-options.php?#alpha).\n',
      )
      .optional(),
    density: z
      .string()
      .regex(new RegExp('\\d+(x\\d+)?'))
      .describe(
        '\nWhile in-memory quality and file format depth specifies the color resolution, the density of an image is the spatial (space) resolution of the image. That is the density (in pixels per inch) of an image and defines how far apart (or how big) the individual pixels are. It defines the size of the image in real world terms when displayed on devices or printed.\n\nYou can set this value to a specific `width` or in the format `width`x`height`.\n\nIf your converted image has a low resolution, please try using the density parameter to resolve that.\n',
      )
      .optional(),
    antialiasing: z
      .boolean()
      .describe(
        '\nControls whether or not antialiasing is used to remove jagged edges from text or images in a document.\n',
      )
      .default(false),
    colorspace: z
      .enum([
        'CMY',
        'CMYK',
        'Gray',
        'HCL',
        'HCLp',
        'HSB',
        'HSI',
        'HSL',
        'HSV',
        'HWB',
        'Jzazbz',
        'Lab',
        'LCHab',
        'LCHuv',
        'LMS',
        'Log',
        'Luv',
        'OHTA',
        'OkLab',
        'OkLCH',
        'Rec601YCbCr',
        'Rec709YCbCr',
        'RGB',
        'scRGB',
        'sRGB',
        'Transparent',
        'Undefined',
        'xyY',
        'XYZ',
        'YCbCr',
        'YCC',
        'YDbDr',
        'YIQ',
        'YPbPr',
        'YUV',
      ])
      .describe(
        '\nSets the image colorspace. For details about the available values, see the [ImageMagick documentation](https://www.imagemagick.org/script/command-line-options.php#colorspace).\n\nPlease note that if you were using `"RGB"`, we recommend using `"sRGB"`. ImageMagick might try to find the most efficient `colorspace` based on the color of an image, and default to e.g. `"Gray"`. To force colors, you might then have to use this parameter.\n',
      )
      .optional(),
    trim_whitespace: z
      .boolean()
      .describe(
        "\nThis determines if additional whitespace around the PDF should first be trimmed away before it is converted to an image. If you set this to `true` only the real PDF page contents will be shown in the image.\n\nIf you need to reflect the PDF's dimensions in your image, it is generally a good idea to set this to `false`.\n",
      )
      .default(true),
    pdf_use_cropbox: z
      .boolean()
      .describe(
        "\nSome PDF documents lie about their dimensions. For instance they'll say they are landscape, but when opened in decent Desktop readers, it's really in portrait mode. This can happen if the document has a cropbox defined. When this option is enabled (by default), the cropbox is leading in determining the dimensions of the resulting thumbnails.\n",
      )
      .default(true),
  })
  .strict()

```

#### `/dropbox/import`

[/dropbox/import docs](https://transloadit.com/docs/transcoding/dropbox-import/)

Robot Parameter Zod Schema:

```ts
const dropboxImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    space: z.string().optional(),
    region: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/dropbox/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your Dropbox to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are descendants of this directory are recursively imported. For example: `images/`.\n\nIf you want to import all files from the root directory, please use `/` as the value here.\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
  })
  .strict()

```

#### `/dropbox/store`

[/dropbox/store docs](https://transloadit.com/docs/transcoding/dropbox-store/)

Robot Parameter Zod Schema:

```ts
const dropboxStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    space: z.string().optional(),
    region: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/dropbox/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    create_sharing_link: z
      .boolean()
      .describe(
        '\nWhether to create a URL to this file for sharing with other people. This will overwrite the file\'s `"url"` property.\n',
      )
      .default(false),
  })
  .strict()

```

#### `/edgly/deliver`

[/edgly/deliver docs](https://transloadit.com/docs/transcoding/edgly-deliver/)

Robot Parameter Zod Schema:

```ts
const edglyDeliverSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    robot: z
      .literal('/edgly/deliver')
      .describe(
        '\nWhen you want Transloadit to tranform files on the fly, this <dfn>Robot</dfn> can cache and deliver the results close to your end-user, saving on latency and encoding volume. The use of this <dfn>Robot</dfn> is implicit when you use the <code>edgly.net</code> domain.\n',
      ),
  })
  .strict()

```

#### `/file/compress`

[/file/compress docs](https://transloadit.com/docs/transcoding/file-compress/)

Robot Parameter Zod Schema:

```ts
const fileCompressSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/file/compress'),
    format: z
      .enum(['tar', 'zip'])
      .describe(
        '\nThe format of the archive to be created. Supported values are `"tar"` and `"zip"`.\n\nNote that `"tar"` without setting `gzip` to `true` results in an archive that\'s not compressed in any way.\n',
      )
      .default('tar'),
    gzip: z
      .boolean()
      .describe(
        '\nDetermines if the result archive should also be gzipped. Gzip compression is only applied if you use the `"tar"` format.\n',
      )
      .default(false),
    password: z
      .union([
        z
          .string()
          .describe(
            '\nThis allows you to encrypt all archive contents with a password and thereby protect it against unauthorized use. To unzip the archive, the user will need to provide the password in a text input field prompt.\n\nThis parameter has no effect if the format parameter is anything other than `"zip"`.\n',
          )
          .default(null),
        z
          .null()
          .describe(
            '\nThis allows you to encrypt all archive contents with a password and thereby protect it against unauthorized use. To unzip the archive, the user will need to provide the password in a text input field prompt.\n\nThis parameter has no effect if the format parameter is anything other than `"zip"`.\n',
          )
          .default(null),
      ])
      .describe(
        '\nThis allows you to encrypt all archive contents with a password and thereby protect it against unauthorized use. To unzip the archive, the user will need to provide the password in a text input field prompt.\n\nThis parameter has no effect if the format parameter is anything other than `"zip"`.\n',
      )
      .default(null),
    compression_level: z
      .number()
      .int()
      .gte(-9)
      .lte(0)
      .describe(
        '\nDetermines how fiercely to try to compress the archive. `-0` is compressionless, which is suitable for media that is already compressed. `-1` is fastest with lowest compression. `-9` is slowest with the highest compression.\n\nIf you are using `-0` in combination with the `tar` format with `gzip` enabled, consider setting `gzip: false` instead. This results in a plain Tar archive, meaning it already has no compression.\n',
      )
      .default(-6),
    file_layout: z
      .enum(['advanced', 'simple'])
      .describe(
        '\nDetermines if the result archive should contain all files in one directory (value for this is `"simple"`) or in subfolders according to the explanation below (value for this is `"advanced"`).\n\nFiles with same names are numbered in the `"simple"` file layout to avoid naming collisions.\n',
      )
      .default('advanced'),
  })
  .strict()

```

#### `/file/decompress`

[/file/decompress docs](https://transloadit.com/docs/transcoding/file-decompress/)

Robot Parameter Zod Schema:

```ts
const fileDecompressSchema = z
  .object({
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/decompress')
      .describe(
        '\nThis Robot supports the following archive formats:\n\n- ZIP archives (with uncompressed or "deflate"-compressed entries)\n- 7-Zip archives\n- RAR archives\n- GNU tar format (including GNU long filenames, long link names, and sparse files)\n- Solaris 9 extended tar format (including ACLs)\n- Old V7 tar archives\n- POSIX ustar\n- POSIX pax interchange format\n- POSIX octet-oriented cpio\n- SVR4 ASCII cpio\n- POSIX octet-oriented cpio\n- Binary cpio (big-endian or little-endian)\n- ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)\n- GNU and BSD "ar" archives\n- "mtree" format\n- Microsoft CAB format\n- LHA and LZH archives\n- XAR archives\n\nThis <dfn>Robot</dfn> also detects and handles any of the following before evaluating the archive file:\n\n- uuencoded files\n- Files with RPM wrapper\n- gzip compression\n- bzip2 compression\n- compress/LZW compression\n- lzma, lzip, and xz compression\n\nFor security reasons, archives that contain symlinks to outside the archived dir, will error out the <dfn>Assembly</dfn>. Decompressing password-protected archives (encrypted archives) is currently not fully supported but will not cause an <dfn>Assembly</dfn> to fail.\n',
      ),
  })
  .strict()

```

#### `/file/filter`

[/file/filter docs](https://transloadit.com/docs/transcoding/file-filter/)

Robot Parameter Zod Schema:

```ts
const fileFilterSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/filter')
      .describe(
        '\nThink of this <dfn>Robot</dfn> as an `if/else` condition for building advanced file conversion workflows. With it, you can filter and direct certain uploaded files depending on their metadata.\n\nThe <dfn>Robot</dfn> has two modes of operation:\n\n- Constructing conditions out of arrays with 3 members each. For example, `["${file.size}", "<=", "720"]`\n- Writing conditions in JavaScript. For example, `${file.size <= 720}`. See also [Dynamic Evaluation](https://transloadit.com/docs/topics/dynamic-evaluation/).\n\nPassing JavaScript allows you to implement logic as complex as you wish, however it’s slower than combining arrays of conditions, and will be charged for per invocation via [🤖/script/run](https://transloadit.com/docs/transcoding/code-evaluation/script-run/).\n\n### Conditions as arrays\n\nThe `accepts` and `declines` parameters can each be set to an array of arrays with three members:\n\n1. A value or job variable, such as `${file.mime}`\n2. One of the following operators: `==`, `===`, `<`, `>`, `<=`, `>=`, `!=`, `!==`, `regex`, `!regex`\n3. A value or job variable, such as `50` or `"foo"`\n\nExamples:\n\n- `[["${file.meta.width}", ">", "${file.meta.height}"]]`\n- `[["${file.size}", "<=", "720"]]`\n- `[["720", ">=", "${file.size}"]]`\n- `[["${file.mime}", "regex", "image"]]`\n\n**Warning:** If you would like to match against a `null` value or a value that is not present (like an audio file does not have a `video_codec` property in its metadata), match against `""` (an empty string) instead. We’ll support proper matching against `null` in the future, but we cannot easily do so right now without breaking backwards compatibility. [{.alert .alert-warning}]\n\n### Conditions as JavaScript\n\nThe `accepts` and `declines` parameters can each be set to strings of JavaScript, which return a boolean value.\n\nExamples:\n\n- `${file.meta.width > file.meta.height}`\n- `${file.size <= 720}`\n- `${/image/.test(file.mime)}`\n- `${Math.max(file.meta.width, file.meta.height) > 100}`\n\nAs indicated, we charge for this via [🤖/script/run](https://transloadit.com/docs/transcoding/code-evaluation/script-run/). See also [Dynamic Evaluation](https://transloadit.com/docs/topics/dynamic-evaluation/) for more details on allowed syntax and behavior.\n',
      ),
    accepts: z
      .array(
        z.union([
          z.string(),
          z.tuple([z.string(), z.string(), z.union([z.string(), z.number()])]),
        ]),
      )
      .describe(
        '\nFiles that match at least one requirement will be accepted, or declined otherwise. If the array is empty, all files will be accepted. Example:\n\n`[["${file.mime}", "==", "image/gif"]]`.\n\nIf the `condition_type` parameter is set to `"and"`, then all requirements must match for the file to be accepted.\n',
      )
      .default([]),
    declines: z
      .array(
        z.union([
          z.string(),
          z.tuple([z.string(), z.string(), z.union([z.string(), z.number()])]),
        ]),
      )
      .describe(
        '\nFiles that match at least one requirement will be declined, or accepted otherwise. Example:\n\n`[["${file.size}",">","1024"]]`.\n\nIf the `condition_type` parameter is set to `"and"`, then all requirements must match for the file to be declined.\n',
      )
      .default([]),
    condition_type: z
      .enum(['and', 'or'])
      .describe(
        '\nSpecifies the condition type according to which the members of the `accepts` or `declines` arrays should be evaluated. Can be `"or"` or `"and"`.\n',
      )
      .default('or'),
    error_on_decline: z
      .boolean()
      .describe(
        '\nIf this is set to `true` and one or more files are declined, the Assembly will be stopped and marked with an error.\n',
      )
      .default(false),
    error_msg: z
      .string()
      .describe(
        '\nThe error message shown to your users (such as by Uppy) when a file is declined and `error_on_decline` is set to `true`.\n',
      )
      .default('One of your files was declined'),
  })
  .strict()

```

#### `/file/hash`

[/file/hash docs](https://transloadit.com/docs/transcoding/file-hash/)

Robot Parameter Zod Schema:

```ts
const fileHashSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/hash')
      .describe(
        '\nThis <dfn>Robot</dfn> allows you to hash any file as part of the <dfn>Assembly</dfn> execution process. This can be useful for verifying the integrity of a file for example.\n',
      ),
    algorithm: z
      .enum(['b2', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'])
      .describe(
        '\nThe hashing algorithm to use.\n\nThe file hash is exported as `file.meta.hash`.\n',
      )
      .default('sha256'),
  })
  .strict()

```

#### `/file/preview`

[/file/preview docs](https://transloadit.com/docs/transcoding/file-preview/)

Robot Parameter Zod Schema:

```ts
const filePreviewSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/preview')
      .describe(
        "\nThis <dfn>Robot</dfn>'s purpose is to generate a meaningful preview image for any file, in such a way that the resulting thumbnail highlights the file's content. The goal is not to losslessly present the original media in a smaller way. Instead, it is to maximize the chance of a person recognizing the media at a glance, while being visually pleasing and consistent with other previews. The generation process depends on the file type. For example, the <dfn>Robot</dfn> can extract artwork from media files, frames from videos, generate a waveform for audio files, and preview the content of documents and images. The details of all available strategies are provided in the next section.\n\nIf no file-specific thumbnail can be generated because the file type is not supported, a generic icon containing the file extension will be generated.\n\nThe default parameters ensure that the <dfn>Robot</dfn> always generates a preview image with the predefined dimensions and formats, to allow an easy integration into your application's UI. In addition, the generated preview images are optimized by default to reduce their file size while keeping their quality.\n",
      ),
    format: z
      .enum(['gif', 'jpg', 'png'])
      .describe(
        '\nThe output format for the generated thumbnail image. If a short video clip is generated using the `clip` strategy, its format is defined by `clip_format`.\n',
      )
      .default('png'),
    width: z
      .union([
        z
          .number()
          .int()
          .gte(1)
          .lte(7680)
          .describe('\nWidth of the thumbnail, in pixels.\n')
          .default(300),
        z.string().regex(new RegExp('^[\\d.]*\\${.+}[\\d.]*$')),
      ])
      .describe('\nWidth of the thumbnail, in pixels.\n')
      .optional(),
    height: z
      .union([
        z
          .number()
          .int()
          .gte(1)
          .lte(4320)
          .describe('\nHeight of the thumbnail, in pixels.\n')
          .default(200),
        z.any(),
      ])
      .describe('\nHeight of the thumbnail, in pixels.\n')
      .optional(),
    resize_strategy: z
      .enum(['crop', 'fit', 'fillcrop', 'min_fit', 'pad', 'stretch'])
      .describe(
        '\nTo achieve the desired dimensions of the preview thumbnail, the <dfn>Robot</dfn> might have to resize the generated image. This happens, for example, when the dimensions of a frame extracted from a video do not match the chosen `width` and `height` parameters.\n\nSee the list of available [resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies) for more details.\n',
      )
      .default('pad'),
    background: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$'))
      .describe(
        '\nThe hexadecimal code of the color used to fill the background (only used for the pad resize strategy). The format is `#rrggbb[aa]` (red, green, blue, alpha). Use `#00000000` for a transparent padding.\n',
      )
      .default('#ffffffff'),
    strategy: z
      .object({
        archive: z.array(z.string()).default(['icon']),
        audio: z.array(z.string()).default(['artwork', 'waveform', 'icon']),
        document: z.array(z.string()).default(['page', 'icon']),
        image: z.array(z.string()).default(['image', 'icon']),
        unknown: z.array(z.string()).default(['icon']),
        video: z.array(z.string()).default(['artwork', 'frame', 'icon']),
        webpage: z.array(z.string()).default(['render', 'icon']),
      })
      .strict()
      .describe(
        '\nDefinition of the thumbnail generation process per file category. The parameter must be an object whose keys can be one of the file categories: `audio`, `video`, `image`, `document`, `archive`, `webpage`, and `unknown`. The corresponding value is an array of strategies for the specific file category. See the above section for a list of all available strategies.\n\nFor each file, the <dfn>Robot</dfn> will attempt to use the first strategy to generate the thumbnail. If this process fails (e.g., because no artwork is available in a video file), the next strategy is attempted. This is repeated until either a thumbnail is generated or the list is exhausted. Selecting the `icon` strategy as the last entry provides a fallback mechanism to ensure that an appropriate strategy is always available.\n\nThe parameter defaults to the following definition:\n\n```json\n{\n  "audio": ["artwork", "waveform", "icon"],\n  "video": ["artwork", "frame", "icon"],\n  "document": ["page", "icon"],\n  "image": ["image", "icon"],\n  "webpage": ["render", "icon"],\n  "archive": ["icon"],\n  "unknown": ["icon"]\n}\n```\n',
      )
      .optional(),
    waveform_center_color: z
      .any()
      .describe(
        "\nThe color used in the center of the waveform's gradient. The format is `#rrggbb[aa]` (red, green, blue, alpha). Only used if the `waveform` strategy for audio files is applied.\n",
      )
      .default('#000000ff'),
    waveform_outer_color: z
      .any()
      .describe(
        "\nThe color used in the outer parts of the waveform's gradient. The format is `#rrggbb[aa]` (red, green, blue, alpha). Only used if the `waveform` strategy for audio files is applied.\n",
      )
      .default('#000000ff'),
    waveform_height: z
      .number()
      .int()
      .gte(1)
      .lte(5000)
      .describe(
        '\nHeight of the waveform, in pixels. Only used if the `waveform` strategy for audio files is applied. It can be utilized to ensure that the waveform only takes up a section of the preview thumbnail.\n',
      )
      .default(100),
    waveform_width: z
      .number()
      .int()
      .gte(1)
      .lte(5000)
      .describe(
        '\nWidth of the waveform, in pixels. Only used if the `waveform` strategy for audio files is applied. It can be utilized to ensure that the waveform only takes up a section of the preview thumbnail.\n',
      )
      .default(300),
    icon_style: z
      .enum(['square', 'with-text'])
      .describe(
        '\nThe style of the icon generated if the `icon` strategy is applied. The default style, `with-text`, includes an icon showing the file type and a text box below it, whose content can be controlled by the `icon_text_content` parameter and defaults to the file extension (e.g. MP4, JPEG). The `square` style only includes a square variant of the icon showing the file type. Below are exemplary previews generated for a text file utilizing the different styles:\n\n<br><br> <strong>`with-text` style:</strong> <br>\n![Image with text style](/assets/images/file-preview/icon-with-text.png)\n<br><br> <strong>`square` style:</strong> <br>\n![Image with square style](/assets/images/file-preview/icon-square.png)\n',
      )
      .default('with-text'),
    icon_text_color: z
      .any()
      .describe(
        '\nThe color of the text used in the icon. The format is `#rrggbb[aa]`. Only used if the `icon` strategy is applied.\n',
      )
      .default('#a2a2a2'),
    icon_text_font: z
      .string()
      .describe(
        '\nThe font family of the text used in the icon. Only used if the `icon` strategy is applied. [Here](https://transloadit.com/docs/supported-formats/fonts/) is a list of all supported fonts.\n',
      )
      .default('Roboto'),
    icon_text_content: z
      .enum(['extension', 'none'])
      .describe(
        '\nThe content of the text box in generated icons. Only used if the `icon_style` parameter is set to `with-text`. The default value, `extension`, adds the file extension (e.g. MP4, JPEG) to the icon. The value `none` can be used to render an empty text box, which is useful if no text should not be included in the raster image, but some place should be reserved in the image for later overlaying custom text over the image using HTML etc.\n',
      )
      .default('extension'),
    optimize: z
      .boolean()
      .describe(
        "\nSpecifies whether the generated preview image should be optimized to reduce the image's file size while keeping their quaility. If enabled, the images will be optimized using [🤖/image/optimize](https://transloadit.com/docs/transcoding/image-manipulation/image-optimize/).\n",
      )
      .default(true),
    optimize_priority: z
      .enum(['compression-ratio', 'conversion-speed'])
      .describe(
        '\nSpecifies whether conversion speed or compression ratio is prioritized when optimizing images. Only used if `optimize` is enabled. Please see the [🤖/image/optimize documentation](https://transloadit.com/docs/transcoding/image-manipulation/image-optimize/#param-priority) for more details.\n',
      )
      .default('conversion-speed'),
    optimize_progressive: z
      .boolean()
      .describe(
        '\nSpecifies whether images should be interlaced, which makes the result image load progressively in browsers. Only used if `optimize` is enabled. Please see the [🤖/image/optimize documentation](https://transloadit.com/docs/transcoding/image-manipulation/image-optimize/#param-progressive) for more details.\n',
      )
      .default(false),
    clip_format: z
      .enum(['apng', 'avif', 'gif', 'webp'])
      .describe(
        '\nThe animated image format for the generated video clip. Only used if the `clip` strategy for video files is applied.\n\nPlease consult the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types) for detailed information about the image formats and their characteristics. GIF enjoys the broadest support in software, but only supports a limit color palette. APNG supports a variety of color depths, but its lossless compression produces large images for videos. AVIF is a modern image format that offers great compression, but proper support for animations is still lacking in some browsers. WebP on the other hand, enjoys broad support while offering a great balance between small file sizes and good visual quality, making it the default clip format.\n',
      )
      .default('webp'),
    clip_offset: z
      .number()
      .gte(0)
      .describe(
        '\nThe start position in seconds of where the clip is cut. Only used if the `clip` strategy for video files is applied. Be aware that for larger video only the first few MBs of the file may be imported to improve speed. Larger offsets may seek to a position outside of the imported part and thus fail to generate a clip.\n',
      )
      .default(1),
    clip_duration: z
      .number()
      .gte(0)
      .describe(
        '\nThe duration in seconds of the generated video clip. Only used if the `clip` strategy for video files is applied. Be aware that a longer clip duration also results in a larger file size, which might be undesirable for previews.\n',
      )
      .default(5),
    clip_framerate: z
      .number()
      .int()
      .gte(1)
      .lte(60)
      .describe(
        '\nThe framerate of the generated video clip. Only used if the `clip` strategy for video files is applied. Be aware that a higher framerate appears smoother but also results in a larger file size, which might be undesirable for previews.\n',
      )
      .default(5),
    clip_loop: z
      .boolean()
      .describe(
        '\nSpecifies whether the generated animated image should loop forever (`true`) or stop after playing the animation once (`false`). Only used if the `clip` strategy for video files is applied.\n',
      )
      .default(true),
  })
  .strict()

```

#### `/file/read`

[/file/read docs](https://transloadit.com/docs/transcoding/file-read/)

Robot Parameter Zod Schema:

```ts
const fileReadSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/read')
      .describe(
        '\nThis <dfn>Robot</dfn> accepts any file, and will read the file using UTF-8 encoding. The result is outputted to `file.meta.content` to be accessed in later <dfn>Steps</dfn>.\n\nThe <dfn>Robot</dfn> currently only accepts files under 500KB.\n',
      ),
  })
  .strict()

```

#### `/file/serve`

[/file/serve docs](https://transloadit.com/docs/transcoding/file-serve/)

Robot Parameter Zod Schema:

```ts
const fileServeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/serve')
      .describe(
        "\nWhen you want Transloadit to tranform files on the fly, you can use this <dfn>Robot</dfn> to determine which <dfn>Step</dfn> of a <dfn>Template</dfn> should be served to the end-user (via a CDN), as well as set extra information on the served files, such as headers. This way you can for instance suggest the CDN for how long to keep cached copies of the result around. By default, as you can see in the `headers` parameter, we instruct browsers to cache the result for 72h (`259200` seconds) and CDNs to cache the content for 24h (`86400` seconds). These values should be adjusted to suit your use case.\n\n🤖/file/serve merely acts as the glue layer between our <dfn>Assembly</dfn> engine and serving files over HTTP. It let's you pick the proper result of a series of <dfn>Steps</dfn> via the `use` parameter and configure headers on the original content. That is where its responsibilies end, and 🤖/tlcdn/deliver, then takes over to globally distribute this original content across the globe, and make sure that is cached close to your end-users, when they make requests such as <https://my-app.tlcdn.com/resize-img/canoe.jpg?w=500>, another. 🤖/tlcdn/deliver is not a part of your <dfn>Assembly Instructions</dfn>, but it may appear on your invoices as bandwidth charges incur when distributing the cached copies. 🤖/file/serve only charges when the CDN does not have a cached copy and requests to regenerate the original content, which depending on your caching settings could be just once a month, or year, per file/transformation.\n\nWhile theoretically possible, you could use [🤖/file/serve](https://transloadit.com/docs/transcoding/content-delivery/file-serve/) directly in HTML files, but we strongly recommend against this, because if your site gets popular and the media URL that /file/serve is handling gets hit one million times, that is one million new image resizes. Wrapping it with a CDN (and thanks to the caching that comes with it) makes sure encoding charges stay low, as well as latencies.\n\nAlso consider configuring caching headers and cache-control directives to control how content is cached and invalidated on the CDN edge servers, balancing between freshness and efficiency.\n\nMore information on:\n\n- [Content Delivery](https://transloadit.com/services/content-delivery/).\n- [🤖/file/serve](https://transloadit.com/docs/transcoding/content-delivery/file-serve/) pricing.\n- [🤖/tlcdn/deliver](https://transloadit.com/docs/transcoding/content-delivery/tlcdn-deliver/) pricing.\n- [File Preview Feature](https://transloadit.com/blog/2024/06/file-preview-with-smart-cdn/) blog post.\n",
      ),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for a file as we serve it to a CDN/web browser, such as `{ FileURL: "${file.url_name}" }` which will be merged over the defaults, and can include any available [Assembly Variable](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default({
        'Access-Control-Allow-Headers':
          'X-Requested-With, Content-Type, Cache-Control, Accept, Content-Length, Transloadit-Client, Authorization',
        'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Origin': '*',
        'Cache-Control': 'public, max-age=259200, s-max-age=86400',
        'Content-Type': '${file.mime}; charset=utf-8',
        'Transfer-Encoding': 'chunked',
        'Transloadit-Assembly': '…',
        'Transloadit-RequestID': '…',
      }),
  })
  .strict()

```

#### `/file/verify`

[/file/verify docs](https://transloadit.com/docs/transcoding/file-verify/)

Robot Parameter Zod Schema:

```ts
const fileVerifySchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/file/verify'),
    error_on_decline: z
      .boolean()
      .describe(
        '\nIf this is set to `true` and one or more files are declined, the Assembly will be stopped and marked with an error.\n',
      )
      .default(false),
    error_msg: z
      .string()
      .describe(
        '\nThe error message shown to your users (such as by Uppy) when a file is declined and `error_on_decline` is set to `true`.\n',
      )
      .default('One of your files was declined'),
    verify_to_be: z
      .string()
      .describe(
        '\nThe type that you want to match against to ensure your file is of this type. For example, `image` will verify whether uploaded files are images. This also works against file media types, in this case `image/png` would also work to match against specifically `png` files.\n',
      )
      .default('pdf'),
  })
  .strict()

```

#### `/file/virusscan`

[/file/virusscan docs](https://transloadit.com/docs/transcoding/file-virusscan/)

Robot Parameter Zod Schema:

```ts
const fileVirusscanSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/file/virusscan')
      .describe(
        '\n      This <dfn>Robot</dfn> is built on top of [ClamAV](https://www.clamav.net/), the best open source antivirus engine available. We update its signatures on a daily basis.\n\nBy default, this <dfn>Robot</dfn> excludes all malicious files from further processing without any additional notification. This behavior can be changed by setting `error_on_decline` to `true`, which will stop <dfn>Assemblies</dfn> as soon as malicious files are found. Such <dfn>Assemblies</dfn> will then be marked with an error.\n\nWe allow the use of industry standard [EICAR files](https://www.eicar.org/download-anti-malware-testfile/) for integration testing without needing to use potentially dangerous live virus samples.\n',
      ),
    error_on_decline: z
      .boolean()
      .describe(
        '\nIf this is set to `true` and one or more files are declined, the Assembly will be stopped and marked with an error.\n',
      )
      .default(false),
    error_msg: z
      .string()
      .describe(
        '\nThe error message shown to your users (such as by Uppy) when a file is declined and `error_on_decline` is set to `true`.\n',
      )
      .default('One of your files was declined'),
  })
  .strict()

```

#### `/ftp/import`

[/ftp/import docs](https://transloadit.com/docs/transcoding/ftp-import/)

Robot Parameter Zod Schema:

```ts
const ftpImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    host: z.string().optional(),
    port: z
      .number()
      .int()
      .gte(1)
      .lte(65535)
      .describe('The port to use for the FTP connection.')
      .default(21),
    user: z.string().optional(),
    password: z.string().optional(),
    robot: z.literal('/ftp/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        '\nThe path on your FTP server where to search for files. Files are imported recursively from all sub-directories and sub-sub-directories (and so on) from this path.\n',
      ),
    passive_mode: z
      .boolean()
      .describe(
        '\nDetermines if passive mode should be used for the FTP connection.\n',
      )
      .default(true),
  })
  .strict()

```

#### `/ftp/store`

[/ftp/store docs](https://transloadit.com/docs/transcoding/ftp-store/)

Robot Parameter Zod Schema:

```ts
const ftpStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    host: z.string().optional(),
    port: z
      .number()
      .int()
      .gte(1)
      .lte(65535)
      .describe('The port to use for the FTP connection.')
      .default(21),
    user: z.string().optional(),
    password: z.string().optional(),
    robot: z.literal('/ftp/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This can contain any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nPlease note that you might need to include your homedir at the beginning of the path.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    url_template: z
      .string()
      .describe(
        '\nThe URL of the file in the result JSON. The following [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables) are supported.\n',
      )
      .default('https://{HOST}/{PATH}'),
    ssl_url_template: z
      .string()
      .describe(
        '\nThe SSL URL of the file in the result JSON. The following [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables) are supported.\n',
      )
      .default('https://{HOST}/{PATH}'),
    secure: z
      .boolean()
      .describe(
        '\nDetermines whether to establish a secure connection to the FTP server using SSL.\n',
      )
      .default(false),
  })
  .strict()

```

#### `/google/import`

[/google/import docs](https://transloadit.com/docs/transcoding/google-import/)

Robot Parameter Zod Schema:

```ts
const googleImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    robot: z.literal('/google/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive a 404 `GOOGLE_IMPORT_NOT_FOUND` error.\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `start_file_name` and `files_per_page` wisely here.\n',
      )
      .default(false),
    next_page_token: z
      .string()
      .describe(
        '\nA string token used for pagination. The returned files of one paginated call have the next page token inside of their meta data, which needs to be used for the subsequent paging call.\n',
      )
      .default(''),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/google/store`

[/google/store docs](https://transloadit.com/docs/transcoding/google-store/)

Robot Parameter Zod Schema:

```ts
const googleStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/google/store')
      .describe(
        "\nThe URL to the exported file in your Google bucket will be presented in the Transloadit <dfn>Assembly Status</dfn> JSON. This <dfn>Robot</dfn> can also be used to export encoded files to Google's Firebase as demonstrated in [this blogpost](https://transloadit.com/blog/2018/12/2h-youtube-clone/).\n",
      ),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    acl: z
      .union([
        z.enum([
          'authenticated-read',
          'bucket-owner-full-control',
          'private',
          'project-private',
          'public-read',
        ]),
        z.null(),
      ])
      .describe('\nThe permissions used for this file.\n')
      .default('public-read'),
    cache_control: z
      .string()
      .describe(
        "\nThe `Cache-Control` header determines how long browsers are allowed to cache your object for. Values specified with this parameter will be added to the object's metadata under the `Cache-Control` header. For more information on valid values, take a look at the [official Google documentation](https://cloud.google.com/storage/docs/metadata#cache-control).\n",
      )
      .optional(),
    url_template: z
      .string()
      .describe(
        '\nThe URL of the file in the result JSON. This may include any of the following supported [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('https://{HOST}/{PATH}'),
    ssl_url_template: z
      .string()
      .describe(
        '\nThe SSL URL of the file in the result JSON. The following [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables) are supported.\n',
      )
      .default('https://{HOST}/{PATH}'),
  })
  .strict()

```

#### `/html/convert`

[/html/convert docs](https://transloadit.com/docs/transcoding/html-convert/)

Robot Parameter Zod Schema:

```ts
const htmlConvertSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/html/convert')
      .describe(
        '\nA URL can be provided instead of an input HTML file, to capture a screenshot from the website referenced by the URL.\n\nUse [🤖/image/resize](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/) to resize or crop the screenshot as needed.\n',
      ),
    url: z
      .union([
        z
          .string()
          .describe(
            '\nThe URL of the web page to be converted. Optional, as you can also upload/import HTML files and pass it to this <dfn>Robot</dfn>.\n',
          )
          .default(null),
        z
          .null()
          .describe(
            '\nThe URL of the web page to be converted. Optional, as you can also upload/import HTML files and pass it to this <dfn>Robot</dfn>.\n',
          )
          .default(null),
      ])
      .describe(
        '\nThe URL of the web page to be converted. Optional, as you can also upload/import HTML files and pass it to this <dfn>Robot</dfn>.\n',
      )
      .default(null),
    format: z
      .enum(['jpeg', 'jpg', 'pdf', 'png'])
      .describe('\nThe format of the resulting image.\n')
      .default('png'),
    fullpage: z
      .boolean()
      .describe(
        '\nDetermines if a screenshot of the full page should be taken or not.\n\nIf set to `true`, the `height` parameter will not have any effect, as heights of websites vary. You can control the size of the resulting image somewhat, though, by setting the `width` parameter.\n\nIf set to `false`, an image will be cropped from the top of the webpage according to your `width` and `height` parameters.\n',
      )
      .default(true),
    omit_background: z
      .boolean()
      .describe(
        "\nDetermines whether to preserve a transparent background in HTML pages. Useful if you're generating artwork in HTML that you want to overlay on e.g. a video.\n\nThe default of `false` fills transparent areas with a white background, for easier reading/printing.\n\nThis parameter is only used when `format` is not `pdf`.\n",
      )
      .default(false),
    width: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nThe screen width that will be used, in pixels. Change this to change the  dimensions of the resulting image.\n',
      )
      .default(1024),
    height: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nThe screen height that will be used, in pixels. By default this equals the length of the web page in pixels if `fullpage` is set to `true`. If `fullpage` is set to `false`, the height parameter takes effect and defaults to the value `768`.\n',
      )
      .optional(),
    delay: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThe delay (in milliseconds) applied to allow the page and all of its JavaScript to render before taking the screenshot.\n',
      )
      .default(0),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing optional headers that will be passed along with the original request to the website. For example, this parameter can be used to pass along an authorization token along with the request.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/http/import`

[/http/import docs](https://transloadit.com/docs/transcoding/http-import/)

Robot Parameter Zod Schema:

```ts
const httpImportSchema = z
  .object({
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    robot: z
      .literal('/http/import')
      .describe(
        '\nThe result of this <dfn>Robot</dfn> will carry a field `import_url` in their metadata, which references the URL from which they were imported. Further conversion results that use this file will also carry this `import_url` field. This allows you to to match conversion results with the original import URL that you used.\n\nThis <dfn>Robot</dfn> knows to interpret links to files on these services:\n\n- Dropbox\n- Google Drive\n- Google Docs\n- OneDrive\n\nInstead of downloading the HTML page previewing the file, the actual file itself will be imported.\n',
      ),
    url: z
      .union([z.string().url(), z.array(z.string().url())])
      .describe(
        '\nThe URL from which the file to be imported can be retrieved.\n\nYou can also specify an array of URLs or a string of `|` delimited URLs to import several files at once. Please also check the `url_delimiter` parameter for that.\n',
      ),
    url_delimiter: z
      .string()
      .describe(
        '\nProvides the delimiter that is used to split the URLs in your `url` parameter value.\n',
      )
      .default('|'),
    headers: z
      .array(z.string())
      .describe(
        '\nCustom headers to be sent for file import.\n\nThis is an empty array by default, such that no additional headers except the necessary ones (e.g. Host) are sent.\n',
      )
      .default([]),
    force_name: z
      .union([z.union([z.string(), z.array(z.string())]), z.null()])
      .describe(
        '\nCustom name for the imported file(s). Defaults to `null`, which means the file names are derived from the supplied URL(s).\n',
      )
      .default(null),
    import_on_errors: z
      .array(z.string())
      .describe(
        '\nSetting this to `"meta"` will still import the file on metadata extraction errors. `ignore_errors` is similar, it also ignores the error and makes sure the Robot doesn\'t stop, but it doesn\'t import the file.\n',
      )
      .default([]),
    fail_fast: z
      .boolean()
      .describe(
        "\nDisable the internal retry mechanism, and fail immediately if a resource can't be imported. This can be useful for performance critical applications.\n",
      )
      .default(false),
  })
  .strict()

```

#### `/image/describe`

[/image/describe docs](https://transloadit.com/docs/transcoding/image-describe/)

Robot Parameter Zod Schema:

```ts
const imageDescribeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/image/describe')
      .describe(
        '\nYou can use the labels that we return in your application to automatically classify images. You can also pass the labels down to other <dfn>Robots</dfn> to filter images that contain (or do not contain) certain content.\n',
      ),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage.\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n',
      ),
    granularity: z
      .enum(['full', 'list'])
      .describe(
        '\nWhether to return a full response (`"full"`) including confidence percentages for each found label, or just a flat list of labels (`"list"`).\n',
      )
      .default('full'),
    format: z
      .enum(['json', 'meta', 'text'])
      .describe(
        '\nIn what format to return the descriptions.\n\n- `"json"` returns a JSON file.\n- `"meta"` does not return a file, but stores the data inside Transloadit\'s file object (under `${file.meta.descriptions}`) that\'s passed around between encoding <dfn>Steps</dfn>, so that you can use the values to burn the data into videos, filter on them, etc.\n',
      )
      .default('json'),
    explicit_descriptions: z
      .boolean()
      .describe(
        '\nWhether to return only explicit or only non-explicit descriptions of the provided image. Explicit descriptions include labels for NSFW content (nudity, violence, etc). If set to `false`, only non-explicit descriptions (such as human or chair) will be returned. If set to `true`, only explicit descriptions will be returned.\n\nThe possible descriptions depend on the chosen provider. The list of labels from AWS can be found [in their documentation](https://docs.aws.amazon.com/rekognition/latest/dg/moderation.html#moderation-api). GCP labels the image based on five categories, as described [in their documentation](https://cloud.google.com/vision/docs/detecting-safe-search).\n\nFor an example of how to automatically reject NSFW content and malware, please check out this [blog post](https://transloadit.com/blog/2022/07/deny-image-uploads/).\n',
      )
      .default(false),
  })
  .strict()

```

#### `/image/facedetect`

[/image/facedetect docs](https://transloadit.com/docs/transcoding/image-facedetect/)

Robot Parameter Zod Schema:

```ts
const imageFacedetectSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/image/facedetect')
      .describe(
        '\nYou can specify padding around the extracted faces, tailoring the output for your needs.\n\nThis <dfn>Robot</dfn> works well together with [🤖/image/resize](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/) to bring the full power of resized and optimized images to your website or app.\n\n<div class="alert alert-note">\n\n**How to improve the accuracy:**\n\n- Ensure that your pictures have the correct orientation. This <dfn>Robot</dfn> achieves the best performance when the faces in the image are oriented upright and not rotated.\n- If the <dfn>Robot</dfn> detects objects other than a face, you can use `"faces": "max-confidence"` within your <dfn>Template</dfn> for selecting only the detection with the highest confidence.\n- The number of returned detections can also be controlled using the `min_confidence` parameter. Increasing its value will yield less results but each with a higher confidence. Decreasing the value, on the other hand, will provide more results but may also include objects other than faces.\n\n</div>\n',
      ),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage.\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n',
      )
      .optional(),
    crop: z
      .boolean()
      .describe(
        '\nDetermine if the detected faces should be extracted. If this option is set to `false`, then the <dfn>Robot</dfn> returns the input image again, but with the coordinates of all detected faces attached to `file.meta.faces` in the result JSON. If this parameter is set to `true`, the <dfn>Robot</dfn> will output all detected faces as images.\n',
      )
      .default(false),
    crop_padding: z
      .string()
      .regex(new RegExp('^\\d+(px|%)$'))
      .describe(
        '\nSpecifies how much padding is added to the extracted face images if `crop` is set to `true`. Values can be in `px` (pixels) or `%` (percentage of the width and height of the particular face image).\n',
      )
      .default('5px'),
    format: z
      .enum(['jpg', 'png', 'preserve', 'tiff'])
      .describe(
        '\nDetermines the output format of the extracted face images if `crop` is set to `true`.\n\nThe default value `"preserve"` means that the input image format is re-used.\n',
      )
      .default('preserve'),
    min_confidence: z
      .number()
      .int()
      .gte(0)
      .lte(100)
      .describe(
        '\nSpecifies the minimum confidence that a detected face must have. Only faces which have a higher confidence value than this threshold will be included in the result.\n',
      )
      .default(70),
    faces: z
      .union([
        z.enum(['each', 'group', 'max-confidence', 'max-size']),
        z.number().int(),
      ])
      .describe(
        '\nDetermines which of the detected faces should be returned. Valid values are:\n\n- `"each"` — each face is returned individually.\n- `"max-confidence"` — only the face with the highest confidence value is returned.\n- `"max-size"` — only the face with the largest area is returned.\n- `"group"` — all detected faces are grouped together into one rectangle that contains all faces.\n- any integer — the faces are sorted by their top-left corner and the integer determines the index of the returned face. Be aware the values are zero-indexed, meaning that `faces: 0` will return the first face. If no face for a given index exists, no output is produced.\n\nFor the following examples, the input image is:\n\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-unsplash.jpg)\n\n<br>\n\n`faces: "each"` applied:\n\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-face-0.jpg)\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-face-1.jpg)\n\n<br>\n\n`faces: "max-confidence"` applied:\n\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-face-1.jpg)\n\n<br>\n\n`faces: "max-size"` applied:\n\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-face-1.jpg)\n\n<br>\n\n`faces: "group"` applied:\n\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-face-group.jpg)\n\n<br>\n\n`faces: 0` applied:\n\n![](https://transloadit.com/assets/images/abbas-malek-hosseini-22NnY93qaOk-face-0.jpg)\n',
      )
      .default('each'),
  })
  .strict()

```

#### `/image/merge`

[/image/merge docs](https://transloadit.com/docs/transcoding/image-merge/)

Robot Parameter Zod Schema:

```ts
const imageMergeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/image/merge')
      .describe(
        "\nThe final result will be a spritesheet, with the images displayed horizontally or vertically.\n\nIt's recommended to use this Robot with\n[🤖/image/resize](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/) so your images are of a\nsimilar size before merging them.\n",
      ),
    format: z
      .enum(['jpg', 'png'])
      .describe('The output format for the modified image.')
      .default('png'),
    direction: z
      .enum(['horizontal', 'vertical'])
      .describe('Specifies the direction which the images are displayed.')
      .default('horizontal'),
    border: z
      .number()
      .int()
      .gte(1)
      .lte(10)
      .describe(
        '\nAn integer value which defines the gap between images on the spritesheet.\n\nA value of `10` would cause the images to have the largest gap between them, while a value of `1` would place the images side-by-side.\n',
      )
      .default(0),
    background: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{6}$'))
      .describe(
        '\nEither the hexadecimal code or [name](https://www.imagemagick.org/script/color.php#color_names) of the color used to fill the background (only shown with a border > 1).\n\nBy default, the background of transparent images is changed to white.\n\nFor details about how to preserve transparency across all image types, see [this demo](https://transloadit.com/demos/image-manipulation/properly-preserve-transparency-across-all-image-types/).\n',
      )
      .default('#FFFFFF'),
    adaptive_filtering: z
      .boolean()
      .describe(
        '\nControls the image compression for PNG images. Setting to `true` results in smaller file size, while increasing processing time. It is encouraged to keep this option disabled.\n',
      )
      .default(false),
    quality: z
      .number()
      .int()
      .gte(1)
      .lte(100)
      .describe(
        '\nControls the image compression for JPG and PNG images. Please also take a look at [🤖/image/optimize](https://transloadit.com/docs/transcoding/image-manipulation/image-optimize/).\n',
      )
      .default(92),
  })
  .strict()

```

#### `/image/ocr`

[/image/ocr docs](https://transloadit.com/docs/transcoding/image-ocr/)

Robot Parameter Zod Schema:

```ts
const imageOcrSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/image/ocr')
      .describe(
        '\nWith this <dfn>Robot</dfn> you can detect and extract text from images using optical character recognition (OCR).\n\nFor example, you can use the results to obtain the content of traffic signs, name tags, package labels and many more. You can also pass the text down to other <dfn>Robots</dfn> to filter images that contain (or do not contain) certain phrases. For images of dense documents, results may vary and be less accurate than for small pieces of text in photos.\n',
      ),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage.\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n\nAWS supports detection for the following languages: English, Arabic, Russian, German, French, Italian, Portuguese and Spanish. GCP allows for a wider range of languages, with varying levels of support which can be found on the [official documentation](https://cloud.google.com/vision/docs/languages/).\n',
      ),
    granularity: z
      .enum(['full', 'list'])
      .describe(
        '\nWhether to return a full response including coordinates for the text (`"full"`), or a flat list of the extracted phrases (`"list"`). This parameter has no effect if the `format` parameter is set to `"text"`.\n',
      )
      .default('full'),
    format: z
      .enum(['json', 'meta', 'text'])
      .describe(
        '\nIn what format to return the extracted text.\n- `"json"` returns a JSON file.\n- `"meta"` does not return a file, but stores the data inside Transloadit\'s file object (under `${file.meta.recognized_text}`, which is an array of strings) that\'s passed around between encoding <dfn>Steps</dfn>, so that you can use the values to burn the data into videos, filter on them, etc.\n- `"text"` returns the recognized text as a plain UTF-8 encoded text file.\n',
      )
      .default('json'),
  })
  .strict()

```

#### `/image/optimize`

[/image/optimize docs](https://transloadit.com/docs/transcoding/image-optimize/)

Robot Parameter Zod Schema:

```ts
const imageOptimizeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/image/optimize')
      .describe(
        "\nWith this <dfn>Robot</dfn> it's possible to reduce the file size of your JPEG, PNG, GIF, WEBP and SVG images by up to 80% for big images and 65% for small to medium sized ones — while keeping their original quality!\n\nThis <dfn>Robot</dfn> enables you to lower your storage and bandwidth costs, and improves your user experience and monetization by reducing the load time of image-intensive web pages.\n\nIt works well together with [🤖/image/resize](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/) to bring the full power of resized and optimized images to your website or app.\n\n**Note:** This <dfn>Robot</dfn> accepts all image types and will just pass on unsupported image types unoptimized. Hence, there is no need to set up [🤖/file/filter](https://transloadit.com/docs/transcoding/file-filtering/file-filter/) workflows for this. [{.alert .alert-note}]\n",
      ),
    priority: z
      .enum(['compression-ratio', 'conversion-speed'])
      .describe(
        '\nProvides different algorithms for better or worse compression for your images, but that run slower or faster. The value `"conversion-speed"` will result in an average compression ratio of 18%. `"compression-ratio"` will result in an average compression ratio of 31%.\n',
      )
      .default('conversion-speed'),
    progressive: z
      .boolean()
      .describe(
        '\nInterlaces the image if set to `true`, which makes the result image load progressively in browsers. Instead of rendering the image from top to bottom, the browser will first show a low-res blurry version of the image which is then quickly replaced with the actual image as the data arrives. This greatly increases the user experience, but comes at a loss of about 10% of the file size reduction.\n',
      )
      .default(false),
    preserve_meta_data: z
      .boolean()
      .describe(
        "\nSpecifies if the image's metadata should be preserved during the optimization, or not. If it is not preserved, the file size is even further reduced. But be aware that this could strip a photographer's copyright information, which for obvious reasons can be frowned upon.\n",
      )
      .default(true),
    fix_breaking_images: z
      .boolean()
      .describe(
        '\nIf set to `true` this parameter tries to fix images that would otherwise make the underlying tool error out and thereby break your <dfn>Assemblies</dfn>. This can sometimes result in a larger file size, though.\n',
      )
      .default(true),
  })
  .strict()

```

#### `/image/resize`

[/image/resize docs](https://transloadit.com/docs/transcoding/image-resize/)

Robot Parameter Zod Schema:

```ts
const imageResizeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    imagemagick_stack: z
      .union([
        z.literal('v3'),
        z.string().regex(new RegExp('^v?[23](\\.\\d+)?(\\.\\d+)?$')),
      ])
      .default('v3'),
    robot: z.literal('/image/resize'),
    format: z
      .union([
        z
          .string()
          .describe(
            '\nThe output format for the modified image.\n\nSome of the most important available formats are `"jpg"`, `"png"`, `"gif"`, and `"tiff"`. For a complete lists of all formats that we can write to please check [our supported image formats list](https://transloadit.com/docs/supported-formats/image-formats/).\n\nIf `null` (default), then the input image\'s format will be used as the output format.\n\nIf you wish to convert to `"pdf"`, please consider [🤖/document/convert](https://transloadit.com/docs/transcoding/document-processing/document-convert/) instead.\n',
          )
          .default(null),
        z
          .null()
          .describe(
            '\nThe output format for the modified image.\n\nSome of the most important available formats are `"jpg"`, `"png"`, `"gif"`, and `"tiff"`. For a complete lists of all formats that we can write to please check [our supported image formats list](https://transloadit.com/docs/supported-formats/image-formats/).\n\nIf `null` (default), then the input image\'s format will be used as the output format.\n\nIf you wish to convert to `"pdf"`, please consider [🤖/document/convert](https://transloadit.com/docs/transcoding/document-processing/document-convert/) instead.\n',
          )
          .default(null),
      ])
      .describe(
        '\nThe output format for the modified image.\n\nSome of the most important available formats are `"jpg"`, `"png"`, `"gif"`, and `"tiff"`. For a complete lists of all formats that we can write to please check [our supported image formats list](https://transloadit.com/docs/supported-formats/image-formats/).\n\nIf `null` (default), then the input image\'s format will be used as the output format.\n\nIf you wish to convert to `"pdf"`, please consider [🤖/document/convert](https://transloadit.com/docs/transcoding/document-processing/document-convert/) instead.\n',
      )
      .default(null),
    width: z
      .union([
        z
          .union([
            z
              .any()
              .refine(
                (value) => !z.any().safeParse(value).success,
                'Invalid input: Should NOT be valid against schema',
              ),
            z.number().int().gte(1).lte(7680),
          ])
          .describe(
            '\nWidth of the result in pixels. If not specified, will default to the width of the original.\n',
          ),
        z.string().regex(new RegExp('^[\\d.]*\\${.+}[\\d.]*$')),
      ])
      .describe(
        '\nWidth of the result in pixels. If not specified, will default to the width of the original.\n',
      )
      .optional(),
    height: z
      .union([
        z
          .union([
            z
              .any()
              .refine(
                (value) => !z.any().safeParse(value).success,
                'Invalid input: Should NOT be valid against schema',
              ),
            z.number().int().gte(1).lte(4320),
          ])
          .describe(
            '\nHeight of the new image, in pixels. If not specified, will default to the height of the input image.\n',
          ),
        z.any(),
      ])
      .describe(
        '\nHeight of the new image, in pixels. If not specified, will default to the height of the input image.\n',
      )
      .optional(),
    resize_strategy: z
      .union([
        z
          .enum(['crop', 'fillcrop', 'fit', 'min_fit', 'pad', 'stretch'])
          .describe(
            '\nSee the list of available [resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
          )
          .default('fit'),
        z.string().regex(new RegExp('\\${.+}')),
      ])
      .describe(
        '\nSee the list of available [resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
      )
      .optional(),
    zoom: z
      .boolean()
      .describe(
        '\nIf this is set to `false`, smaller images will not be stretched to the desired width and height. For details about the impact of zooming for your preferred resize strategy, see the list of available [resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
      )
      .default(true),
    crop: z
      .union([
        z
          .object({
            x1: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
            y1: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
            x2: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
            y2: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
          })
          .strict(),
        z.string(),
      ])
      .describe(
        '\nSpecify an object containing coordinates for the top left and bottom right corners of the rectangle to be cropped from the original image(s). The coordinate system is rooted in the top left corner of the image. Values can be integers for absolute pixel values or strings for percentage based values.\n\nFor example:\n\n```json\n{\n  "x1": 80,\n  "y1": 100,\n  "x2": "60%",\n  "y2": "80%"\n}\n```\n\nThis will crop the area from `(80, 100)` to `(600, 800)` from a 1000×1000 pixels image, which is a square whose width is 520px and height is 700px. If `crop` is set, the width and height parameters are ignored, and the `resize_strategy` is set to `crop` automatically.\n\nYou can also use a JSON string of such an object with coordinates in similar fashion:\n\n```json\n"{"x1": <Integer>, "y1": <Integer>, "x2": <Integer>, "y2": <Integer>}"\n```\n\nTo crop around human faces, see [🤖/image/facedetect](https://transloadit.com/docs/transcoding/artificial-intelligence/image-facedetect/).\n',
      )
      .optional(),
    gravity: z
      .enum([
        'bottom',
        'bottom-left',
        'bottom-right',
        'center',
        'left',
        'right',
        'top',
        'top-left',
        'top-right',
      ])
      .describe(
        '\nThe direction from which the image is to be cropped, when `"resize_strategy"` is set to `"crop"`, but no crop coordinates are defined.\n',
      )
      .default('center'),
    strip: z
      .boolean()
      .describe(
        '\nStrips all metadata from the image. This is useful to keep thumbnails as small as possible.\n',
      )
      .default(false),
    alpha: z
      .enum([
        'Activate',
        'Background',
        'Copy',
        'Deactivate',
        'Extract',
        'Off',
        'On',
        'Opaque',
        'Remove',
        'Set',
        'Shape',
        'Transparent',
      ])
      .describe('\nGives control of the alpha/matte channel of an image.\n')
      .optional(),
    preclip_alpha: z
      .enum([
        'Activate',
        'Background',
        'Copy',
        'Deactivate',
        'Extract',
        'Off',
        'On',
        'Opaque',
        'Remove',
        'Set',
        'Shape',
        'Transparent',
      ])
      .describe(
        '\nGives control of the alpha/matte channel of an image before applying the clipping path via `clip: true`.\n',
      )
      .optional(),
    flatten: z
      .boolean()
      .describe(
        '\nFlattens all layers onto the specified background to achieve better results from transparent formats to non-transparent formats, as explained in the [ImageMagick documentation](https://www.imagemagick.org/script/command-line-options.php?#layers).\n\nTo preserve animations, GIF files are not flattened when this is set to `true`. To flatten GIF animations, use the `frame` parameter.\n',
      )
      .default(true),
    correct_gamma: z
      .boolean()
      .describe(
        '\nPrevents gamma errors [common in many image scaling algorithms](https://www.4p8.com/eric.brasseur/gamma.html).\n',
      )
      .default(false),
    quality: z
      .number()
      .int()
      .gte(1)
      .lte(100)
      .describe(
        '\nControls the image compression for JPG and PNG images. Please also take a look at [🤖/image/optimize](https://transloadit.com/docs/transcoding/image-manipulation/image-optimize/).\n',
      )
      .default(92),
    adaptive_filtering: z
      .boolean()
      .describe(
        '\nControls the image compression for PNG images. Setting to `true` results in smaller file size, while increasing processing time. It is encouraged to keep this option disabled.\n',
      )
      .default(false),
    background: z
      .union([
        z
          .union([
            z.literal('transparent'),
            z.literal('none'),
            z.string().regex(new RegExp('^#?[0-9a-fA-F]{6}$')),
          ])
          .describe(
            '\nEither the hexadecimal code or [name](https://www.imagemagick.org/script/color.php#color_names) of the color used to fill the background (used for the `pad` resize strategy).\n\n**Note:** By default, the background of transparent images is changed to white. To preserve transparency, set `"background"` to `"none"`.\n',
          )
          .default('#FFFFFF'),
        z.any(),
      ])
      .describe(
        '\nEither the hexadecimal code or [name](https://www.imagemagick.org/script/color.php#color_names) of the color used to fill the background (used for the `pad` resize strategy).\n\n**Note:** By default, the background of transparent images is changed to white. To preserve transparency, set `"background"` to `"none"`.\n',
      )
      .optional(),
    frame: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        '\nUse this parameter when dealing with animated GIF files to specify which frame of the GIF is used for the operation. Specify `1` to use the first frame, `2` to use the second, and so on. `null` means all frames.\n',
      )
      .default(null),
    colorspace: z
      .enum([
        'CMY',
        'CMYK',
        'Gray',
        'HCL',
        'HCLp',
        'HSB',
        'HSI',
        'HSL',
        'HSV',
        'HWB',
        'Jzazbz',
        'Lab',
        'LCHab',
        'LCHuv',
        'LMS',
        'Log',
        'Luv',
        'OHTA',
        'OkLab',
        'OkLCH',
        'Rec601YCbCr',
        'Rec709YCbCr',
        'RGB',
        'scRGB',
        'sRGB',
        'Transparent',
        'Undefined',
        'xyY',
        'XYZ',
        'YCbCr',
        'YCC',
        'YDbDr',
        'YIQ',
        'YPbPr',
        'YUV',
      ])
      .describe(
        '\nSets the image colorspace. For details about the available values, see the [ImageMagick documentation](https://www.imagemagick.org/script/command-line-options.php#colorspace). Please note that if you were using `"RGB"`, we recommend using `"sRGB"` instead as of 2014-02-04. ImageMagick might try to find the most efficient `colorspace` based on the color of an image, and default to e.g. `"Gray"`. To force colors, you might have to use this parameter in combination with `type: "TrueColor"`.\n',
      )
      .optional(),
    type: z
      .enum([
        'Bilevel',
        'ColorSeparation',
        'ColorSeparationAlpha',
        'Grayscale',
        'GrayscaleAlpha',
        'Palette',
        'PaletteAlpha',
        'TrueColor',
        'TrueColorAlpha',
      ])
      .describe(
        '\nSets the image color type. For details about the available values, see the [ImageMagick documentation](https://www.imagemagick.org/script/command-line-options.php#type). If you\'re using `colorspace`, ImageMagick might try to find the most efficient based on the color of an image, and default to e.g. `"Gray"`. To force colors, you could e.g. set this parameter to `"TrueColor"`\n',
      )
      .optional(),
    sepia: z
      .union([z.number().int().gte(0).lte(99), z.null()])
      .describe('\nApplies a sepia tone effect in percent.\n')
      .default(null),
    rotation: z
      .union([
        z.literal(90),
        z.literal(180),
        z.literal(270),
        z.literal(360),
        z.boolean(),
      ])
      .describe(
        '\nDetermines whether the image should be rotated. Use integers to specify the rotation for each quarter revolution(`90`, `180`, `270`, `360`). Use the value `true` to auto-rotate images that are rotated incorrectly or depend on EXIF rotation settings. Otherwise, use `false` to disable auto-fixing altogether.\n',
      )
      .default(true),
    compress: z
      .union([
        z.enum([
          'BZip',
          'Fax',
          'Group4',
          'JPEG',
          'JPEG2000',
          'Lossless',
          'LZW',
          'None',
          'RLE',
          'Zip',
        ]),
        z.null(),
      ])
      .describe(
        '\nSpecifies pixel compression for when the image is written. Compression is disabled by default.\n\nPlease also take a look at [🤖/image/optimize](https://transloadit.com/docs/transcoding/image-manipulation/image-optimize/).\n',
      )
      .default(null),
    blur: z
      .union([
        z.string().regex(new RegExp('^\\d+(\\.\\d+)?x\\d+(\\.\\d+)?$')),
        z.null(),
      ])
      .describe(
        '\nSpecifies gaussian blur, using a value with the form `{radius}x{sigma}`. The radius value specifies the size of area the operator should look at when spreading pixels, and should typically be either `"0"` or at least two times the sigma value. The sigma value is an approximation of how many pixels the image is "spread"; think of it as the size of the brush used to blur the image. This number is a floating point value, enabling small values like `"0.5"` to be used.\n',
      )
      .default(null),
    blur_regions: z
      .union([
        z
          .union([
            z.array(
              z
                .object({
                  x: z.any(),
                  y: z.any(),
                  width: z.any(),
                  height: z.any(),
                })
                .strict(),
            ),
            z.null(),
          ])
          .describe(
            '\nSpecifies an array of ellipse objects that should be blurred on the image. Each object has the following keys: `x`, `y`, `width`, `height`.  If `blur_regions` has a value, then the `blur` parameter is used as the strength of the blur for each region.\n',
          )
          .default(null),
        z.array(
          z
            .object({
              x: z.union([z.any(), z.any()]),
              y: z.union([z.any(), z.any()]),
              width: z.union([z.any(), z.any()]),
              height: z.union([z.any(), z.any()]),
            })
            .strict(),
        ),
      ])
      .describe(
        '\nSpecifies an array of ellipse objects that should be blurred on the image. Each object has the following keys: `x`, `y`, `width`, `height`.  If `blur_regions` has a value, then the `blur` parameter is used as the strength of the blur for each region.\n',
      )
      .optional(),
    brightness: z
      .number()
      .gte(0)
      .describe(
        '\nIncreases or decreases the brightness of the image by using a multiplier. For example `1.5` would increase the brightness by 50%, and `0.75` would decrease the brightness by 25%.\n',
      )
      .default(1),
    saturation: z
      .number()
      .gte(0)
      .describe(
        '\nIncreases or decreases the saturation of the image by using a multiplier. For example `1.5` would increase the saturation by 50%, and `0.75` would decrease the saturation by 25%.\n',
      )
      .default(1),
    hue: z
      .number()
      .gte(0)
      .describe(
        '\nChanges the hue by rotating the color of the image. The value `100` would produce no change whereas `0` and `200` will negate the colors in the image.\n',
      )
      .default(100),
    watermark_url: z
      .string()
      .describe(
        '\nA URL indicating a PNG image to be overlaid above this image. Please note that you can also  [supply the watermark via another Assembly Step](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#image-resize-supply-watermark-via-assembly-step). With watermarking you can add an image onto another image. This is usually used for logos.\n',
      )
      .optional(),
    watermark_position: z
      .union([z.any(), z.array(z.any())])
      .describe(
        '\nThe position at which the watermark is placed. The available options are `"center"`, `"top"`, `"bottom"`, `"left"`, and `"right"`. You can also combine options, such as `"bottom-right"`.\n\nAn array of possible values can also be specified, in which case one value will be selected at random, such as `[ "center", "left", "bottom-left", "bottom-right" ]`.\n\nThis setting puts the watermark in the specified corner. To use a specific pixel offset for the watermark, you will need to add the padding to the image itself.\n',
      )
      .default('center'),
    watermark_x_offset: z
      .number()
      .int()
      .describe(
        "\nThe x-offset in number of pixels at which the watermark will be placed in relation to the position it has due to `watermark_position`.\n\nValues can be both positive and negative and yield different results depending on the `watermark_position` parameter. Positive values move the watermark closer to the image's center point, whereas negative values move the watermark further away from the image's center point.\n",
      )
      .default(0),
    watermark_y_offset: z
      .number()
      .int()
      .describe(
        "\nThe y-offset in number of pixels at which the watermark will be placed in relation to the position it has due to `watermark_position`.\n\nValues can be both positive and negative and yield different results depending on the `watermark_position` parameter. Positive values move the watermark closer to the image's center point, whereas negative values move the watermark further away from the image's center point.\n",
      )
      .default(0),
    watermark_size: z
      .string()
      .regex(new RegExp('^\\d+%$'))
      .describe(
        '\nThe size of the watermark, as a percentage.\n\nFor example, a value of `"50%"` means that size of the watermark will be 50% of the size of image on which it is placed. The exact sizing depends on `watermark_resize_strategy`, too.\n',
      )
      .optional(),
    watermark_resize_strategy: z
      .enum(['area', 'fit', 'min_fit', 'stretch'])
      .describe(
        '\nAvailable values are `"fit"`, `"min_fit"`, `"stretch"` and `"area"`.\n\nTo explain how the resize strategies work, let\'s assume our target image size is 800×800 pixels and our watermark image is 400×300 pixels. Let\'s also assume, the `watermark_size` parameter is set to `"25%"`.\n\nFor the `"fit"` resize strategy, the watermark is scaled so that the longer side of the watermark takes up 25% of the corresponding image side. And the other side is scaled according to the aspect ratio of the watermark image. So with our watermark, the width is the longer side, and 25% of the image size would be 200px. Hence, the watermark would be resized to 200×150 pixels. If the `watermark_size` was set to `"50%"`, it would be resized to 400×300 pixels (so just left at its original size).\n\nFor the `"min_fit"` resize strategy, the watermark is scaled so that the shorter side of the watermark takes up 25% of the corresponding image side. And the other side is scaled according to the aspect ratio of the watermark image. So with our watermark, the height is the shorter side, and 25% of the image size would be 200px. Hence, the watermark would be resized to 267×200 pixels. If the `watermark_size` was set to `"50%"`, it would be resized to 533×400 pixels (so larger than its original size).\n\nFor the `"stretch"` resize strategy, the watermark is stretched (meaning, it is resized without keeping its aspect ratio in mind) so that both sides take up 25% of the corresponding image side. Since our image is 800×800 pixels, for a watermark size of 25% the watermark would be resized to 200×200 pixels. Its height would appear stretched, because keeping the aspect ratio in mind it would be resized to 200×150 pixels instead.\n\nFor the `"area"` resize strategy, the watermark is resized (keeping its aspect ratio in check) so that it covers `"xx%"` of the image\'s surface area. The value from `watermark_size` is used for the percentage area size.\n',
      )
      .default('fit'),
    text: z
      .array(
        z
          .object({
            text: z.string(),
            font: z
              .string()
              .describe(
                '\nThe font family to use. Also includes boldness and style of the font.\n\n[Here](https://transloadit.com/docs/supported-formats/fonts/) is a list of all\nsupported fonts.\n',
              )
              .default('Arial'),
            size: z
              .number()
              .int()
              .gte(1)
              .describe('\nThe text size in pixels.\n')
              .default(12),
            rotate: z
              .number()
              .int()
              .describe('\nThe rotation angle in degrees.\n')
              .default(0),
            color: z
              .union([z.any(), z.literal('transparent')])
              .describe(
                '\nThe text color. All hex colors in the form `"#xxxxxx"` are supported, where each x can be `0-9` or `a-f`. `"transparent"` is also supported if you want a transparent text color. In that case use "stroke" instead, otherwise your text will not be visible.\n',
              )
              .default('#000000'),
            background_color: z
              .union([z.any(), z.literal('transparent')])
              .describe(
                '\nThe text color. All hex colors in the form `"#xxxxxx"` are supported, where each x is can be `0-9` or `a-f`. `"transparent"` is also supported.\n',
              )
              .default('transparent'),
            stroke_width: z
              .number()
              .int()
              .gte(0)
              .describe("\nThe stroke's width in pixels.\n")
              .default(0),
            stroke_color: z
              .union([z.any(), z.literal('transparent')])
              .describe(
                '\nThe stroke\'s color. All hex colors in the form `"#xxxxxx"` are supported, where each x is can be `0-9` or `a-f`. `"transparent"` is also supported.\n',
              )
              .default('transparent'),
            align: z
              .enum(['center', 'left', 'right'])
              .describe(
                '\nThe horizontal text alignment. Can be `"left"`, `"center"` and `"right"`.\n',
              )
              .default('center'),
            valign: z
              .enum(['bottom', 'center', 'top'])
              .describe(
                '\nThe vertical text alignment. Can be `"top"`, `"center"` and `"bottom"`.\n',
              )
              .default('center'),
            x_offset: z
              .number()
              .int()
              .describe(
                '\nThe horizontal offset for the text in pixels that is added (positive integer) or removed (negative integer) from the horizontal alignment.\n',
              )
              .default(0),
            y_offset: z
              .number()
              .int()
              .describe(
                '\nThe vertical offset for the text in pixels that is added (positive integer) or removed (negative integer) from the vertical alignment.\n',
              )
              .default(0),
          })
          .strict(),
      )
      .describe(
        '\nAn array of objects each containing text rules. The following text parameters are intended to be used as properties for your array of text overlays. Here is an example:\n\n```json\n"watermarked": {\n  "use": "resized",\n  "robot": "/image/resize",\n  "text": [\n    {\n      "text": "© 2018 Transloadit.com",\n      "size": 12,\n      "font": "Ubuntu",\n      "color": "#eeeeee",\n      "valign": "bottom",\n      "align": "right",\n      "x_offset": 16,\n      "y_offset": -10\n    }\n  ]\n}\n```\n',
      )
      .default([]),
    progressive: z
      .boolean()
      .describe(
        '\nInterlaces the image if set to `true`, which makes the image load progressively in browsers. Instead of rendering the image from top to bottom, the browser will first show a low-res blurry version of the images which is then quickly replaced with the actual image as the data arrives. This greatly increases the user experience, but comes at a cost of a file size increase by around 10%.\n',
      )
      .default(false),
    transparent: z
      .union([z.any(), z.string().regex(new RegExp('^\\d+,\\d+,\\d+$'))])
      .describe(
        '\nMake this color transparent within the image. Example: `"255,255,255"`.\n',
      )
      .optional(),
    trim_whitespace: z
      .boolean()
      .describe(
        '\nThis determines if additional whitespace around the image should first be trimmed away. If you set this to `true` this parameter removes any edges that are exactly the same color as the corner pixels.\n',
      )
      .default(false),
    clip: z
      .union([
        z
          .string()
          .describe(
            '\nApply the clipping path to other operations in the resize job, if one is present. If set to `true`, it will automatically take the first clipping path. If set to a String it finds a clipping path by that name.\n',
          )
          .default(false),
        z
          .boolean()
          .describe(
            '\nApply the clipping path to other operations in the resize job, if one is present. If set to `true`, it will automatically take the first clipping path. If set to a String it finds a clipping path by that name.\n',
          )
          .default(false),
      ])
      .describe(
        '\nApply the clipping path to other operations in the resize job, if one is present. If set to `true`, it will automatically take the first clipping path. If set to a String it finds a clipping path by that name.\n',
      )
      .default(false),
    negate: z
      .boolean()
      .describe(
        '\nReplace each pixel with its complementary color, effectively negating the image. Especially useful when testing clipping.\n',
      )
      .default(false),
    density: z
      .union([z.string().regex(new RegExp('\\d+(x\\d+)?')), z.null()])
      .describe(
        '\nWhile in-memory quality and file format depth specifies the color resolution, the density of an image is the spatial (space) resolution of the image. That is the density (in pixels per inch) of an image and defines how far apart (or how big) the individual pixels are. It defines the size of the image in real world terms when displayed on devices or printed.\n\nYou can set this value to a specific `width` or in the format `width`x`height`.\n\nIf your converted image is unsharp, please try increasing density.\n',
      )
      .default(null),
  })
  .strict()

```

#### `/meta/write`

[/meta/write docs](https://transloadit.com/docs/transcoding/meta-write/)

Robot Parameter Zod Schema:

```ts
const metaWriteSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z
      .literal('/meta/write')
      .describe(
        '\n**Note:** This <dfn>Robot</dfn> currently accepts images, videos and audio files.\n',
      ),
    data_to_write: z
      .object({})
      .catchall(z.any())
      .describe(
        '\nA key/value map defining the metadata to write into the file.\n\nValid metadata keys can be found [here](https://exiftool.org/TagNames/EXIF.html). For example: `ProcessingSoftware`.\n',
      )
      .default({}),
  })
  .strict()

```

#### `/minio/import`

[/minio/import docs](https://transloadit.com/docs/transcoding/minio-import/)

Robot Parameter Zod Schema:

```ts
const minioImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/minio/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/minio/store`

[/minio/store docs](https://transloadit.com/docs/transcoding/minio-store/)

Robot Parameter Zod Schema:

```ts
const minioStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/minio/store')
      .describe(
        '\nThe URL to the result file will be returned in the <dfn>Assembly Status JSON</dfn>.\n',
      ),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    acl: z
      .enum(['private', 'public-read'])
      .describe('\nThe permissions used for this file.\n')
      .default('public-read'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on MinIO Spaces, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds.\n\nIf this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/s3/import`

[/s3/import docs](https://transloadit.com/docs/transcoding/s3-import/)

Robot Parameter Zod Schema:

```ts
const s3ImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/s3/import')
      .describe(
        '\nIf you are new to Amazon S3, see our tutorial on [using your own S3 bucket](https://transloadit.com/docs/faq/how-to-set-up-an-amazon-s3-bucket/).\n\nThe URL to the result file in your S3 bucket will be returned in the <dfn>Assembly Status JSON</dfn>.\n\n**Use DNS-compliant bucket names.** Your bucket name [must be DNS-compliant](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) and must not contain uppercase letters. Any non-alphanumeric characters in the file names will be replaced with an underscore, and spaces will be replaced with dashes. If your existing S3 bucket contains uppercase letters or is otherwise not DNS-compliant, rewrite the result URLs using the <dfn>Robot</dfn>’s `url_prefix` parameter. [{.alert .alert-warning}]\n\n<a id="minimum-s3-iam-permissions" aria-hidden="true"></a>\n\n## Limit access\n\nYou will also need to add permissions to your bucket so that Transloadit can access it properly. Here is an example IAM policy that you can use. Following the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), it contains the **minimum required permissions** to export a file to your S3 bucket using Transloadit. You may require more permissions (especially viewing permissions) depending on your application.\n\nPlease change `{BUCKET_NAME}` in the values for `Sid` and `Resource` accordingly. Also, this policy will grant the minimum required permissions to all your users. We advise you to create a separate Amazon IAM user, and use its User ARN (can be found in the "Summary" tab of a user [here](https://console.aws.amazon.com/iam/home#users)) for the `Principal` value. More information about this can be found [here](https://docs.aws.amazon.com/AmazonS3/latest/dev/AccessPolicyLanguage_UseCases_s3_a.html).\n\n```json\n{\n  "Version": "2012-10-17",\n  "Statement": [\n    {\n      "Sid": "AllowTransloaditToImportFilesIn{BUCKET_NAME}Bucket",\n      "Effect": "Allow",\n      "Action": ["s3:GetBucketLocation", "s3:ListBucket"],\n      "Resource": ["arn:aws:s3:::{BUCKET_NAME}", "arn:aws:s3:::{BUCKET_NAME}/*"]\n    }\n  ]\n}\n```\n\nThe `Sid` value is just an identifier for you to recognize the rule later. You can name it anything you like.\n\nThe policy needs to be separated into two parts, because the `ListBucket` action requires permissions on the bucket while the other actions require permissions on the objects in the bucket. When targeting the objects there\'s a trailing slash and an asterisk in the `Resource` parameter, whereas when the policy targets the bucket, the slash and the asterisk are omitted.\n\nIn order to build proper result URLs we need to know the region in which your S3 bucket resides. For this we require the `GetBucketLocation` permission. Figuring out your bucket\'s region this way will also slow down your Assemblies. To make this much faster and to also not require the `GetBucketLocation` permission, we have added the `bucket_region` parameter to the /s3/store and /s3/import Robots. We recommend using them at all times.\n\nPlease keep in mind that if you use bucket encryption you may also need to add `"sts:*"` and `"kms:*"` to the bucket policy. Please read [here](https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html) and [here](https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/) in case you run into trouble with our example bucket policy.\n',
      ),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants to this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/s3/store`

[/s3/store docs](https://transloadit.com/docs/transcoding/s3-store/)

Robot Parameter Zod Schema:

```ts
const s3StoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    bucket_region: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/s3/store')
      .describe(
        '\nIf you are new to Amazon S3, see our tutorial on [using your own S3 bucket](https://transloadit.com/docs/faq/how-to-set-up-an-amazon-s3-bucket/).\n\nThe URL to the result file in your S3 bucket will be returned in the <dfn>Assembly Status JSON</dfn>. If your S3 bucket has versioning enabled, the version ID of the file will be returned within `meta.version_id`\n\n**Avoid permission errors.** By default, `acl` is set to `"public"`. AWS S3 has a bucket setting called "Block new public ACLs and uploading public objects". Set this to <strong>False</strong> in your bucket if you intend to leave `acl` as `"public"`. Otherwise, you’ll receive permission errors in your Assemblies despite your S3 credentials being configured correctly. [{.alert .alert-warning}]\n\n**Use DNS-compliant bucket names.** Your bucket name [must be DNS-compliant](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) and must not contain uppercase letters. Any non-alphanumeric characters in the file names will be replaced with an underscore, and spaces will be replaced with dashes. If your existing S3 bucket contains uppercase letters or is otherwise not DNS-compliant, rewrite the result URLs using the <dfn>Robot</dfn>’s `url_prefix` parameter. [{.alert .alert-warning}]\n\n<a id="minimum-s3-iam-permissions" aria-hidden="true"></a>\n\n## Limit access\n\nYou will also need to add permissions to your bucket so that Transloadit can access it properly. Here is an example IAM policy that you can use. Following the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), it contains the **minimum required permissions** to export a file to your S3 bucket using Transloadit. You may require more permissions (especially viewing permissions) depending on your application.\n\nPlease change `{BUCKET_NAME}` in the values for `Sid` and `Resource` accordingly. Also, this policy will grant the minimum required permissions to all your users. We advise you to create a separate Amazon IAM user, and use its User ARN (can be found in the "Summary" tab of a user [here](https://console.aws.amazon.com/iam/home#users)) for the `Principal` value. More information about this can be found [here](https://docs.aws.amazon.com/AmazonS3/latest/dev/AccessPolicyLanguage_UseCases_s3_a.html).\n\n```json\n{\n  "Version": "2012-10-17",\n  "Statement": [\n    {\n      "Sid": "AllowTransloaditToStoreFilesIn{BUCKET_NAME}Bucket",\n      "Effect": "Allow",\n      "Action": ["s3:GetBucketLocation", "s3:ListBucket", "s3:PutObject", "s3:PutObjectAcl"],\n      "Resource": ["arn:aws:s3:::{BUCKET_NAME}", "arn:aws:s3:::{BUCKET_NAME}/*"]\n    }\n  ]\n}\n```\n\nThe `Sid` value is just an identifier for you to recognize the rule later. You can name it anything you like.\n\nThe policy needs to be separated into two parts, because the `ListBucket` action requires permissions on the bucket while the other actions require permissions on the objects in the bucket. When targeting the objects there\'s a trailing slash and an asterisk in the `Resource` parameter, whereas when the policy targets the bucket, the slash and the asterisk are omitted.\n\nPlease note that if you give the <dfn>Robot</dfn>\'s `acl` parameter a value of `"bucket-default"`, then you do not need the `"s3:PutObjectAcl"` permission in your bucket policy.\n\nIn order to build proper result URLs we need to know the region in which your S3 bucket resides. For this we require the `GetBucketLocation` permission. Figuring out your bucket\'s region this way will also slow down your Assemblies. To make this much faster and to also not require the `GetBucketLocation` permission, we have added the `bucket_region` parameter to the /s3/store and /s3/import Robots. We recommend using them at all times.\n\nPlease keep in mind that if you use bucket encryption you may also need to add `"sts:*"` and `"kms:*"` to the bucket policy. Please read [here](https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html) and [here](https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/) in case you run into trouble with our example bucket policy.\n',
      ),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    url_prefix: z
      .string()
      .describe(
        '\nThe URL prefix used for the returned URL, such as `"http://my.cdn.com/some/path/"`.\n',
      )
      .default('http://{bucket}.s3.amazonaws.com/'),
    acl: z
      .enum(['bucket-default', 'private', 'public', 'public-read'])
      .describe(
        '\nThe permissions used for this file.\n\nPlease keep in mind that the default value `"public-read"` can lead to permission errors due to the `"Block all public access"` checkbox that is checked by default when creating a new Amazon S3 Bucket in the AWS console.\n',
      )
      .default('public-read'),
    check_integrity: z
      .boolean()
      .describe(
        "\nCalculate and submit the file's checksum in order for S3 to verify its integrity after uploading, which can help with occasional file corruption issues.\n\nEnabling this option adds to the overall execution time, as integrity checking can be CPU intensive, especially for larger files.\n",
      )
      .default(false),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on S3, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). You can find a list of available headers [here](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    tags: z
      .record(z.string())
      .describe(
        '\nObject tagging allows you to categorize storage. You can associate up to 10 tags with an object. Tags that are associated with an object must have unique tag keys.\n',
      )
      .default({}),
    host: z
      .string()
      .describe(
        '\nThe host of the storage service used. This only needs to be set when the storage service used is not Amazon S3, but has a compatible API (such as hosteurope.de). The default protocol used is HTTP, for anything else the protocol needs to be explicitly specified. For example, prefix the host with `https://` or `s3://` to use either respective protocol.\n',
      )
      .default('s3.amazonaws.com'),
    no_vhost: z
      .boolean()
      .describe(
        '\nSet to `true` if you use a custom host and run into access denied errors.\n',
      )
      .default(false),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_url` and `signed_ssl_url` properties). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/script/run`

[/script/run docs](https://transloadit.com/docs/transcoding/script-run/)

Robot Parameter Zod Schema:

```ts
const scriptRunSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/script/run')
      .describe(
        '\nThis <dfn>Robot</dfn> allows you to run arbitrary `JavaScript` as part of the <dfn>Assembly</dfn>\nexecution process. The <dfn>Robot</dfn> is invoked automatically when there are <dfn>Assembly\nInstructions</dfn> containing `${...}`:\n\n```json\n{\n  "robot": "/image/resize",\n  "width": "${Math.max(file.meta.width, file.meta.height)}"\n}\n```\n\nYou can also invoke this <dfn>Robot</dfn> directly, leaving out the `${...}`:\n\n```json\n{\n  "robot": "/script/run",\n  "script": "Math.max(file.meta.width, file.meta.height)"\n}\n```\n\nWhen accessing arrays, the syntax is the same as in any JavaScript program:\n\n```json\n{\n  "robot": "/image/resize",\n  "width": "${file.meta.faces[0].width * 2}"\n}\n```\n\nCompared to only accessing an <dfn>Assembly Variable</dfn>:\n\n```json\n{\n  "robot": "/image/resize",\n  "width": "${file.meta.faces[0].width}"\n}\n```\n\nFor more information, see [Dynamic Evaluation](https://transloadit.com/docs/topics/dynamic-evaluation/).\n',
      ),
    script: z
      .string()
      .describe(
        '\nA string of JavaScript to evaluate. It has access to all JavaScript features available in a modern browser environment.\n\nThe script is expected to return a `JSON.stringify`-able value in the same tick, so no `await` or callbacks are allowed (yet).\n\nIf the script does not finish within 1000ms it times out with an error. The return value or error is exported as `file.meta.result`. If there was an error, `file.meta.isError` is `true`. Note that the <dfn>Assembly</dfn> will not crash in this case. If you need it to crash, you can check this value with a [🤖/file/filter](https://transloadit.com/docs/transcoding/file-filtering/file-filter/) <dfn>Step</dfn>, setting `error_on_decline` to `true`.\n\nYou can check whether evaluating this script was free by inspecting `file.meta.isFree`. It is recommended to do this during development as to not see sudden unexpected costs in production.\n',
      ),
  })
  .strict()

```

#### `/sftp/import`

[/sftp/import docs](https://transloadit.com/docs/transcoding/sftp-import/)

Robot Parameter Zod Schema:

```ts
const sftpImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    host: z.string().optional(),
    port: z
      .number()
      .int()
      .gte(1)
      .lte(65535)
      .describe('The port to use for the FTP connection.')
      .default(21),
    user: z.string().optional(),
    public_key: z.string().optional(),
    robot: z.literal('/sftp/import'),
    path: z
      .string()
      .describe('\nThe path on your SFTP server where to search for files.\n'),
  })
  .strict()

```

#### `/sftp/store`

[/sftp/store docs](https://transloadit.com/docs/transcoding/sftp-store/)

Robot Parameter Zod Schema:

```ts
const sftpStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    host: z.string().optional(),
    port: z
      .number()
      .int()
      .gte(1)
      .lte(65535)
      .describe('The port to use for the FTP connection.')
      .default(21),
    user: z.string().optional(),
    public_key: z.string().optional(),
    robot: z.literal('/sftp/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    url_template: z
      .string()
      .describe(
        '\nThe URL of the file in the result JSON. This may include any of the following supported [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n',
      )
      .default('http://host/path'),
    ssl_url_template: z
      .string()
      .describe(
        '\n  The SSL URL of the file in the result JSON. The following [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables) are supported.\n',
      )
      .default('https://{HOST}/{PATH}'),
    file_chmod: z
      .string()
      .regex(new RegExp('([0-7]{3}|auto)'))
      .describe(
        "\nThis optional parameter controls how an uploaded file's permission bits are set. You can use any string format that the `chmod` command would accept, such as `\"755\"`. If you don't specify this option, the file's permission bits aren't changed at all, meaning it's up to your server's configuration (e.g. umask).\n      ",
      )
      .default('auto'),
  })
  .strict()

```

#### `/speech/transcribe`

[/speech/transcribe docs](https://transloadit.com/docs/transcoding/speech-transcribe/)

Robot Parameter Zod Schema:

```ts
const speechTranscribeSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/speech/transcribe')
      .describe(
        '\nYou can use the text that we return in your application, or you can pass the text down to other <dfn>Robots</dfn> to filter audio or video files that contain (or do not contain) certain content, or burn the text into images or video for example.\n\nAnother common use case is automatically subtitling videos, or making audio searchable.\n',
      ),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage.\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n',
      ),
    granularity: z
      .enum(['full', 'list'])
      .describe(
        '\nWhether to return a full response (`"full"`), or a flat list of descriptions (`"list"`).\n',
      )
      .default('full'),
    format: z
      .enum(['json', 'meta', 'srt', 'meta', 'text', 'webvtt'])
      .describe(
        '\nOutput format for the transcription.\n\n- `"text"` outputs a plain text file that you can store and process.\n- `"json"` outputs a JSON file containing timestamped words.\n- `"srt"` and `"webvtt"` output subtitle files of those respective file types, which can be stored separately or used in other encoding <dfn>Steps</dfn>.\n- `"meta"` does not return a file, but stores the data inside  Transloadit\'s file object (under `${file.meta.transcription.text}`) that\'s passed around between encoding <dfn>Steps</dfn>, so that you can use the values to burn the data into videos, filter on them, etc.\n',
      )
      .default('json'),
    source_language: z
      .string()
      .describe(
        '\nThe spoken language of the audio or video. This will also be the language of the transcribed text.\n\nThe language should be specified in the [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) format, such as `"en-GB"`, `"de-DE"` or `"fr-FR"`. Please also consult the list of supported languages for [the `gcp` provider](https://cloud.google.com/speech-to-text/docs/languages) and the [the `aws` provider](https://docs.aws.amazon.com/transcribe/latest/dg/what-is-transcribe.html).\n',
      )
      .default('en-US'),
    target_language: z
      .string()
      .describe(
        '\n      This will also be the language of the written text.\n\n      The language should be specified in the [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) format, such as `"en-GB"`, `"de-DE"` or `"fr-FR"`. Please consult the list of supported languages and voices.\n    ',
      )
      .default('en-US'),
  })
  .strict()

```

#### `/supabase/import`

[/supabase/import docs](https://transloadit.com/docs/transcoding/supabase-import/)

Robot Parameter Zod Schema:

```ts
const supabaseImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/supabase/import')
      .describe(
        '\nThe URL to the result file will be returned in the <dfn>Assembly Status JSON</dfn>.\n',
      ),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subfolders and sub-subfolders, etc. of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/supabase/store`

[/supabase/store docs](https://transloadit.com/docs/transcoding/supabase-store/)

Robot Parameter Zod Schema:

```ts
const supabaseStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/supabase/store'),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on supabase Spaces, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/swift/import`

[/swift/import docs](https://transloadit.com/docs/transcoding/swift-import/)

Robot Parameter Zod Schema:

```ts
const swiftImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/swift/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/swift/store`

[/swift/store docs](https://transloadit.com/docs/transcoding/swift-store/)

Robot Parameter Zod Schema:

```ts
const swiftStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/swift/store')
      .describe(
        '\nThe URL to the result file in your OpenStack bucket will be returned in the <dfn>Assembly Status JSON</dfn>.',
      ),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    acl: z
      .enum(['private', 'public-read'])
      .describe('\nThe permissions used for this file.\n')
      .default('public-read'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on swift Spaces, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/text/speak`

[/text/speak docs](https://transloadit.com/docs/transcoding/text-speak/)

Robot Parameter Zod Schema:

```ts
const textSpeakSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/text/speak')
      .describe(
        '\nYou can use the audio that we return in your application, or you can pass the audio down to other <dfn>Robots</dfn> to add a voice track to a video for example.\n\nAnother common use case is making your product accessible to people with a reading disability.\n',
      ),
    prompt: z
      .union([
        z
          .string()
          .describe(
            '\nWhich text to speak. You can also set this to `null` and supply an input text file.\n',
          ),
        z
          .null()
          .describe(
            '\nWhich text to speak. You can also set this to `null` and supply an input text file.\n',
          ),
      ])
      .describe(
        '\nWhich text to speak. You can also set this to `null` and supply an input text file.\n',
      )
      .optional(),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage.\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n',
      ),
    target_language: z
      .string()
      .describe(
        '\nThe written language of the document. This will also be the language of the spoken text.\n\nThe language should be specified in the [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) format, such as `"en-GB"`, `"de-DE"` or `"fr-FR"`. Please consult the list of supported languages and voices.\n',
      )
      .default('en-US'),
    voice: z
      .enum([
        'female-1',
        'female-2',
        'female-3',
        'female-child-1',
        'male-1',
        'male-child-1',
      ])
      .describe(
        '\nThe gender to be used for voice synthesis. Please consult the list of supported languages and voices.\n      ',
      )
      .default('female-1'),
    ssml: z
      .boolean()
      .describe(
        '\nSupply [Speech Synthesis Markup Language](https://en.wikipedia.org/wiki/Speech_Synthesis_Markup_Language) instead of raw text, in order to gain more control over how your text is voiced, including rests and pronounciations.\n\nPlease see the supported syntaxes for [AWS](https://docs.aws.amazon.com/polly/latest/dg/supportedtags.html) and [GCP](https://cloud.google.com/text-to-speech/docs/ssml).\n',
      )
      .default(false),
  })
  .strict()

```

#### `/text/translate`

[/text/translate docs](https://transloadit.com/docs/transcoding/text-translate/)

Robot Parameter Zod Schema:

```ts
const textTranslateSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/text/translate')
      .describe(
        '\nYou can use the text that we return in your application, or you can pass the text down to other <dfn>Robots</dfn> to add a translated subtitle track to a video for example.\n\n**This <dfn>Robot</dfn> accepts only files with a `text/*` MIME-type,** including plain text and Markdown. For documents in other formats, use [🤖/document/convert](https://transloadit.com/docs/transcoding/document-processing/document-convert/) to first convert them into a compatible text format before proceeding. [{.alert .alert-note}]\n',
      ),
    provider: z
      .enum(['aws', 'gcp', 'replicate', 'fal', 'transloadit'])
      .describe(
        '\nWhich AI provider to leverage. Valid values are `"aws"` (Amazon Web Services) and `"gcp"` (Google Cloud Platform).\n\nTransloadit outsources this task and abstracts the interface so you can expect the same data structures, but different latencies and information being returned. Different cloud vendors have different areas they shine in, and we recommend to try out and see what yields the best results for your use case.\n',
      ),
    target_language: z
      .enum([
        'af',
        'am',
        'ar',
        'az',
        'be',
        'bg',
        'bn',
        'bs',
        'ca',
        'ceb',
        'co',
        'cs',
        'cy',
        'da',
        'de',
        'el',
        'en',
        'eo',
        'es',
        'es-MX',
        'et',
        'eu',
        'fa',
        'fa-AF',
        'fi',
        'fr',
        'fr-CA',
        'fy',
        'ga',
        'gd',
        'gl',
        'gu',
        'ha',
        'haw',
        'he',
        'hi',
        'hmn',
        'hr',
        'ht',
        'hu',
        'hy',
        'id',
        'ig',
        'is',
        'it',
        'iw',
        'ja',
        'jv',
        'ka',
        'kk',
        'km',
        'kn',
        'ko',
        'ku',
        'ky',
        'la',
        'lb',
        'lo',
        'lt',
        'lv',
        'mg',
        'mi',
        'mk',
        'ml',
        'mn',
        'mr',
        'ms',
        'mt',
        'my',
        'ne',
        'nl',
        'no',
        'ny',
        'or',
        'pa',
        'pl',
        'ps',
        'pt',
        'ro',
        'ru',
        'rw',
        'sd',
        'si',
        'sk',
        'sl',
        'sm',
        'sn',
        'so',
        'sq',
        'sr',
        'st',
        'su',
        'sv',
        'sw',
        'ta',
        'te',
        'tg',
        'th',
        'tk',
        'tl',
        'tr',
        'tt',
        'ug',
        'uk',
        'ur',
        'uz',
        'vi',
        'xh',
        'yi',
        'yo',
        'zh',
        'zh-CN',
        'zh-TW',
        'zu',
      ])
      .describe(
        '\nThe desired language to translate to.\n\nIf the exact language can\'t be found, a generic variant can be fallen back to. For example, if you specify `"en-US"`, "en" will be used instead. Please consult the list of supported languages for each provider.\n',
      )
      .default('en'),
    source_language: z
      .any()
      .describe(
        '\nThe desired language to translate from.\n\nBy default, both providers will detect this automatically, but there are cases where specifying the source language prevents ambiguities.\n\nIf the exact language can\'t be found, a generic variant can be fallen back to. For example, if you specify `"en-US"`, "en" will be used instead. Please consult the list of supported languages for each provider.\n',
      )
      .default('en'),
  })
  .strict()

```

#### `/tigris/import`

[/tigris/import docs](https://transloadit.com/docs/transcoding/tigris-import/)

Robot Parameter Zod Schema:

```ts
const tigrisImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/tigris/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/tigris/store`

[/tigris/store docs](https://transloadit.com/docs/transcoding/tigris-store/)

Robot Parameter Zod Schema:

```ts
const tigrisStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/tigris/store')
      .describe(
        '\nThe URL to the result file will be returned in the <dfn>Assembly Status JSON</dfn>.\n',
      ),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    acl: z
      .enum(['private', 'public-read'])
      .describe('\nThe permissions used for this file.\n')
      .default('public-read'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on Tigris, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds.\n\nIf this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/tlcdn/deliver`

[/tlcdn/deliver docs](https://transloadit.com/docs/transcoding/tlcdn-deliver/)

Robot Parameter Zod Schema:

```ts
const tlcdnDeliverSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    robot: z
      .literal('/tlcdn/deliver')
      .describe(
        '\nWhen you want Transloadit to tranform files on the fly, this <dfn>Robot</dfn> can cache and deliver the results close to your end-user, saving on latency and encoding volume. The use of this <dfn>Robot</dfn> is implicit when you use the <code>tlcdn.com</code> domain.\n',
      ),
  })
  .strict()

```

#### `/tus/store`

[/tus/store docs](https://transloadit.com/docs/transcoding/tus-store/)

Robot Parameter Zod Schema:

```ts
const tusStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/tus/store')
      .describe(
        "\n**Note:** This <dfn>Robot</dfn> only accepts videos. [{.alert .alert-note}]\n\n**Warning:** Vimeo's API limits the number of concurrent uploads per minute based on your Vimeo account plan. To see how many videos can be uploaded at once based on your plan, click the following [link](https://developer.vimeo.com/guidelines/rate-limiting#table-1). [{.alert .alert-warning}]\n\n## Installation\n\nSince Vimeo works with OAuth, you will need to generate [Template Credentials](https://transloadit.com/c/template-credentials/) to use this <dfn>Robot</dfn>.\n\nTo change the `title` or `description` per video, we recommend to [inject variables into your Template](https://transloadit.com/docs/topics/templates/).\n",
      ),
    endpoint: z
      .string()
      .url()
      .describe(
        "\nThe URL of the Tus-compatible server, which you're uploading files to.\n",
      ),
    headers: z
      .record(z.string())
      .describe(
        "\nOptional extra headers outside of the <dfn>Template Credentials</dfn> can be passed along within this parameter.\n\nAlthough, we recommend to exclusively use <dfn>Template Credentials</dfn>, this may be necessary if you're looking to use dynamic credentials, which isn't a feature supported by <dfn>Template Credentials</dfn>.\n",
      )
      .default({}),
    metadata: z
      .record(z.string())
      .describe(
        '\nMetadata to pass along to destination. Includes some file info by default.\n',
      )
      .default({
        filename: 'example.png',
        basename: 'example',
        extension: 'png',
      }),
    url_template: z
      .string()
      .describe(
        '\nThe URL of the file in the <dfn>Assembly Status JSON</dfn>. The following [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables) are supported. If this is not specified, the upload URL specified by the destination server will be used instead.\n',
      )
      .optional(),
    ssl_url_template: z
      .string()
      .describe(
        '\nThe SSL URL of the file in the <dfn>Assembly Status JSON</dfn>. The following [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables) are supported. If this is not specified, the upload URL specified by the destination server will be used instead, as long as it starts with `https`.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/upload/handle`

[/upload/handle docs](https://transloadit.com/docs/transcoding/upload-handle/)

Robot Parameter Zod Schema:

```ts
const uploadHandleSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/upload/handle')
      .describe(
        '\nTransloadit handles file uploads by default, so specifying this <dfn>Robot</dfn> is optional.\n\nIt can still be a good idea to define this <dfn>Robot</dfn>, though. It makes your <dfn>Assembly Instructions</dfn> explicit, and allows you to configure exactly how uploads should be handled. For example, you can extract specific metadata from the uploaded files.\n\nThere are **3 important constraints** when using this <dfn>Robot</dfn>:\n\n1. Don’t define a `use` parameter, unlike with other <dfn>Robots</dfn>.\n2. Use it only once in a single set of <dfn>Assembly Instructions</dfn>.\n3. Name the Step as `:original`.\n',
      ),
  })
  .strict()

```

#### `/video/adaptive`

[/video/adaptive docs](https://transloadit.com/docs/transcoding/video-adaptive/)

Robot Parameter Zod Schema:

```ts
const videoAdaptiveSchema = z
  .object({
    preset: VideoPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    width: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nWidth of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied width](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    height: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nHeight of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied height](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    robot: z
      .literal('/video/adaptive')
      .describe(
        '\nThis <dfn>Robot</dfn> accepts all types of video files and audio files. Do not forget to use <dfn>Step</dfn> bundling in your `use` parameter to make the <dfn>Robot</dfn> work on several input files at once.\n\nThis <dfn>Robot</dfn> is normally used in combination with [🤖/video/encode](https://transloadit.com/docs/transcoding/video-encoding/video-encode/). We have implemented video and audio encoding presets specifically for MPEG-Dash and HTTP Live Streaming support. These presets are prefixed with `"dash/"` and `"hls/"`. [View a HTTP Live Streaming demo here](https://transloadit.com/demos/video-encoding/implement-http-live-streaming/).\n\n### Required CORS settings for MPEG-Dash and HTTP Live Streaming\n\nPlaying back MPEG-Dash Manifest or HLS playlist files requires a proper CORS setup on the server-side. The file-serving server should be configured to add the following header fields to responses:\n\n```\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Methods: GET\nAccess-Control-Allow-Headers: *\n```\n\nIf the files are stored in an Amazon S3 Bucket, you can use the following [CORS definition](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html) to ensure the CORS header fields are set correctly:\n\n```json\n[\n  {\n    "AllowedHeaders": ["*"],\n    "AllowedMethods": ["GET"],\n    "AllowedOrigins": ["*"],\n    "ExposeHeaders": []\n  }\n]\n```\n\nTo set up CORS for your S3 bucket:\n\n1. Visit <https://s3.console.aws.amazon.com/s3/buckets/>\n1. Click on your bucket\n1. Click "Permissions"\n1. Edit "Cross-origin resource sharing (CORS)"\n\n### Storing Segments and Playlist files\n\nThe <dfn>Robot</dfn> gives its result files (segments, initialization segments, MPD manifest files and M3U8 playlist files) the right metadata property `relative_path`, so that you can store them easily using one of our storage <dfn>Robots</dfn>.\n\nIn the `path` parameter of the storage <dfn>Robot</dfn> of your choice, use the <dfn>Assembly Variable</dfn> `${file.meta.relative_path}` to store files in the proper paths to make the playlist files work.\n',
      ),
    technique: z
      .enum(['dash', 'hls'])
      .describe(
        '\nDetermines which streaming technique should be used. Currently supports `"dash"` for MPEG-Dash and `"hls"` for HTTP Live Streaming.\n',
      )
      .default('dash'),
    playlist_name: z
      .string()
      .describe(
        '\nThe filename for the generated manifest/playlist file. The default is `"playlist.mpd"` if your `technique` is `"dash"`, and `"playlist.m3u8"` if your `technique` is `"hls"`.\n',
      )
      .optional(),
    segment_duration: z
      .number()
      .int()
      .describe('\nThe duration for each segment in seconds.\n')
      .default(10),
    closed_captions: z
      .boolean()
      .describe(
        '\nDetermines whether you want closed caption support when using the `"hls"` technique.\n',
      )
      .default(true),
  })
  .strict()

```

#### `/video/concat`

[/video/concat docs](https://transloadit.com/docs/transcoding/video-concat/)

Robot Parameter Zod Schema:

```ts
const videoConcatSchema = z
  .object({
    preset: VideoPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    width: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nWidth of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied width](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    height: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nHeight of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied height](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    robot: z
      .literal('/video/concat')
      .describe(
        '\n**Warning:** All videos you concatenate must have the same dimensions (width and height) and the same streams (audio and video streams), otherwise you will run into errors. If your videos donʼt have the desired dimensions when passing them to [🤖/video/concat](https://transloadit.com/docs/transcoding/video-encoding/video-concat/), encode them first with [🤖/video/encode](https://transloadit.com/docs/transcoding/video-encoding/video-encode/). [{.alert .alert-warning}]\n\nItʼs possible to concatenate a virtually infinite number of video files using [🤖/video/concat](https://transloadit.com/docs/transcoding/video-encoding/video-concat/).\n',
      ),
    video_fade_seconds: z
      .number()
      .describe(
        '\nWhen used this adds a video fade in and out effect between each section of your concatenated video. The float value is used so if you want a video delay effect of 500 milliseconds between each video section you would select `0.5`, however, integer values can also be represented.\n\nThis parameter does not add a video fade effect at the beginning or end of your video. If you want to do so, create an additional [🤖/video/encode](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) Step and use our `ffmpeg` parameter as shown in this [demo](https://transloadit.com/demos/video-encoding/concatenate-fade-effect/).\n\nPlease note this parameter is independent of adding audio fades between sections.\n',
      )
      .default(1),
    audio_fade_seconds: z
      .number()
      .describe(
        '\nWhen used this adds an audio fade in and out effect between each section of your concatenated video. The float value is used so if you want an audio delay effect of 500 milliseconds between each video section you would select `0.5`, however, integer values can also be represented.\n\nThis parameter does not add an audio fade effect at the beginning or end of your video. If you want to do so, create an additional [🤖/video/encode](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) Step and use our `ffmpeg` parameter as shown in this [demo](https://transloadit.com/demos/audio-encoding/ffmpeg-fade-in-and-out/).\n\nPlease note this parameter is independent of adding video fades between sections.\n',
      )
      .default(1),
  })
  .strict()

```

#### `/video/encode`

[/video/encode docs](https://transloadit.com/docs/transcoding/video-encode/)

Robot Parameter Zod Schema:

```ts
const videoEncodeSchema = z
  .object({
    preset: VideoPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    width: z
      .union([
        z
          .union([
            z
              .any()
              .refine(
                (value) => !z.any().safeParse(value).success,
                'Invalid input: Should NOT be valid against schema',
              ),
            z.union([z.number().int().gte(1), z.null()]),
          ])
          .describe(
            "\nWidth of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied width](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
          ),
        z.any(),
      ])
      .describe(
        "\nWidth of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied width](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    height: z
      .union([
        z
          .union([
            z
              .any()
              .refine(
                (value) => !z.any().safeParse(value).success,
                'Invalid input: Should NOT be valid against schema',
              ),
            z.union([z.number().int().gte(1), z.null()]),
          ])
          .describe(
            "\nHeight of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied height](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
          ),
        z.any(),
      ])
      .describe(
        "\nHeight of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied height](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    robot: z.literal('/video/encode'),
    resize_strategy: z
      .union([
        z
          .enum(['crop', 'fit', 'fillcrop', 'min_fit', 'pad', 'stretch'])
          .describe(
            '\nSee the [available resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
          )
          .default('pad'),
        z.string().regex(new RegExp('\\${.+}')),
      ])
      .describe(
        '\nSee the [available resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
      )
      .optional(),
    zoom: z
      .boolean()
      .describe(
        '\nIf this is set to `false`, smaller videos will not be stretched to the desired width and height. For details about the impact of zooming for your preferred resize strategy, see the list of available [resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
      )
      .default(true),
    crop: z
      .union([
        z
          .object({
            x1: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
            y1: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
            x2: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
            y2: z
              .union([z.union([z.string(), z.number()]), z.null()])
              .optional(),
          })
          .strict(),
        z.string(),
      ])
      .describe(
        '\nSpecify an object containing coordinates for the top left and bottom right corners of the rectangle to be cropped from the original video(s). Values can be integers for absolute pixel values or strings for percentage based values.\n\nFor example:\n\n```json\n\n{\n  "x1": 80,\n  "y1": 100,\n  "x2": "60%",\n  "y2": "80%"\n}\n\n```\n\nThis will crop the area from `(80, 100)` to `(600, 800)` from a 1000×1000 pixels video, which is a square whose width is 520px and height is 700px. If `crop` is set, the width and height parameters are ignored, and the `resize_strategy` is set to `crop` automatically.\n\nYou can also use a JSON string of such an object with coordinates in similar fashion: `"{ "x1": <Integer>, "y1": <Integer>, "x2": <Integer>, "y2": <Integer> }"`\n',
      )
      .optional(),
    background: z
      .union([
        z
          .string()
          .regex(new RegExp('^#?[0-9a-fA-F]{8}$'))
          .describe(
            '\nThe background color of the resulting video the `"rrggbbaa"` format (red, green, blue, alpha) when used with the `"pad"` resize strategy. The default color is black.\n',
          )
          .default('#00000000'),
        z.any(),
      ])
      .describe(
        '\nThe background color of the resulting video the `"rrggbbaa"` format (red, green, blue, alpha) when used with the `"pad"` resize strategy. The default color is black.\n',
      )
      .optional(),
    rotate: z
      .union([
        z.literal(0),
        z.literal(90),
        z.literal(180),
        z.literal(270),
        z.literal(360),
        z.literal(false),
      ])
      .describe(
        '\nForces the video to be rotated by the specified degree integer. Currently, only multiples of `90` are supported. We automatically correct the orientation of many videos when the orientation is provided by the camera. This option is only useful for videos requiring rotation because it was not detected by the camera. If you set `rotate` to `false` no rotation is performed, even if the metadata contains such instructions.\n',
      )
      .optional(),
    hint: z
      .boolean()
      .describe('\nEnables hinting for mp4 files, for RTP/RTSP streaming.\n')
      .default(false),
    turbo: z
      .boolean()
      .describe(
        '\nSplits the video into multiple chunks so that each chunk can be encoded in parallel before all encoded chunks are stitched back together to form the result video. This comes at the expense of extra <dfn>Priority Job Slots</dfn> and may prove to be counter-productive for very small video files.\n',
      )
      .default(false),
    chunk_duration: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nAllows you to specify the duration of each chunk when `turbo` is set to `true`. This means you can take advantage of that feature while using fewer <dfn>Priority Job Slots</dfn>. For instance, the longer each chunk is, the fewer <dfn>Encoding Jobs</dfn> will need to be used.\n',
      )
      .optional(),
    freeze_detect: z
      .boolean()
      .describe(
        '\nExamines the transcoding result file for video freeze frames and re-transcodes the video a second time if they are found. This is useful when you are using `turbo: true` because freeze frames can sometimes happen there. The re-transcode would then happen without turbo mode.\n',
      )
      .default(false),
    watermark_url: z
      .string()
      .describe(
        '\nA URL indicating a PNG image to be overlaid above this image. You can also [supply the watermark via another Assembly Step](https://transloadit.com/docs/transcoding/video-encoding/video-encode/#watermark-parameters-video-encode).\n',
      )
      .default(''),
    watermark_position: z
      .union([
        z.enum([
          'bottom',
          'bottom-left',
          'bottom-right',
          'center',
          'left',
          'right',
          'top',
          'top-left',
          'top-right',
        ]),
        z.array(z.any()),
      ])
      .describe(
        '\nThe position at which the watermark is placed.\n\nAn array of possible values can also be specified, in which case one value will be selected at random, such as `[ "center", "left", "bottom-left", "bottom-right" ]`.\n\nThis setting puts the watermark in the specified corner. To use a specific pixel offset for the watermark, you will need to add the padding to the image itself.\n',
      )
      .default('center'),
    watermark_x_offset: z
      .number()
      .int()
      .describe(
        "\nThe x-offset in number of pixels at which the watermark will be placed in relation to the position it has due to `watermark_position`.\n\nValues can be both positive and negative and yield different results depending on the `watermark_position` parameter. Positive values move the watermark closer to the image's center point, whereas negative values move the watermark further away from the image's center point.\n",
      )
      .default(0),
    watermark_y_offset: z
      .number()
      .int()
      .describe(
        "\nThe y-offset in number of pixels at which the watermark will be placed in relation to the position it has due to `watermark_position`.\n\nValues can be both positive and negative and yield different results depending on the `watermark_position` parameter. Positive values move the watermark closer to the image's center point, whereas negative values move the watermark further away from the image's center point.\n",
      )
      .default(0),
    watermark_size: z
      .string()
      .regex(new RegExp('^\\d+%$'))
      .describe(
        '\nThe size of the watermark, as a percentage, such as `"50%"`. How the watermark is resized greatly depends on the `watermark_resize_strategy`.\n',
      )
      .optional(),
    watermark_resize_strategy: z
      .enum(['area', 'fit', 'stretch'])
      .describe(
        '\nTo explain how the resize strategies work, let\'s assume our target video size is 800×800 pixels and our watermark image is 400×300 pixels. Let\'s also assume, the `watermark_size` parameter is set to `"25%"`.\n\nFor the `"fit"` resize strategy, the watermark is scaled so that the longer side of the watermark takes up 25% of the corresponding video side. And the other side is scaled according to the aspect ratio of the watermark image. So with our watermark, the width is the longer side, and 25% of the video size would be 200px. Hence, the watermark would be resized to 200×150 pixels. If the `watermark_size` was set to `"50%"`", it would be resized to 400×300 pixels (so just left at its original size).\n\nFor the `"stretch"` resize strategy, the watermark image is stretched (meaning, it is resized without keeping its aspect ratio in mind) so that both sides take up 25% of the corresponding video side. Since our video is 800×800 pixels, for a watermark size of 25% the watermark would be resized to 200×200 pixels. Its height would appear stretched, because keeping the aspect ratio in mind it would be resized to 200×150 pixels instead.\n\nFor the `"area"` resize strategy, the watermark is resized (keeping its aspect ratio in check) so that it covers `"xx%"` of the video\'s surface area. The value from `watermark_size` is used for the percentage area size.\n',
      )
      .default('fit'),
    watermark_start_time: z
      .number()
      .describe(
        '\nThe delay in seconds from the start of the video for the watermark to appear. By default the watermark is immediately shown.\n',
      )
      .default(0),
    watermark_duration: z
      .number()
      .describe(
        '\nThe duration in seconds for the watermark to be shown. Can be used together with `watermark_start_time` to create nice effects. The default value is `-1.0`, which means that the watermark is shown for the entire duration of the video.\n',
      )
      .default(-1),
    watermark_opacity: z
      .number()
      .gte(0)
      .lte(1)
      .describe(
        '\nThe opacity of the watermark. Valid values are between `0` (invisible) and `1.0` (full visibility).\n',
      )
      .default(1),
    segment: z
      .boolean()
      .describe(
        "\nSplits the file into multiple parts, to be used for Apple's [HTTP Live Streaming](https://developer.apple.com/resources/http-streaming/).\n",
      )
      .default(false),
    segment_duration: z
      .number()
      .int()
      .gte(1)
      .describe(
        '\nSpecifies the length of each HTTP segment. This is optional, and the default value as recommended by Apple is `10`. Do not change this value unless you have a good reason.\n',
      )
      .default(10),
    segment_prefix: z
      .string()
      .describe(
        '\nThe prefix used for the naming. For example, a prefix of `"segment_"` would produce files named `"segment_0.ts"`, `"segment_1.ts"` and so on. This is optional, and defaults to the base name of the input file. Also see the related `segment_name` parameter.\n',
      )
      .default(''),
    segment_name: z
      .string()
      .describe(
        '\nThe name used for the final segment. Available variables are `${segment_prefix}`, `${segment_number}` and `${segment_id}` (which is a UUIDv4 without dashes).\n',
      )
      .default(''),
  })
  .strict()

```

#### `/video/merge`

[/video/merge docs](https://transloadit.com/docs/transcoding/video-merge/)

Robot Parameter Zod Schema:

```ts
const videoMergeSchema = z
  .object({
    preset: VideoPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    width: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nWidth of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied width](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    height: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nHeight of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied height](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    robot: z.literal('/video/merge'),
    resize_strategy: z
      .enum(['crop', 'fit', 'fillcrop', 'min_fit', 'pad', 'stretch'])
      .describe(
        "\nIf the given width/height parameters are bigger than the input image's dimensions, then the `resize_strategy` determines how the image will be resized to match the provided width/height. See the [available resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n",
      )
      .default('pad'),
    background: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{8}$'))
      .describe(
        '\nThe background color of the resulting video the `"rrggbbaa"` format (red, green, blue, alpha) when used with the `"pad"` resize strategy. The default color is black.\n',
      )
      .default('#00000000'),
    framerate: z
      .union([
        z.number().int().gte(1),
        z.string().regex(new RegExp('^\\d+(?:\\/\\d+)?$')),
      ])
      .describe(
        '\nWhen merging images to generate a video this is the input framerate. A value of "1/5" means each image is given 5 seconds before the next frame appears (the inverse of a framerate of "5"). Likewise for "1/10", "1/20", etc. A value of "5" means there are 5 frames per second.\n',
      )
      .default('1/5'),
    image_durations: z
      .array(z.number())
      .describe(
        '\nWhen merging images to generate a video this allows you to define how long (in seconds) each image will be shown inside of the video. So if you pass 3 images and define `[2.4, 5.6, 9]` the first image will be shown for 2.4s, the second image for 5.6s and the last one for 9s. The `duration` parameter will automatically be set to the sum of the image_durations, so `17` in our example. It can still be overwritten, though, in which case the last image will be shown until the defined duration is reached.\n',
      )
      .default([]),
    duration: z
      .number()
      .describe(
        '\nWhen merging images to generate a video or when merging audio and video this is the desired target duration in seconds. The float value can take one decimal digit. If you want all images to be displayed exactly once, then you can set the duration according to this formula: `duration = numberOfImages / framerate`. This also works for the inverse framerate values like `1/5`.\n\nIf you set this value to `null` (default), then the duration of the input audio file will be used when merging images with an audio file.\n\nWhen merging audio files and video files, the duration of the longest video or audio file is used by default.\n',
      )
      .default(5),
    audio_delay: z
      .number()
      .describe(
        '\nWhen merging a video and an audio file, and when merging images and an audio file to generate a video, this is the desired delay in seconds for the audio file to start playing. Imagine you merge a video file without sound and an audio file, but you wish the audio to start playing after 5 seconds and not immediately, then this is the parameter to use.\n',
      )
      .default(0),
    loop: z
      .boolean()
      .describe(
        '\n  Determines whether the shorter media file should be looped to match the duration of the longer one. For example, if you merge a 1-minute video with a 3-minute audio file and enable this option, the video will play three times in a row to match the audio length.',
      )
      .default(false),
    replace_audio: z
      .boolean()
      .describe(
        '\nDetermines whether the audio of the video should be replaced with a provided audio file.\n',
      )
      .default(false),
    vstack: z
      .boolean()
      .describe(
        '\nStacks the input media vertically. All streams need to have the same pixel format and width - so consider using a [/video/encode](https://transloadit.com/docs/transcoding/video-encoding/video-encode/) <dfn>Step</dfn> before using this parameter to enforce this.\n',
      )
      .default(false),
  })
  .strict()

```

#### `/video/subtitle`

[/video/subtitle docs](https://transloadit.com/docs/transcoding/video-subtitle/)

Robot Parameter Zod Schema:

```ts
const videoSubtitleSchema = z
  .object({
    preset: VideoPresetSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    width: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nWidth of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied width](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    height: z
      .union([z.number().int().gte(1), z.null()])
      .describe(
        "\nHeight of the new video, in pixels.\n\nIf the value is not specified and the `preset` parameter is available, the `preset`'s [supplied height](https://transloadit.com/docs/transcoding/video-encoding/video-presets/) will be implemented.\n",
      )
      .optional(),
    robot: z
      .literal('/video/subtitle')
      .describe(
        '\nThis <dfn>Robot</dfn> supports both SRT and VTT subtitle files.\n',
      ),
    subtitles_type: z
      .enum(['burned', 'external', 'burn'])
      .describe(
        '\nDetermines if subtitles are added as a separate stream to the video (value `"external"`) that then can be switched on and off in your video player, or if they should be burned directly into the video (value `"burned"` or `"burn"`) so that they become part of the video stream.\n',
      )
      .default('external'),
    border_style: z
      .enum(['box', 'outline', 'shadow'])
      .describe(
        '\nSpecifies the style of the subtitle. Use the `border_color` parameter to specify the color of the border.\n',
      )
      .default('outline'),
    border_color: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{8}$'))
      .describe(
        '\nThe color for the subtitle border. The first two hex digits specify the alpha value of the color.\n',
      )
      .default('40000000'),
    font: z
      .string()
      .describe(
        '\nThe font family to use. Also includes boldness and style of the font.\n\n[Here](https://transloadit.com/docs/supported-formats/fonts/) is a list of all supported fonts.\n',
      )
      .default('Arial'),
    font_color: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{6}$'))
      .describe(
        '\nThe color of the subtitle text. The first two hex digits specify the alpha value of the color.\n',
      )
      .default('FFFFFF'),
    font_size: z
      .number()
      .int()
      .gte(1)
      .describe('\nSpecifies the size of the text.\n')
      .default(16),
    position: z
      .enum([
        'bottom',
        'bottom-left',
        'bottom-right',
        'center',
        'left',
        'right',
        'top',
        'top-left',
        'top-right',
      ])
      .describe('\nSpecifies the position of the subtitles.\n')
      .default('bottom'),
  })
  .strict()

```

#### `/video/thumbs`

[/video/thumbs docs](https://transloadit.com/docs/transcoding/video-thumbs/)

Robot Parameter Zod Schema:

```ts
const videoThumbsSchema = z
  .object({
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    ffmpeg_stack: FfmpegStackSchema,
    use: UseSchema,
    ffmpeg: FfmpegSchema,
    robot: z
      .literal('/video/thumbs')
      .describe(
        '\n**Note:** Even though thumbnails are extracted from videos in parallel, we sort the thumbnails before adding them to the Assembly results. So the order in which they appear there reflects the order in which they appear in the video. You can also make sure by checking the <code>thumb_index</code> meta key. [{.alert .alert-note}]\n',
      ),
    count: z
      .number()
      .int()
      .gte(1)
      .lte(999)
      .describe(
        '\nThe number of thumbnails to be extracted. As some videos have incorrect durations, the actual number of thumbnails generated may be less in rare cases. The maximum number of thumbnails we currently allow is 999.\n\nThe thumbnails are taken at regular intervals, determined by dividing the video duration by the count. For example, a count of 3 will produce thumbnails at 25%, 50% and 75% through the video.\n\nTo extract thumbnails for specific timestamps, use the `offsets` parameter.\n',
      )
      .default(8),
    offsets: z
      .union([
        z.array(z.number().int()),
        z.array(z.string().regex(new RegExp('^\\d+%$'))),
      ])
      .describe(
        '\nAn array of offsets representing seconds of the file duration, such as `[ 2, 45, 120 ]`. Millisecond durations of a file can also be used by using decimal place values. For example, an offset from 1250 milliseconds would be represented with `1.25`. Offsets can also be percentage values such as `[ "2%", "50%", "75%" ]`.\n\nThis option cannot be used with the `count` parameter, and takes precedence if both are specified. Out-of-range offsets are silently ignored.\n',
      )
      .default([]),
    format: z
      .enum(['jpeg', 'jpg', 'png'])
      .describe(
        '\nThe format of the extracted thumbnail. Supported values are `"jpg"`, `"jpeg"` and `"png"`. Even if you specify the format to be `"jpeg"` the resulting thumbnails will have a `"jpg"` file extension.\n',
      )
      .default('jpeg'),
    width: z
      .number()
      .int()
      .gte(1)
      .lte(1920)
      .describe(
        '\nThe width of the thumbnail, in pixels. Defaults to the original width of the video.\n',
      )
      .optional(),
    height: z
      .number()
      .int()
      .gte(1)
      .lte(1080)
      .describe(
        '\nThe height of the thumbnail, in pixels. Defaults to the original height of the video.\n',
      )
      .optional(),
    resize_strategy: z
      .enum(['crop', 'fit', 'fillcrop', 'min_fit', 'pad', 'stretch'])
      .describe(
        '\nOne of the [available resize strategies](https://transloadit.com/docs/transcoding/image-manipulation/image-resize/#resize-strategies).\n',
      )
      .default('pad'),
    background: z
      .string()
      .regex(new RegExp('^#?[0-9a-fA-F]{8}$'))
      .describe(
        '\nThe background color of the resulting thumbnails in the `"rrggbbaa"` format (red, green, blue, alpha) when used with the `"pad"` resize strategy. The default color is black.\n',
      )
      .default('#00000000'),
    rotate: z
      .union([
        z.literal(0),
        z.literal(90),
        z.literal(180),
        z.literal(270),
        z.literal(360),
      ])
      .describe(
        '\nForces the video to be rotated by the specified degree integer. Currently, only multiples of 90 are supported. We automatically correct the orientation of many videos when the orientation is provided by the camera. This option is only useful for videos requiring rotation because it was not detected by the camera.\n',
      )
      .default(0),
  })
  .strict()

```

#### `/vimeo/store`

[/vimeo/store docs](https://transloadit.com/docs/transcoding/vimeo-store/)

Robot Parameter Zod Schema:

```ts
const vimeoStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z.literal('/vimeo/store'),
    title: z
      .string()
      .describe('\nThe title of the video to be displayed on Vimeo.\n'),
    description: z
      .string()
      .describe('\nThe description of the video to be displayed on Vimeo.\n'),
    acl: z
      .enum([
        'anybody',
        'contacts',
        'disable',
        'nobody',
        'password',
        'unlisted',
        'users',
      ])
      .describe(
        '\nControls access permissions for the video. Here are the valid values:\n\n- `"anybody"` — anyone can access the video.\n- `"contacts"` — only those who follow the owner on Vimeo can access the video.\n- `"disable"` — the video is embeddable, but it\'s hidden on Vimeo and can\'t be played.\n- `"nobody"` — no one except the owner can access the video.\n- `"password"` — only those with the password can access the video.\n- `"unlisted"` — only those with the private link can access the video.\n- `"users"` — only Vimeo members can access the video.\n',
      )
      .default('anybody'),
    password: z
      .string()
      .describe(
        '\nThe password to access the video if `acl` is `"password"`.\n',
      )
      .optional(),
    showcases: z
      .array(z.string())
      .describe(
        '\nAn array of string IDs of showcases that you want to add the video to. The IDs can be found when browsing Vimeo. For example `https://vimeo.com/manage/showcases/[SHOWCASE_ID]/info`.\n',
      )
      .default([]),
    downloadable: z
      .boolean()
      .describe(
        '\nWhether or not the video can be downloaded from the Vimeo website.\n\nOnly set this to `true` if you have unlocked this feature in your Vimeo accounting by upgrading to their "Pro" plan. If you use it while on their Freemium plan, the Vimeo API will return an `"Invalid parameter supplied"` error.\n',
      )
      .default(false),
    folder_id: z
      .union([
        z
          .string()
          .describe(
            '\nThe ID of the folder to which the video is uploaded.\n\nWhen visiting one of your folders, the URL is similar to `https://vimeo.com/manage/folders/xxxxxxxx`. The folder_id would be `"xxxxxxxx"`.\n',
          )
          .default(null),
        z
          .null()
          .describe(
            '\nThe ID of the folder to which the video is uploaded.\n\nWhen visiting one of your folders, the URL is similar to `https://vimeo.com/manage/folders/xxxxxxxx`. The folder_id would be `"xxxxxxxx"`.\n',
          )
          .default(null),
      ])
      .describe(
        '\nThe ID of the folder to which the video is uploaded.\n\nWhen visiting one of your folders, the URL is similar to `https://vimeo.com/manage/folders/xxxxxxxx`. The folder_id would be `"xxxxxxxx"`.\n',
      )
      .default(null),
  })
  .strict()

```

#### `/wasabi/import`

[/wasabi/import docs](https://transloadit.com/docs/transcoding/wasabi-import/)

Robot Parameter Zod Schema:

```ts
const wasabiImportSchema = z
  .object({
    credentials: CredentialsSchema,
    ignore_errors: IgnoreErrorsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z.literal('/wasabi/import'),
    path: z
      .union([z.string(), z.array(z.string())])
      .describe(
        "\nThe path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: `images/avatar.jpg`.\n\nIf it points to a directory, indicated by a trailing slash (`/`), then all files that are direct descendants of this directory will be imported. For example: `images/`.\n\nDirectories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the `recursive` parameter.\n\nIf you want to import all files from the root directory, please use `/` as the value here. In this case, make sure all your objects belong to a path. If you have objects in the root of your bucket that aren't prefixed with `/`, you'll receive an error: `A client error (NoSuchKey) occurred when calling the GetObject operation: The specified key does not exist.`\n\nYou can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.\n",
      ),
    recursive: z
      .boolean()
      .describe(
        '\nSetting this to `true` will enable importing files from subfolders and sub-subfolders, etc. of the given path.\n\nPlease use the pagination parameters `page_number` and `files_per_page` wisely here.\n',
      )
      .default(false),
    page_number: z
      .number()
      .int()
      .describe(
        '\nThe pagination page number. For now, in order to not break backwards compatibility in non-recursive imports, this only works when recursive is set to `true`.\n\nWhen doing big imports, make sure no files are added or removed from other scripts within your path, otherwise you might get weird results with the pagination.\n',
      )
      .default(1),
    files_per_page: z
      .number()
      .int()
      .describe(
        '\nThe pagination page size. This only works when recursive is `true` for now, in order to not break backwards compatibility in non-recursive imports.\n',
      )
      .default(1000),
  })
  .strict()

```

#### `/wasabi/store`

[/wasabi/store docs](https://transloadit.com/docs/transcoding/wasabi-store/)

Robot Parameter Zod Schema:

```ts
const wasabiStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    bucket: z.string().optional(),
    host: z.string().optional(),
    key: z.string().optional(),
    secret: z.string().optional(),
    robot: z
      .literal('/wasabi/store')
      .describe(
        '\nThe URL to the result file will be returned in the <dfn>Assembly Status JSON</dfn>.\n',
      ),
    path: z
      .string()
      .describe(
        '\nThe path at which the file is to be stored. This may include any available [Assembly variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.\n',
      )
      .default('${unique_prefix}/${file.url_name}'),
    acl: z
      .enum(['private', 'public-read'])
      .describe('\nThe permissions used for this file.\n')
      .default('public-read'),
    headers: z
      .record(z.string())
      .describe(
        '\nAn object containing a list of headers to be set for this file on Wasabi Spaces, such as `{ FileURL: "${file.url_name}" }`. This can also include any available [Assembly Variables](https://transloadit.com/docs/topics/assembly-instructions/#assembly-variables).\n\nObject Metadata can be specified using `x-amz-meta-*` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).\n',
      )
      .default({ 'Content-Type': '${file.mime}' }),
    sign_urls_for: z
      .number()
      .int()
      .gte(0)
      .describe(
        '\nThis parameter provides signed URLs in the result JSON (in the `signed_ssl_url` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.\n',
      )
      .optional(),
  })
  .strict()

```

#### `/youtube/store`

[/youtube/store docs](https://transloadit.com/docs/transcoding/youtube-store/)

Robot Parameter Zod Schema:

```ts
const youtubeStoreSchema = z
  .object({
    credentials: CredentialsSchema,
    output_meta: OutputMetaSchema,
    result: ResultSchema,
    use: UseSchema,
    robot: z
      .literal('/youtube/store')
      .describe(
        '\n**Note:** This <dfn>Robot</dfn> only accepts videos. [{.alert .alert-note}]\n\n## Installation\n\nSince YouTube works with OAuth, you will need to generate [Template Credentials](https://transloadit.com/c/template-credentials/) to use this <dfn>Robot</dfn>.\n\nTo change the `title`, `description`, `category`, or `keywords` per video, we recommend to [inject variables into your Template](https://transloadit.com/docs/topics/templates/).\n\n## Adding a thumbnail image to your video\n\nYou can add a custom thumbnail to your video on YouTube by using our `"as"` syntax for the `"use"` parameter to supply both a video and an image to the step:\n\n```json\n"exported": {\n  "use": [\n    { "name": "video_encode_step", "as": "video" },\n    { "name": "image_resize_step", "as": "image" },\n  ],\n  ...\n},\n```\n\nIf you encounter an error such as "The authenticated user doesnʼt have permissions to upload and set custom video thumbnails", you should go to your YouTube account and try adding a custom thumbnail to one of your existing videos. Youʼll be prompted to add your phone number. Once youʼve added it, the error should go away.\n',
      ),
    title: z
      .string()
      .max(80)
      .describe(
        '\nThe title of the video to be displayed on YouTube.\n\nNote that since the YouTube API requires titles to be within 80 characters, longer titles may be truncated.\n',
      ),
    description: z
      .string()
      .describe(
        '\nThe description of the video to be displayed on YouTube. This can be up to 5000 characters, including `\\n` for new-lines.\n',
      ),
    category: z
      .enum([
        'autos & vehicles',
        'comedy',
        'education',
        'entertainment',
        'film & animation',
        'gaming',
        'howto & style',
        'music',
        'news & politics',
        'people & blogs',
        'pets & animals',
        'science & technology',
        'sports',
        'travel & events',
      ])
      .describe('\nThe category to which this video will be assigned.\n'),
    keywords: z
      .string()
      .describe(
        '\nTags used to describe the video, separated by commas. These tags will also be displayed on YouTube.\n',
      ),
    visibility: z
      .enum(['public', 'private', 'unlisted'])
      .describe('\nDefines the visibility of the uploaded video.\n'),
  })
  .strict()

```


## More resources

- [Getting Started](https://transloadit.com/docs/): Introduction to Transloadit's core concepts
- [Assembly Instructions](https://transloadit.com/docs/topics/assembly-instructions/): How to create processing workflows
- [Templates](https://transloadit.com/docs/topics/templates/): Learn about reusable Assembly Instructions
- [API Reference](https://transloadit.com/docs/api/): Detailed API documentation
- [Community Forum](https://community.transloadit.com/): Get help from other Transloadit users
- [Status Page](https://status.transloadit.com/): Real-time status of our services
- [Pricing](https://transloadit.com/pricing/): Transloadit pricing plans
- [Blog](https://transloadit.com/blog/): Latest news and updates

this file is 245kB