---
title: "Join files, free for the first hour"
method: POST
path: "/api/try/join"
tags: ["Free API"]
---

# Join files, free for the first hour

`POST /api/try/join`

## Request

- Base URL: `https://audo.ai`
- URL: `https://audo.ai/api/try/join`
- Auth: one of:
  - none
  - HTTP bearer

Free for the first hour of the file, 10 times a day, without an account. With an API key (Authorization: Bearer <key>), the same request processes the whole file with credits ($0.01/min, 1 credits a minute; 1 credit is 1 US cent) when the balance covers it, and otherwise the free part. free=true always asks for the free part, and free=false always for the whole file. With exhausted quota, free=true returns 429; omitted free with insufficient balance returns 402. free=false with insufficient balance returns 402 with no fallback. Use an explicitly approved positive max_credits for paid automation. A request takes up to 100 MB of files either way (without a key, what its links fetch counts too), and links are fetched one at a time; upload a larger file in parts with POST /api/v1/files, then start the job with POST /api/v1/jobs. With an API key, an Idempotency-Key header makes a repeated request return the first one's job instead of starting another. Examples save unclassified response.body and response.headers: branch on HTTP status and Content-Type before naming media. See /docs/api#responses for the complete response client. Cut examples explicitly remove the named ranges; mode=keep retains them instead. The request waits up to about 30 seconds for the result. A job that takes longer, or a request with Prefer: respond-async, gets 202 with the job's link to check on. 

    curl -F file=@intro.wav -F file=@episode.wav -F file=@outro.wav https://audo.ai/api/try/join -D response.headers -o response.body

## Headers

- `Prefer` string
- `Idempotency-Key` string

## Request body

- union
  - object
    - `url` string[], required: Or links, in order
    - `file_token` string[]: Or file tokens from POST /api/try/uploads, in order
    - `crossfade_ms` integer: A crossfade between files, in milliseconds (0 to 5000), such as 500. Default 0.
    - `match_loudness` boolean: Matches the files' loudness before joining. Default true.
    - `output_format` 'same' | 'wav' | 'mp3' | 'm4a' | 'flac': The result's format: same (as the first file), wav, mp3, m4a, or flac. Default same.
    - `max_credits` integer: With an API key only. The most this job may cost, in credits (1 credit is 1 US cent), such as 200. A job that would cost more doesn't start.
    - `free` boolean: With an API key only. true processes only the first hour of the result, at no cost, a few times a day. false always processes the whole file with credits. Left out, the whole file when the balance covers it, otherwise the first hour of the result free if quota is available (otherwise insufficient_balance / 402). true with exhausted quota returns free_limit_reached / 429; false with insufficient balance returns 402, without fallback.
  - object
    - `url` string[]: Or links, in order
    - `file_token` string[], required: Or file tokens from POST /api/try/uploads, in order
    - `crossfade_ms` integer: A crossfade between files, in milliseconds (0 to 5000), such as 500. Default 0.
    - `match_loudness` boolean: Matches the files' loudness before joining. Default true.
    - `output_format` 'same' | 'wav' | 'mp3' | 'm4a' | 'flac': The result's format: same (as the first file), wav, mp3, m4a, or flac. Default same.
    - `max_credits` integer: With an API key only. The most this job may cost, in credits (1 credit is 1 US cent), such as 200. A job that would cost more doesn't start.
    - `free` boolean: With an API key only. true processes only the first hour of the result, at no cost, a few times a day. false always processes the whole file with credits. Left out, the whole file when the balance covers it, otherwise the first hour of the result free if quota is available (otherwise insufficient_balance / 402). true with exhausted quota returns free_limit_reached / 429; false with insufficient balance returns 402, without fallback.
  - object
    - `url` string[], required: Or links, in order
    - `file_token` string[], required: Or file tokens from POST /api/try/uploads, in order
    - `crossfade_ms` integer: A crossfade between files, in milliseconds (0 to 5000), such as 500. Default 0.
    - `match_loudness` boolean: Matches the files' loudness before joining. Default true.
    - `output_format` 'same' | 'wav' | 'mp3' | 'm4a' | 'flac': The result's format: same (as the first file), wav, mp3, m4a, or flac. Default same.
    - `max_credits` integer: With an API key only. The most this job may cost, in credits (1 credit is 1 US cent), such as 200. A job that would cost more doesn't start.
    - `free` boolean: With an API key only. true processes only the first hour of the result, at no cost, a few times a day. false always processes the whole file with credits. Left out, the whole file when the balance covers it, otherwise the first hour of the result free if quota is available (otherwise insufficient_balance / 402). true with exhausted quota returns free_limit_reached / 429; false with insufficient balance returns 402, without fallback.

## Response `200`

The result file itself (beside it, details such as a time map stay in the job). A job with several audio or video outputs (such as a cut into separate parts) returns the job with download links instead

- object
  - `id` string, required
  - `tool` 'remove_noise' | 'enhance_voice' | 'transcribe_audio' | 'align_script' | 'cut_audio' | 'remove_silence' | 'adjust_loudness' | 'convert_audio' | 'join_audio' | 'replace_audio' | 'analyze_audio' | 'remove_fillers' | 'level_speakers' | 'mix_tracks', required
  - `status` 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'held', required
  - `progress` integer, required: How much of the job is done, from 0 to 100. It never goes down, and its first part is the time a job usually takes to start
  - `stage` 'queued' | 'preparing' | 'processing' | 'finishing' | 'succeeded' | 'failed' | 'cancelled' | 'held', required: Where the job is: queued (not started yet, perhaps behind the account's other running jobs), preparing (getting the file ready), processing (the tool's work), finishing (saving the result), then succeeded, failed, or cancelled; or held (waiting for payment: see finishUrl)
  - `estimatedSecondsLeft` integer, nullable, required: About how many seconds the job has left, from the file's length and how fast the tool runs, refined as it goes. A rough guide. Null while it's queued, while Audo is busy (waitingForWorker), and once it has ended
  - `waitingForWorker` boolean, required: True while a running job has waited in line longer than a start usually takes: Audo is busy, and the job carries on as soon as there's room. A free job also waits behind paid ones, so it can wait longer; jobs with credits go first
  - `inputFileIds` string[], required: The main input first
  - `outputFileIds` string[], required: The main output first, once the job succeeds
  - `free` boolean, required: A free job processes only the first part of its input, at no cost
  - `processedSeconds` number, required: How much of the input the job processes
  - `quotedCredits` integer, required
  - `chargedCredits` integer, nullable, required: Set when the job succeeds
  - `result` object, nullable, required: The tool's details, such as loudness before and after
  - `error` object, nullable, required
    - `code` string, required
    - `message` string, required
  - `createdAt` string, required: ISO 8601 time
  - `startedAt` string, nullable, required: ISO 8601 time
  - `finishedAt` string, nullable, required: ISO 8601 time
  - `finishUrl` string, nullable: For a free result cut short: the page where the whole file can run, as a new job. Null when the job did the whole file
  - `statusUrl` string, required: This job's capability link. GET it to check on the job; it works for 1 hour
  - `fullPriceCredits` integer, nullable, required: The price to process the whole input with credits
  - `outputs` object[], required: The outputs with download links, once the job succeeds
    - `fileId` string, required
    - `filename` string, required
    - `contentType` string, required
    - `sizeBytes` integer, nullable, required
    - `durationSeconds` number, nullable, required
    - `hasVideo` boolean, required
    - `url` string, required: A signed download link
    - `expiresAt` string, required: ISO 8601 time
    - `fileExpiresAt` string: When Audo deletes the file itself (the link above expires sooner)
  - `finishPriceCredits` integer, nullable: What the whole file costs in credits (1 credit is 1 cent)
  - `finishedBy` object, nullable: Once someone paid to finish this free run: the whole-file job
    - `jobId` string, required
    - `status` 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'held', required
    - `progress` integer, required
    - `statusUrl` string, required: The whole-file job's own status link. GET it until its status is succeeded, then download its outputs
  - `nextStep` string: What to do next, for an agent

## Other responses

- `202`: The job is still running. Check on it at the Location header's link
- `429`: Today's free uses are used up (or 3 runs already wait for payment from this address: rate_limited). The file is still taken and held for payment: details has finishUrl (where the whole file can run), finishPriceCredits, jobId, and statusUrl, whose finishedBy names the whole-file job once paid
- `default`: An error, with what went wrong and what to do next

---

[API](https://skmtc.dev/audo/apis/audo-api.md) · [All operations](https://skmtc.dev/audo/apis/audo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/audo/apis/audo-api/revisions/0800e93224eb?raw)
