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

# Upload Audio

> Upload an MP3, WAV, or M4A audio file to get a public URL for generation APIs. Default file limit: 15MB.

> [!NOTE]
>
> Upload reference media and receive a public URL immediately on success; no polling is needed. Uploading is free, but your account balance must be positive. The three upload endpoints share a per-user quota, defaulting to 2000 files over 72 hours.

> [!NOTE]
>
> The documentation Playground does not support file uploads. Use the cURL, Python, or JavaScript examples below. The JavaScript example requires an `<input type="file">` with a file selected on the page.

```bash cURL theme={null}
curl --request POST \
  --url https://api.apimart.ai/v1/uploads/audios \
  --header 'Authorization: Bearer <token>' \
  --form 'file=@/path/to/reference.mp3'
```

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

with open("reference.mp3", "rb") as file:
    response = requests.post(
        "https://api.apimart.ai/v1/uploads/audios",
        headers={"Authorization": "Bearer <token>"},
        files={"file": file}
    )

response.raise_for_status()
result = response.json()
print(result["url"])
```

```javascript JavaScript theme={null}
const input = document.querySelector('input[type="file"]');
const file = input?.files?.[0];
if (!file) throw new Error("Select a file first");

const formData = new FormData();
formData.append("file", file, file.name);

const response = await fetch("https://api.apimart.ai/v1/uploads/audios", {
  method: "POST",
  headers: { Authorization: "Bearer <token>" },
  body: formData
});
const result = await response.json();
if (!response.ok) {
  throw new Error(result.error?.message ?? `HTTP ${response.status}`);
}
console.log(result.url);
```

```json 200 theme={null}
{
  "url": "https://cdn.example/uploads/reference.mp3",
  "filename": "reference.mp3",
  "content_type": "audio/mpeg",
  "file_type": "audio",
  "bytes": 235680,
  "created_at": 1793836800,
  "quota": {
    "limit": 2000,
    "used": 124,
    "remaining": 1876,
    "window_hours": 72,
    "reset_at": 1794063600
  }
}
```

```json 402 theme={null}
{
  "error": {
    "message": "insufficient balance: uploading files requires a positive account balance, please top up",
    "type": "insufficient_user_quota"
  }
}
```

```json 413 theme={null}
{
  "error": {
    "message": "audio file exceeds maximum 15728640 bytes (15MB)",
    "type": "invalid_request_error"
  }
}
```

```json 429 theme={null}
{
  "error": {
    "message": "upload limit reached: each account can upload at most 2000 files per 72 hours",
    "type": "rate_limit_exceeded",
    "code": "rate_limit_exceeded",
    "param": ""
  },
  "quota": {
    "limit": 2000,
    "used": 2000,
    "remaining": 0,
    "window_hours": 72,
    "reset_at": 1794063600
  }
}
```

## Authentication

**Authorization** `string` *required*

Use a valid, enabled, unexpired APIMart API Key as `Bearer <token>`, with an account that is not suspended. The account balance must be positive; exhausting the Key's own quota does not prevent uploads. Get a Key from [API Key management](https://apimart.ai/keys).

## Request parameters

**file** `file` *required*

Send one file, including its filename, in the `file` field of a `multipart/form-data` request. Do not substitute JSON, a base64 string, or a file URL for the file part. Other form fields are ignored; if multiple `file` parts are sent, only the first is processed.

**Supported formats:** MP3 (.mp3), WAV (.wav), M4A (.m4a)

**Default maximum file size:** 15MB. File size limits can be configured. The active service configuration and size-limit error message take precedence.

With cURL `--form`, Python `files`, or JavaScript `FormData`, let the client generate the `Content-Type` header with its boundary. Do not set this header manually.

## File validation

The file type is detected from its content, not its extension or the MIME type supplied by the client. The content must match the endpoint; renaming a file does not convert it. A type mismatch returns HTTP `400`.

Audio container or frame structure is validated. Fake headers or damaged files are rejected. OGG, FLAC, and AAC (raw ADTS streams) are unsupported.

| Format | Detected MIME type |
| - | - |
| MP3 (.mp3) | `audio/mpeg` |
| WAV (.wav) | `audio/wav` |
| M4A (.m4a) | `audio/mp4` |

## Successful response

HTTP `200` returns file metadata. `url` is at the JSON root, without a `data` wrapper or a generation task ID.

**url** `string`

Public file URL. Pass it to the appropriate reference-media parameter of the target generation API. Each model still has its own format, size, count, and duration limits; a successful upload does not guarantee model compatibility.

**filename** `string`

Original filename.

**content\_type** `string`

MIME type detected by the server from the file content, not the client's declared value.

**file\_type** `string`

File category. This endpoint returns `audio`.

**bytes** `integer`

Actual file size in bytes.

**created\_at** `integer`

Upload time as a Unix timestamp in seconds.

**quota** `object`

Optional upload quota information. Fields for a quota-limited user are listed below; unlimited access or temporarily unavailable statistics may produce a different structure, as explained below.

| Field | Description |
| - | - |
| `quota.limit` | Maximum successful uploads for this user within the window; it may differ from the default of 2000. |
| `quota.used` | Used slots within the window, including this successful upload. |
| `quota.remaining` | Number of files that can currently still be uploaded. |
| `quota.window_hours` | Window length in hours; defaults to 72. |
| `quota.reset_at` | Time when the oldest batch leaves the window, in Unix seconds. Some slots become available then; the entire quota does not necessarily reset at once. |

## Shared quota and request rate limits

Image, video, and audio uploads share one per-user quota. Multiple API Keys for the same user do not add quota. The window rolls on the hour and, by default, counts successful uploads over approximately the past 71–72 hours. Invalid files, oversized files, and storage failures do not consume file quota.

Normal quota-limited responses also include `X-Upload-Quota-Limit`, `X-Upload-Quota-Remaining`, and `X-Upload-Quota-Reset`, corresponding to `limit`, `remaining`, and `reset_at`. Reset is in Unix seconds.

Unlimited users receive `quota: {"unlimited": true}` without those three quota headers. When statistics are temporarily unavailable, a successful response may omit `quota`. Do not interpret missing statistics as zero or unlimited, or re-upload solely because quota information is absent.

Exhausted file quota returns HTTP `429` with `error.type: rate_limit_exceeded`, `quota` (`remaining: 0`), and `Retry-After`. Wait the specified number of seconds before retrying. A separate limit of 1000 requests per Key per 60 seconds uses `rate_limit_error`; it is independent of the file quota.

## Error handling

Errors use a root-level `error` object. Inspect the HTTP status, `error.type` / `error.code`, and `error.message` to determine the cause.

| HTTP | `error.type` | Cause and action |
| - | - | - |
| 400 | `invalid_request_error` | Missing file, non-multipart request, empty file, wrong media type, unsupported format, or damaged content. Fix the file or endpoint before retrying. |
| 401 / 403 | `—` | Invalid or disabled Key, or suspended account. Check authentication and account status. |
| 402 | `insufficient_user_quota` | Non-positive account balance or expired Key. Add balance or use a valid Key. Free uploads still require these access conditions. |
| 413 | `invalid_request_error` | The file exceeds the limit for its type. Compress or reduce it; use the current limit stated in the error message. |
| 429 | `rate_limit_exceeded` | The user's shared file quota is exhausted. Read `quota` and `Retry-After`, then wait for slots to become available. |
| 429 | `rate_limit_error` | Too many requests from the Key. Reduce request frequency and retry with backoff. |
| 503 | `server_error` | Too many concurrent video/audio uploads, or temporarily unavailable storage. Retry later. |
| 500 | `server_error` | Failed to write the file to storage. Retry later. |

## Using URLs and retaining files

72 hours is the default quota window, not a file-retention guarantee. Retention depends on the storage policy. Keep the original files and use returned URLs promptly for generation; do not assume URLs are permanent.

## Other upload endpoints

* [Upload Image](https://docs.apimart.ai/en/api-reference/uploads/images.md)
* [Upload Video](https://docs.apimart.ai/en/api-reference/uploads/videos.md)


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