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

# 주문 결과 다운로드 URL 발급

> 완료된 Anti-AI·워터마크 삽입 주문의 결과 파일별 다운로드 URL과 결과 전체를 받는 URL을 한 번에 발급합니다. 워터마크 주문을 v2·v3 어느 쪽으로 만들었든 응답 형식은 같습니다.

- `files[]`: 결과 파일별 `{ fileId, downloadUrl }`. [`GET /api/v3/orders/{orderId}`](/ko/api-reference/orders/get-order-v3)의 `result.outputFiles[]`와 같은 파일을 같은 순서로 담고 `fileId`도 같습니다
- `archiveUrl`: 이 URL 하나로 결과 전체를 받습니다. 항상 문자열입니다
  - Anti-AI 주문, v2로 만든 워터마크 삽입 주문: 결과 ZIP
  - v3로 만든 워터마크 삽입 주문: 결과 파일이 2개 이상이면 ZIP, 1개면 그 결과 파일 URL(`files[0].downloadUrl`과 같은 파일)
- `expiresInSeconds`: URL 유효 시간. 기본 3600초(1시간)이며, 보관 기한(`expiresAt`)까지 남은 시간이 더 짧으면 그 시간으로 줄입니다. 새 URL이 필요하면 다시 호출하세요

**오류 검사 순서** (처음 걸린 오류를 반환)
1. 주문이 없거나 다른 계정의 주문 → `404 ORDER_NOT_FOUND`
2. 워터마크 검출·AI Detection 주문 → `400 ORDER_TYPE_CANT_DOWNLOAD`. 보관 기한이 지났어도 이 오류입니다
3. 보관 기한 만료 → `400 ORDER_EXPIRED`. 보관 기한을 확인할 수 없으면 `409 FILE_RETENTION_UNKNOWN`
4. `status`가 `complete`가 아님(`pending`·`inProgress`·`failed`) → `400 ORDER_NOT_COMPLETED`

**이전 v3 응답과의 차이(breaking change, 2026-10-08)**: 응답이 `{ downloadUrl, expiresInSeconds: 300 }`에서 `{ archiveUrl, files, expiresInSeconds }`로 바뀌었고, Anti-AI 주문과 v2로 만든 워터마크 삽입 주문도 지원합니다. URL 유효 시간은 300초에서 최대 3600초로 늘었습니다. 미완료 주문은 `VALIDATION_FAILED` 대신 `ORDER_NOT_COMPLETED`를, 검출 주문은 `ORDER_TYPE_CANT_DOWNLOAD`를 반환합니다. 결과 파일 하나를 받는 `GET /api/v3/orders/{orderId}/files/{fileId}/download`는 삭제되었습니다. `files[]`를 사용하세요.

**테스트 키(`sk_test_`)**: 같은 키로 만든 완료된 Anti-AI·워터마크 삽입 테스트 주문(v2·v3)에서 동작합니다. URL은 처리 결과가 아니라 `https://api.bizmori.com/api/v2/test-samples/{signedToken}`에서 제공하는 샘플 파일을 가리킵니다. 결과 파일이 없는 Anti-AI 테스트 주문은 `files: []`와 샘플 ZIP `archiveUrl`을 반환합니다. 결과가 1개인 v3 삽입 테스트 주문은 그 샘플 파일을, 그 외 테스트 주문은 샘플 ZIP을 `archiveUrl`로 반환합니다. `expiresInSeconds`, 오류 코드, 검사 순서는 운영 주문과 같습니다.


완료된 Anti-AI·워터마크 삽입 주문의 결과를 내려받을 때 이 엔드포인트를 사용합니다. 한 번의 호출로 결과 파일별 URL과 결과 전체를 받는 URL을 함께 받습니다. 워터마크 주문을 v2·v3 어느 쪽으로 만들었든 응답 형식은 같습니다.

> [!WARNING]
>
> 2026년 10월 8일에 응답 형식이 바뀌었고 `GET /api/v3/orders/{orderId}/files/{fileId}/download`는 삭제되었습니다. [이전 응답과의 차이](#이전-응답과의-차이)를 확인하세요.

## 응답 필드

| 필드 | 타입 | 설명 |
| - | - | - |
| `archiveUrl` | string | 결과 전체를 받는 URL. 항상 있음 |
| `files[]` | array | 결과 파일별 `{ fileId, downloadUrl }` |
| `expiresInSeconds` | integer | URL 유효 시간(초). 최대 3600 |

`files[]`는 [주문 상세 조회](https://docs.contentcare.ai/ko/api-reference/orders/get-order-v3.md)의 `result.outputFiles[]`와 같은 파일을 같은 순서로 담고 `fileId`도 같습니다. `fileId`로 각 URL을 결과 파일과 그 `inputFileId`에 연결하세요.

### `archiveUrl`이 가리키는 파일

| 주문 | `archiveUrl` |
| - | - |
| Anti-AI | 모든 결과 파일의 ZIP |
| v2로 만든 워터마크 삽입 | 모든 결과 파일의 ZIP |
| v3로 만든 워터마크 삽입, 결과 파일 2개 이상 | 모든 결과 파일의 ZIP |
| v3로 만든 워터마크 삽입, 결과 파일 1개 | 그 결과 파일(`files[0].downloadUrl`과 같은 파일) |

`archiveUrl`은 결과 파일 하나이거나 전체 ZIP이므로, 다운로드 버튼 하나에 그대로 연결할 수 있습니다.

### URL 유효 시간

URL은 3600초(1시간) 동안 유효합니다. 주문의 보관 기한(`expiresAt`)이 그보다 먼저 끝나면 남은 시간으로 줄이고, `expiresInSeconds`에 줄인 값을 넣습니다. URL을 저장해 두지 말고 내려받을 때마다 이 엔드포인트를 다시 호출하세요.

## 예시

```json Anti-AI theme={null}
{
  "data": {
    "archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/zip/1001/archive.zip?X-Amz-...",
    "files": [
      {
        "fileId": "21",
        "downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/cat.png?X-Amz-..."
      },
      {
        "fileId": "22",
        "downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/dog.png?X-Amz-..."
      }
    ],
    "expiresInSeconds": 3600
  }
}
```

```json 워터마크 삽입 (결과 1개) theme={null}
{
  "data": {
    "archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo.png?X-Amz-...",
    "files": [
      {
        "fileId": "201",
        "downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo.png?X-Amz-..."
      }
    ],
    "expiresInSeconds": 3600
  }
}
```

```json 워터마크 삽입 (결과 2개) theme={null}
{
  "data": {
    "archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/archive/2001.zip?X-Amz-...",
    "files": [
      {
        "fileId": "201",
        "downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo-1.png?X-Amz-..."
      },
      {
        "fileId": "202",
        "downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo-2.png?X-Amz-..."
      }
    ],
    "expiresInSeconds": 3600
  }
}
```

## 결과 파일 모두 내려받기

```javascript Node.js theme={null}
import { writeFile } from 'node:fs/promises';

const headers = { Authorization: 'Bearer YOUR_API_KEY' };
const base = `https://api.bizmori.com/api/v3/orders/${orderId}`;

const { data: order } = await (await fetch(base, { headers })).json();
const { data: download } = await (await fetch(`${base}/download`, { headers })).json();

// files[]와 result.outputFiles[]는 fileId 값과 순서가 같습니다.
const names = new Map(order.result.outputFiles.map((file) => [file.fileId, file.fileName]));
for (const { fileId, downloadUrl } of download.files) {
  const res = await fetch(downloadUrl);
  await writeFile(`${fileId}-${names.get(fileId)}`, Buffer.from(await res.arrayBuffer()));
}
```

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

headers = {'Authorization': 'Bearer YOUR_API_KEY'}
base = f'https://api.bizmori.com/api/v3/orders/{order_id}'

order = requests.get(base, headers=headers).json()['data']
download = requests.get(f'{base}/download', headers=headers).json()['data']

# files[]와 result.outputFiles[]는 fileId 값과 순서가 같습니다.
names = {f['fileId']: f['fileName'] for f in order['result']['outputFiles']}
for item in download['files']:
    res = requests.get(item['downloadUrl'])
    with open(f"{item['fileId']}-{names[item['fileId']]}", 'wb') as out:
        out.write(res.content)
```

## 오류

아래 순서로 오류를 검사하고 처음 해당하는 오류를 반환합니다.

| 순서 | 조건 | HTTP | `code` |
| - | - | - | - |
| 1 | 주문이 없거나 다른 계정의 주문 | 404 | `ORDER_NOT_FOUND` |
| 2 | 워터마크 검출·AI Detection 주문(보관 기한이 지났어도 동일) | 400 | `ORDER_TYPE_CANT_DOWNLOAD` |
| 3 | 보관 기한 만료 | 400 | `ORDER_EXPIRED` |
| 3 | 보관 기한을 확인할 수 없음 | 409 | `FILE_RETENTION_UNKNOWN` |
| 4 | `status`가 `pending`, `inProgress`, `failed` | 400 | `ORDER_NOT_COMPLETED` |

`orderId` 형식이 잘못되면 `400 VALIDATION_FAILED`를 반환합니다.

## 이전 응답과의 차이

2026년 10월 8일부터 이 엔드포인트는 위 형식으로 응답합니다. 하위 호환되지 않는 변경입니다.

| 이전 동작 | 현재 |
| - | - |
| 응답 `{ downloadUrl, expiresInSeconds }` | `{ archiveUrl, files, expiresInSeconds }`. `downloadUrl` 대신 `archiveUrl` |
| v3 워터마크 삽입 주문만 지원 | Anti-AI 주문, v2·v3로 만든 워터마크 삽입 주문 지원 |
| URL 300초 유효 | 최대 3600초. 보관 기한까지로 제한 |
| 미완료 주문: `400 VALIDATION_FAILED` | `400 ORDER_NOT_COMPLETED` |
| 워터마크 검출·AI Detection 주문: 지원 안 함 | 계속 지원하지 않으며 전용 오류 `400 ORDER_TYPE_CANT_DOWNLOAD` 반환 |
| 결과 파일 하나를 받는 `GET /api/v3/orders/{orderId}/files/{fileId}/download` | 삭제됨. 이 엔드포인트의 `files[]` 사용 |

deprecated된 [`GET /api/v2/orders/{orderId}/download`](https://docs.contentcare.ai/ko/api-reference/orders/download-order)는 기존 응답을 그대로 반환합니다.

## 테스트 키

`sk_test_` 키로 호출하면 같은 키로 만든 완료된 Anti-AI·워터마크 삽입 테스트 주문에서 동작합니다. URL은 처리 결과가 아니라 고정 샘플 파일을 가리킵니다. [테스트 API 키](https://docs.contentcare.ai/ko/test-api-keys.md)를 참고하세요.


## OpenAPI

````yaml ko/api-reference/openapi.yaml GET /api/v3/orders/{orderId}/download
openapi: 3.0.0
info:
  title: BIZ MORI API
  version: 2.0.0
  description: >
    BIZ MORI API는 디지털 콘텐츠 보호를 위한 네 가지 핵심 서비스를 제공합니다:

    - **Anti-AI**: 이미지를 AI 학습으로부터 보호

    - **Watermark Embed**: 이미지에 보이지 않는 디지털 워터마크 삽입

    - **Watermark Extract**: 이미지에서 워터마크 추출 및 검증

    - **AI Detection**: 이미지가 AI로 생성되었는지 감지

    - **테스트 API 키**: `sk_test_` 접두사의 키는 동일한 Bearer 인증을 사용하며, 실제 처리 서비스나 크레딧 사용
    없이 주문 흐름을 검증할 수 있습니다. 테스트 업로드는 파일 내용을 폐기하고 결과 파일을 만들지 않습니다
  contact:
    name: BIZ MORI 지원
    email: support@contentcare.ai
  license:
    name: Proprietary
    url: https://docs.contentcare.ai/legal/terms
servers:
  - url: https://api.bizmori.com
    description: 프로덕션
security: []
tags:
  - name: Anti-AI
    description: AI 학습 방지 이미지 보호 주문
  - name: Watermark Embed
    description: 워터마크 삽입 주문
  - name: Watermark Extract
    description: 워터마크 추출 주문
  - name: AI Detection
    description: AI 생성 이미지 감지 주문
  - name: Orders
    description: 주문 조회 및 관리
  - name: Webhooks
    description: 웹훅 설정 및 이벤트
  - name: Reports
    description: 워터마크 추출·AI Detection 주문의 PDF 분석 보고서
paths:
  /api/v3/orders/{orderId}/download:
    get:
      tags:
        - Orders
      summary: 주문 결과 다운로드 URL 발급
      description: >
        완료된 Anti-AI·워터마크 삽입 주문의 결과 파일별 다운로드 URL과 결과 전체를 받는 URL을 한 번에 발급합니다. 워터마크
        주문을 v2·v3 어느 쪽으로 만들었든 응답 형식은 같습니다.


        - `files[]`: 결과 파일별 `{ fileId, downloadUrl }`. [`GET
        /api/v3/orders/{orderId}`](/ko/api-reference/orders/get-order-v3)의
        `result.outputFiles[]`와 같은 파일을 같은 순서로 담고 `fileId`도 같습니다

        - `archiveUrl`: 이 URL 하나로 결과 전체를 받습니다. 항상 문자열입니다
          - Anti-AI 주문, v2로 만든 워터마크 삽입 주문: 결과 ZIP
          - v3로 만든 워터마크 삽입 주문: 결과 파일이 2개 이상이면 ZIP, 1개면 그 결과 파일 URL(`files[0].downloadUrl`과 같은 파일)
        - `expiresInSeconds`: URL 유효 시간. 기본 3600초(1시간)이며, 보관 기한(`expiresAt`)까지
        남은 시간이 더 짧으면 그 시간으로 줄입니다. 새 URL이 필요하면 다시 호출하세요


        **오류 검사 순서** (처음 걸린 오류를 반환)

        1. 주문이 없거나 다른 계정의 주문 → `404 ORDER_NOT_FOUND`

        2. 워터마크 검출·AI Detection 주문 → `400 ORDER_TYPE_CANT_DOWNLOAD`. 보관 기한이 지났어도
        이 오류입니다

        3. 보관 기한 만료 → `400 ORDER_EXPIRED`. 보관 기한을 확인할 수 없으면 `409
        FILE_RETENTION_UNKNOWN`

        4. `status`가 `complete`가 아님(`pending`·`inProgress`·`failed`) → `400
        ORDER_NOT_COMPLETED`


        **이전 v3 응답과의 차이(breaking change, 2026-10-08)**: 응답이 `{ downloadUrl,
        expiresInSeconds: 300 }`에서 `{ archiveUrl, files, expiresInSeconds }`로
        바뀌었고, Anti-AI 주문과 v2로 만든 워터마크 삽입 주문도 지원합니다. URL 유효 시간은 300초에서 최대 3600초로
        늘었습니다. 미완료 주문은 `VALIDATION_FAILED` 대신 `ORDER_NOT_COMPLETED`를, 검출 주문은
        `ORDER_TYPE_CANT_DOWNLOAD`를 반환합니다. 결과 파일 하나를 받는 `GET
        /api/v3/orders/{orderId}/files/{fileId}/download`는 삭제되었습니다. `files[]`를
        사용하세요.


        **테스트 키(`sk_test_`)**: 같은 키로 만든 완료된 Anti-AI·워터마크 삽입 테스트 주문(v2·v3)에서
        동작합니다. URL은 처리 결과가 아니라
        `https://api.bizmori.com/api/v2/test-samples/{signedToken}`에서 제공하는 샘플
        파일을 가리킵니다. 결과 파일이 없는 Anti-AI 테스트 주문은 `files: []`와 샘플 ZIP `archiveUrl`을
        반환합니다. 결과가 1개인 v3 삽입 테스트 주문은 그 샘플 파일을, 그 외 테스트 주문은 샘플 ZIP을 `archiveUrl`로
        반환합니다. `expiresInSeconds`, 오류 코드, 검사 순서는 운영 주문과 같습니다.
      operationId: downloadOrderV3
      parameters:
        - in: path
          name: orderId
          required: true
          schema:
            type: string
            pattern: ^[0-9]{1,20}$
          description: 주문 ID
      responses:
        '200':
          description: 결과 파일별 URL과 결과 전체 URL
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicOrderV3DownloadResponse'
              examples:
                antiAi:
                  summary: Anti-AI (결과 2개, `archiveUrl`은 ZIP)
                  value:
                    data:
                      archiveUrl: >-
                        https://bucket.s3.ap-northeast-2.amazonaws.com/zip/1001/archive.zip?X-Amz-...
                      files:
                        - fileId: '21'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/cat.png?X-Amz-...
                        - fileId: '22'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/dog.png?X-Amz-...
                      expiresInSeconds: 3600
                watermarkEmbedV3Multiple:
                  summary: 워터마크 삽입(v3) (결과 2개, `archiveUrl`은 ZIP)
                  value:
                    data:
                      archiveUrl: >-
                        https://bucket.s3.ap-northeast-2.amazonaws.com/archive/2001.zip?X-Amz-...
                      files:
                        - fileId: '201'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo-1.png?X-Amz-...
                        - fileId: '202'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo-2.png?X-Amz-...
                      expiresInSeconds: 3600
                watermarkEmbedV3Single:
                  summary: 워터마크 삽입(v3) (결과 1개, `archiveUrl`은 결과 파일 URL)
                  value:
                    data:
                      archiveUrl: >-
                        https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo.png?X-Amz-...
                      files:
                        - fileId: '201'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo.png?X-Amz-...
                      expiresInSeconds: 3600
                watermarkEmbedV2:
                  summary: 워터마크 삽입(v2) (결과 2개, `expiresAt`까지 20분 남아 URL 유효 시간 단축)
                  value:
                    data:
                      archiveUrl: >-
                        https://bucket.s3.ap-northeast-2.amazonaws.com/zip/2101.zip?X-Amz-...
                      files:
                        - fileId: '41'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/a.png?X-Amz-...
                        - fileId: '42'
                          downloadUrl: >-
                            https://bucket.s3.ap-northeast-2.amazonaws.com/out/b.png?X-Amz-...
                      expiresInSeconds: 1200
        '400':
          description: 요청 형식 오류, 다운로드할 수 없는 주문 종류, 보관 기한 만료, 미완료 주문
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                validation:
                  summary: '`orderId` 형식 오류'
                  value:
                    code: VALIDATION_FAILED
                typeCantDownload:
                  summary: 워터마크 검출·AI Detection 주문
                  value:
                    code: ORDER_TYPE_CANT_DOWNLOAD
                expired:
                  summary: 보관 기한 만료
                  value:
                    code: ORDER_EXPIRED
                notCompleted:
                  summary: '`pending`·`inProgress`·`failed` 주문'
                  value:
                    code: ORDER_NOT_COMPLETED
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: 주문이 없거나 다른 계정의 주문
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: ORDER_NOT_FOUND
        '409':
          description: 주문의 보관 기한을 확인할 수 없음
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: FILE_RETENTION_UNKNOWN
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - BearerAuth: []
      x-codeSamples:
        - lang: curl
          label: cURL
          source: >
            curl -X GET https://api.bizmori.com/api/v3/orders/ORDER_ID/download
            \
              -H "Authorization: Bearer YOUR_API_KEY"
        - lang: javascript
          label: JavaScript
          source: >
            const orderId = 'ORDER_ID';

            const response = await
            fetch(`https://api.bizmori.com/api/v3/orders/${orderId}/download`, {
              headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
            });

            const { data } = await response.json();
        - lang: python
          label: Python
          source: |
            import requests

            order_id = 'ORDER_ID'
            response = requests.get(
                f'https://api.bizmori.com/api/v3/orders/{order_id}/download',
                headers={'Authorization': 'Bearer YOUR_API_KEY'}
            )
            data = response.json()['data']
components:
  schemas:
    PublicOrderV3DownloadResponse:
      type: object
      required:
        - data
      additionalProperties: false
      properties:
        data:
          type: object
          required:
            - archiveUrl
            - files
            - expiresInSeconds
          additionalProperties: false
          properties:
            archiveUrl:
              type: string
              format: uri
              description: >-
                결과 전체를 한 번에 받는 URL. Anti-AI 주문과 v2 워터마크 삽입 주문은 결과 ZIP입니다. v3
                워터마크 삽입 주문은 결과 파일이 2개 이상이면 ZIP, 1개면 그 결과 파일
                URL(`files[0].downloadUrl`과 같은 파일)입니다
            files:
              type: array
              description: 결과 파일별 다운로드 URL. 주문 상세 `result.outputFiles`와 같은 파일을 같은 순서로 담습니다
              items:
                type: object
                required:
                  - fileId
                  - downloadUrl
                additionalProperties: false
                properties:
                  fileId:
                    type: string
                    pattern: ^[0-9]+$
                    description: 주문 상세 `result.outputFiles[].fileId`와 같은 값
                  downloadUrl:
                    type: string
                    format: uri
                    description: 결과 파일의 presigned 다운로드 URL
            expiresInSeconds:
              type: integer
              maximum: 3600
              description: URL 유효 시간(초). 기본 3600초이며 `expiresAt`까지 남은 시간이 더 짧으면 그 시간으로 줄입니다
              example: 3600
    ErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: 에러 코드
  responses:
    Unauthorized:
      description: 인증 실패
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: AUTH_NOT_AUTHENTICATED
    InternalError:
      description: 내부 서버 오류
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: SERVER_INTERNAL_ERROR
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        외부 클라이언트 접근을 위한 Bearer API 키. 일반 키는 `sk_` 접두사를 사용하고, 테스트 키는 `sk_test_`
        접두사로 모의 응답을 사용해 실제 처리나 크레딧 사용 없이 주문 흐름을 검증합니다.

````

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