Skip to content

DocsAPI referenceOperations

Join files

Plays the inputs one after another, each trimmed with start and end if you like, as one video or sound file. A part of a video may cross into the one before it with transition. Creates the same Job as POST /v1/jobs, with operation set.

POST /v1/concat

Needs an API key: Authorization: Bearer $VIDEXO_API_KEY.

Parameters

Parameters
NameInTypeDescription
idempotency-key headerstring, up to 255 charactersMakes retries safe for 24 hours. Up to 255 printable ASCII characters. One key space per account across every endpoint that creates a job.

Body ConcatRequest

Send the fields of one of these bodies, never both. Each has its own required fields.

ConcatVideoRequest

A video concatenation: every part fitted into a resize box.

Fields of ConcatVideoRequest
NameTypeDescription
inputs requiredarray of string or object or object
extra_inputs map of string to string or object
webhook_url string, URL, up to 2,048 characters or nullAn https URL that gets the job when it ends (M4).
metadata map of string to string, up to 500 charactersYour own string pairs, returned with the job and its webhook: at most 20 keys of up to 40 characters, values up to 500.
filename string, up to 105 charactersThe stored file name, <name>.<format> by default; one extension, matching format.
format one of mp4, mov, webm, mkv, ts, mp3, m4a, aac, wav, flac, ogg, opus, jpg, png, gif, jsonThe container or image format; from filename, or the type's default.
trim objectThe part of the input to use: start, and end or duration.
crop objectA rectangle of the input frame, in input pixels.
rotate numberDegrees clockwise.
flip one of horizontal, verticalMirror the picture.
resize objectA box: width and height, or one of them and aspect; every part is fitted into it.
color objectBrightness, contrast, saturation, gamma and hue.
sharpen objectAn unsharp mask.
blur objectA box blur of the whole frame, or of up to 4 regions.
overlays array of objectImages or videos drawn over the picture, in order.
text array of TextLayerUp to 8 text layers, drawn after overlays in order.
subtitles SubtitlesCaptions from an SRT or WebVTT input, burned into the picture at their cue times.
speed number, 0.25 to 4How fast it plays, 0.25 to 4; the sound keeps its pitch.
fps number, 1 to 120A constant frame rate.
fade objectFade in at the start and out at the end; out needs trim.duration or trim.end.
video objectThe video encoder: codec, quality or CRF, preset, maximum bitrate, pixel format.
audio boolean or objectfalse for no sound, or the audio encoder and filters.
visualize objectA waveform or spectrum video drawn from the input's sound.
strip_metadata booleanDrop the input's global and stream metadata (GPS, device tags).
preset one of web-720p, web-1080p, social-vertical, squareA video preset (GET /v1/presets); its options are the defaults and the output's own fields win.
type stringvideo by default.

ConcatAudioRequest

An audio concatenation ("type": "audio"): sound only.

Fields of ConcatAudioRequest
NameTypeDescription
inputs requiredarray of string or object or object
extra_inputs map of string to string or object
webhook_url string, URL, up to 2,048 characters or nullAn https URL that gets the job when it ends (M4).
metadata map of string to string, up to 500 charactersYour own string pairs, returned with the job and its webhook: at most 20 keys of up to 40 characters, values up to 500.
filename string, up to 105 charactersThe stored file name, <name>.<format> by default; one extension, matching format.
format one of mp4, mov, webm, mkv, ts, mp3, m4a, aac, wav, flac, ogg, opus, jpg, png, gif, jsonThe container or image format; from filename, or the type's default.
trim objectThe part of the input to use: start, and end or duration.
speed number, 0.25 to 4How fast it plays, 0.25 to 4; the sound keeps its pitch.
fade objectFade in at the start and out at the end; out needs trim.duration or trim.end.
audio boolean or objectfalse for no sound, or the audio encoder and filters.
strip_metadata booleanDrop the input's global and stream metadata (GPS, device tags).
preset one of podcast-audioAn audio preset (GET /v1/presets); its options are the defaults and the output's own fields win.
type requiredstring

Request

bash
curl "$VIDEXO_API_URL/v1/concat" \
  -H "Authorization: Bearer $VIDEXO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "inputs": [
    {
      "source": "https://videxo.io/samples/talk.mp4",
      "start": 0,
      "end": 5
    },
    {
      "source": "https://videxo.io/samples/talk.mp4",
      "start": 10,
      "end": 15
    }
  ],
  "resize": {
    "width": 1920,
    "height": 1080,
    "fit": "pad"
  }
}'

Response

202 JSON
{
  "id": "job_3k9x0c2mfq8w1n7r5t4b6v2z",
  "state": "queued",
  "kind": "operations",
  "operation": "concat",
  "spec": {
    "inputs": {
      "part_1": {
        "url": "https://videxo.io/samples/talk.mp4"
      }
    },
    "outputs": [
      {
        "name": "video",
        "type": "video",
        "concat": [
          {
            "input": "part_1",
            "start": 0,
            "end": 5
          },
          {
            "input": "part_1",
            "start": 10,
            "end": 15
          }
        ],
        "filename": "video.mp4",
        "format": "mp4",
        "resize": {
          "width": 1920,
          "height": 1080,
          "fit": "pad"
        },
        "video": {
          "codec": "h264",
          "crf": 23,
          "encoder_preset": "veryfast",
          "pixel_format": "yuv420p",
          "faststart": true
        },
        "audio": {
          "codec": "aac",
          "bitrate": "128k"
        }
      }
    ]
  },
  "command": "-t 5 -i {{in_part_1}} -ss 10 -t 5 -i {{in_part_1}} -filter_complex \"[0:v]setpts=PTS-STARTPTS,scale=1920:1080:force_original_aspect_ratio=decrease:force_divisible_by=2,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x000000,setsar=1,fps=30[o0c0v];[0:a]asetpts=PTS-STARTPTS[o0c0a];[1:v]setpts=PTS-STARTPTS,scale=1920:1080:force_original_aspect_ratio=decrease:force_divisible_by=2,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x000000,setsar=1,fps=30[o0c1v];[1:a]asetpts=PTS-STARTPTS[o0c1a];[o0c0v][o0c0a][o0c1v][o0c1a]concat=n=2:v=1:a=1[o0cv][o0ca]\" -map [o0cv] -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -map [o0ca] -c:a aac -b:a 128k -movflags +faststart {{out_video}}",
  "input_files": {
    "in_part_1": "https://videxo.io/samples/talk.mp4"
  },
  "output_files": {
    "out_video": "video.mp4"
  },
  "ffmpeg_command": "ffmpeg -t 5 -i https://videxo.io/samples/talk.mp4 -ss 10 -t 5 -i https://videxo.io/samples/talk.mp4 -filter_complex '[0:v]setpts=PTS-STARTPTS,scale=1920:1080:force_original_aspect_ratio=decrease:force_divisible_by=2,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x000000,setsar=1,fps=30[o0c0v];[0:a]asetpts=PTS-STARTPTS[o0c0a];[1:v]setpts=PTS-STARTPTS,scale=1920:1080:force_original_aspect_ratio=decrease:force_divisible_by=2,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x000000,setsar=1,fps=30[o0c1v];[1:a]asetpts=PTS-STARTPTS[o0c1a];[o0c0v][o0c0a][o0c1v][o0c1a]concat=n=2:v=1:a=1[o0cv][o0ca]' -map '[o0cv]' -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -map '[o0ca]' -c:a aac -b:a 128k -movflags +faststart video.mp4",
  "steps": [
    {
      "tool": "ffmpeg",
      "inputs": [
        "part_1"
      ],
      "outputs": [
        "video"
      ],
      "command": "ffmpeg -t 5 -i https://videxo.io/samples/talk.mp4 -ss 10 -t 5 -i https://videxo.io/samples/talk.mp4 -filter_complex '[0:v]setpts=PTS-STARTPTS,scale=1920:1080:force_original_aspect_ratio=decrease:force_divisible_by=2,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x000000,setsar=1,fps=30[o0c0v];[0:a]asetpts=PTS-STARTPTS[o0c0a];[1:v]setpts=PTS-STARTPTS,scale=1920:1080:force_original_aspect_ratio=decrease:force_divisible_by=2,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=0x000000,setsar=1,fps=30[o0c1v];[1:a]asetpts=PTS-STARTPTS[o0c1a];[o0c0v][o0c0a][o0c1v][o0c1a]concat=n=2:v=1:a=1[o0cv][o0ca]' -map '[o0cv]' -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -map '[o0ca]' -c:a aac -b:a 128k -movflags +faststart video.mp4"
    }
  ],
  "webhook_url": null,
  "metadata": {},
  "progress": null,
  "error": null,
  "outputs": [],
  "usage": null,
  "created_at": "2026-11-04T12:00:00.000Z",
  "started_at": null,
  "finished_at": null
}

Responses

Responses
StatusBodyWhen
200JobThe job this Idempotency-Key made earlier (same endpoint and body).
202JobThe job, queued.
400Probleminvalid_request (with errors) or command_invalid (with problems)
401Problemauthentication_failed (missing_api_key, invalid_api_key, api_key_revoked, api_key_expired)
402Problemusage_cap_reached or out_of_credits
403Problempermission_denied (account_disabled, token_scope)
404Problemnot_found (upload)
409Problemconflict (idempotency_key_reused)
413Problemlimit_exceeded (request_body_size): the body is larger than 512 KB
415Probleminvalid_request (not_json): the body is not sent as application/json
429Problemrate_limited, with Retry-After in seconds
500Probleminternal_error
503Problemservice_unavailable (temporary): the account's free credits are still being granted, or a part of the service did not answer