> ## 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.

# 동영상 업로드

> MP4, MOV, WebM 동영상을 업로드하고 생성 API에 사용할 공개 URL을 받습니다. 기본 파일당 한도는 50MB입니다.

> [!NOTE]
>
> 참조 파일을 업로드하면 성공 시 공개 URL이 바로 반환되며 조회는 필요하지 않습니다. 업로드는 무료지만 계정 잔액이 0보다 커야 합니다. 세 업로드 API는 사용자별 한도를 공유하며 기본값은 72시간 동안 총 2000개 파일입니다.

> [!NOTE]
>
> 문서 Playground는 파일 업로드를 지원하지 않습니다. 아래 cURL, Python, JavaScript 예제를 사용하세요. JavaScript 예제에는 파일을 선택한 `<input type="file">` 요소가 필요합니다.

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

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

with open("reference.mp4", "rb") as file:
    response = requests.post(
        "https://api.apimart.ai/v1/uploads/videos",
        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/videos", {
  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.mp4",
  "filename": "reference.mp4",
  "content_type": "video/mp4",
  "file_type": "video",
  "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": "video file exceeds maximum 52428800 bytes (50MB)",
    "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
  }
}
```

## 인증

**Authorization** `string` *required*

활성 상태이며 만료되지 않은 유효한 APIMart API Key를 `Bearer <token>` 형식으로 사용하세요. 계정은 정지되지 않아야 하며 잔액이 양수여야 합니다. Key 자체 할당량을 소진해도 업로드할 수 있습니다. [API Key 관리](https://apimart.ai/keys)에서 Key를 발급받을 수 있습니다.

## 요청 매개변수

**file** `file` *required*

`multipart/form-data`의 `file` 필드에 파일명과 함께 파일 하나를 전송하세요. 파일 부분을 JSON, base64 문자열, 파일 URL로 대체하지 마세요. 다른 폼 필드는 무시하며 여러 `file` 부분을 보내면 첫 번째만 처리합니다.

**지원 형식:** MP4 (.mp4), MOV (.mov), WebM (.webm)

**기본 파일 크기 상한:** 50MB. 크기 상한은 설정에 따라 변경될 수 있습니다. 실제 서비스 설정과 크기 초과 오류의 값을 기준으로 하세요.

cURL `--form`, Python `files`, JavaScript `FormData`를 사용할 때는 클라이언트가 boundary를 포함한 `Content-Type`을 생성하도록 두세요. 이 헤더를 직접 설정하지 마세요.

## 파일 검증

확장자나 클라이언트가 지정한 MIME 유형이 아닌 실제 내용으로 형식을 판별합니다. 내용은 업로드 API 종류와 일치해야 합니다. 이름을 바꿔도 형식이 변환되지 않으며 유형 불일치는 HTTP `400`을 반환합니다.

동영상 컨테이너 구조를 검증하며 위조 헤더나 손상된 컨테이너는 거부합니다. 아래 형식만 지원합니다. AVI, MKV 등은 이름을 바꿔도 사용할 수 없습니다.

| 형식 | 감지된 MIME 유형 |
| - | - |
| MP4 (.mp4) | `video/mp4` |
| MOV (.mov) | `video/quicktime` |
| WebM (.webm) | `video/webm` |

## 성공 응답

HTTP `200`으로 파일 정보를 반환합니다. `url`은 JSON 최상위에 있으며 `data` 래퍼나 생성 작업 ID는 없습니다.

**url** `string`

파일 공개 URL입니다. 대상 생성 API의 해당 참조 매개변수에 전달하세요. 모델별 형식, 크기, 수량, 길이 제한이 별도로 적용되므로 업로드 성공이 모델 호환성을 보장하지는 않습니다.

**filename** `string`

원본 파일명입니다.

**content\_type** `string`

서버가 파일 내용에서 감지한 MIME 유형이며 클라이언트 선언값이 아닙니다.

**file\_type** `string`

파일 분류입니다. 이 API는 `video`를 반환합니다.

**bytes** `integer`

실제 파일 크기(바이트)입니다.

**created\_at** `integer`

업로드 시각의 Unix 타임스탬프(초)입니다.

**quota** `object`

선택적 업로드 할당량 정보입니다. 제한 사용자의 필드는 아래와 같으며 무제한 또는 통계 일시 불가 상태에서는 구조가 다를 수 있습니다.

| 필드 | 설명 |
| - | - |
| `quota.limit` | 해당 사용자가 기간 내 성공적으로 업로드할 수 있는 최대 파일 수입니다. 기본값 2000과 다를 수 있습니다. |
| `quota.used` | 이번 업로드를 포함한 기간 내 사용량입니다. |
| `quota.remaining` | 현재 추가 업로드 가능한 파일 수입니다. |
| `quota.window_hours` | 집계 기간(시간)이며 기본값은 72입니다. |
| `quota.reset_at` | 가장 오래된 기록 묶음이 기간에서 제외되는 Unix 시각(초)입니다. 일부 자리가 생기며 전체 한도가 한 번에 초기화되는 것은 아닙니다. |

## 공유 할당량과 요청 속도 제한

이미지, 동영상, 오디오는 사용자별 한도를 공유합니다. 동일 사용자의 Key를 늘려도 한도는 합산되지 않습니다. 매시 정각에 기간을 이동하며 기본적으로 최근 약 71–72시간의 성공 업로드를 집계합니다. 형식 오류, 크기 초과, 저장 실패는 파일 할당량을 소모하지 않습니다.

일반 제한 응답에는 `X-Upload-Quota-Limit`, `X-Upload-Quota-Remaining`, `X-Upload-Quota-Reset`이 포함되며 각각 `limit`, `remaining`, `reset_at`에 대응합니다. Reset은 Unix 초입니다.

무제한 사용자는 `quota: {"unlimited": true}`를 받으며 위 세 헤더는 없습니다. 통계를 일시적으로 가져올 수 없으면 성공 응답에서도 `quota`가 생략될 수 있습니다. 이를 0이나 무제한으로 해석하거나 할당량 정보가 없다는 이유만으로 다시 업로드하지 마세요.

파일 한도 소진 시 HTTP `429`, `error.type: rate_limit_exceeded`, `quota`(`remaining: 0`), `Retry-After`를 반환합니다. 지정된 초만큼 기다린 후 재시도하세요. 별도로 Key당 60초에 1000회 요청 제한이 있으며 `rate_limit_error`로 구분합니다.

## 오류 처리

오류는 JSON 최상위 `error` 객체에 있습니다. HTTP 상태, `error.type` / `error.code`, `error.message`를 확인하세요.

| HTTP | `error.type` | 원인 및 처리 |
| - | - | - |
| 400 | `invalid_request_error` | 파일 누락, multipart가 아닌 요청, 빈 파일, 유형 불일치, 지원하지 않는 형식, 손상된 내용입니다. 파일이나 API 경로를 수정하세요. |
| 401 / 403 | `—` | 유효하지 않거나 비활성화된 Key, 또는 정지된 계정입니다. 인증과 계정 상태를 확인하세요. |
| 402 | `insufficient_user_quota` | 계정 잔액이 0 이하이거나 Key가 만료되었습니다. 충전하거나 유효한 Key를 사용하세요. 무료 업로드도 이용 조건을 충족해야 합니다. |
| 413 | `invalid_request_error` | 유형별 파일 크기 한도를 초과했습니다. 압축하거나 크기를 줄이고 오류에 표시된 현재 한도를 확인하세요. |
| 429 | `rate_limit_exceeded` | 사용자의 공유 파일 할당량을 소진했습니다. `quota`와 `Retry-After`를 확인하고 한도가 확보될 때까지 기다리세요. |
| 429 | `rate_limit_error` | Key의 요청이 너무 잦습니다. 요청 빈도를 낮추고 대기 시간을 두어 재시도하세요. |
| 503 | `server_error` | 동영상/오디오 동시 업로드가 너무 많거나 저장소가 일시적으로 불가능합니다. 나중에 다시 시도하세요. |
| 500 | `server_error` | 저장소에 파일을 쓰지 못했습니다. 나중에 다시 시도하세요. |

## URL 사용 및 파일 보관

72시간은 기본 할당량 집계 기간이며 파일 보관 기간을 보장하지 않습니다. 보관 기간은 저장소 정책에 따릅니다. 원본을 보관하고 받은 URL을 생성에 신속히 사용하세요. URL이 영구 유효하다고 가정하지 마세요.

## 다른 업로드 API

* [이미지 업로드](https://docs.apimart.ai/ko/api-reference/uploads/images.md)
* [오디오 업로드](https://docs.apimart.ai/ko/api-reference/uploads/audios.md)


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