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

# 계약 폴더 조립

> 다중 파일 계약 JSON을 하나의 완전 검증 매니페스트로 병합. 익명 가능.

**`POST`** `https://api-datahub.octoparse.com/v1/data-apps/contract/assemble`

인증: 없음. 익명 호출 가능.

계약 폴더(상대 경로를 키로 하는 파일 맵, 순서 유지)를 하나의 자체 완결형 매니페스트로 병합합니다. 조립 규칙의 유일한 기준이 되는 엔드포인트입니다. 포털 가져오기 마법사와 계약 Skill 자체 점검 모두 이 엔드포인트를 사용합니다.

슬롯 파일: `dataapp.json` / `input_schema.json` / `output_schema.json` / `runtime.json` / `pricing.json` / `examples.json` / `README.md`(파일 이름은 대소문자를 구분하지 않으며, `input.schema.json` 같은 점 표기 형식도 허용되고 `picked`에서 정규화됩니다). 가격과 예시는 `dataapp.json`에 인라인으로 작성할 수도 있습니다. 병합된 매니페스트는 작성자 측 전체 검증을 거칩니다(매니페스트 검증과 같은 규칙). `issues`가 비어 있을 때만 제출 가능합니다. 복구 가능한 이상(파일 누락, 레이어 간 이름 충돌, 무시된 비계약 파일, 폴더 이름 불일치 등)은 구조화된 `warnings`(`code` + `params`, 표시 계층에서 현지화)로 반환되며 오류가 아닙니다.

치명적 실패(`400`): 슬롯 파일이 유효한 JSON이 아니거나, 형태가 잘못되었거나(`examples.json`은 배열이어야 하고 다른 슬롯은 객체여야 함), 1MB를 초과하는 경우. 계약 파일이 하나도 없는 경우. 전체 크기가 12MB를 초과하는 경우. 계약 경로는 api 유형만 대상으로 하며, `runtime.kind=code`는 issue가 됩니다.

선택적인 8번째 파일 `i18n.json`(`{source, locales}`, 최대 4MB)은 매니페스트에 **병합되지 않습니다**. 파싱된 뒤 `translations`로 반환되며, 호출자가 번역 엔드포인트로 저장합니다. `source`는 필수입니다. 잘못된 로캘은 `400`이 됩니다. `source`와 같은 로캘은 `i18n-locale-is-source`로 건너뜁니다. 경로 수준의 문제는 `i18n-*` 경고로 반환됩니다.

익명 접근이 허용됩니다: 조립은 요청 본문만으로 결정되는 순수 처리로, 플랫폼 데이터를 읽거나 쓰지 않으며 파일별·전체 크기 제한만 적용됩니다.

## 요청

### 요청 body

<ParamField body="files" type="object" required>
  파일 맵. 키는 상대 경로, 값은 파일 텍스트입니다.
</ParamField>

### 요청 예시

```bash theme={null}
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"files": {"dataapp.json": "{\"spec_version\": \"0.2\", \"identity\": {…}}", "input_schema.json": "{\"type\": \"object\", …}", "output_schema.json": "{\"id_field\": \"review_id\", …}", "runtime.json": "{\"kind\": \"api\", …}", "pricing.json": "{\"events\": [...]}", "examples.json": "[...]", "README.md": "# Product review lookup"}}' \
  "https://api-datahub.octoparse.com/v1/data-apps/contract/assemble"
```

## 응답

### 200 성공

```json theme={null}
{
  "data": {
    "manifest": {
      "spec_version": "0.2",
      "identity": {
        "app_name": "reviews-query",
        "name": "Product review lookup"
      },
      "…": "…"
    },
    "picked": {
      "dataapp.json": "dataapp.json",
      "input_schema.json": "input_schema.json"
    },
    "issues": [],
    "warnings": [
      {
        "code": "contract-folder-name-mismatch",
        "params": {
          "expected": "reviews-query",
          "actual": "reviews"
        }
      }
    ],
    "card": {
      "app_name": "reviews-query",
      "name": "Product review lookup"
    },
    "translations": null
  }
}
```

페이로드는 `data`로 감쌉니다. 필드:

<ResponseField name="manifest" type="object" required>
  병합된 매니페스트 객체.
</ResponseField>

<ResponseField name="picked" type="string[]">
  실제로 인식된 슬롯 파일의 맵.
</ResponseField>

<ResponseField name="folder_name" type="string">
  —
</ResponseField>

<ResponseField name="issues" type="object[]">
  검증 문제. 비어 있으면 제출 가능합니다.

  <Expandable title="fields">
    <ResponseField name="path" type="string" required>
      —
    </ResponseField>

    <ResponseField name="message" type="string" required>
      —
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="warnings" type="object[]">
  구조화된 경고.

  <Expandable title="fields">
    <ResponseField name="code" type="string" required>
      —
    </ResponseField>

    <ResponseField name="params" type="object">
      —
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="translations" type="object">
  파싱된 `i18n.json` 내용. 없으면 `null`.

  <Expandable title="fields">
    <ResponseField name="source" type="string" required>
      —
    </ResponseField>

    <ResponseField name="locales" type="object">
      —
    </ResponseField>
  </Expandable>
</ResponseField>

### 오류

| HTTP | `code`                  | `category`      | 설명                                                                             |
| ---- | ----------------------- | --------------- | ------------------------------------------------------------------------------ |
| 400  | `contract-file-invalid` | `invalid_input` | 계약 파일이 유효한 JSON이 아니거나, 형태가 잘못되었거나, 1MB를 초과합니다. 또는 `i18n.json`에 `source`가 없습니다. |
| 400  | `contract-empty`        | `invalid_input` | 파일 세트에 계약 슬롯 파일이 없습니다.                                                         |
| 400  | `locale-invalid`        | `invalid_input` | 로캘 코드가 유효하지 않습니다.                                                              |
| 413  | `payload-too-large`     | `invalid_input` | 요청 body가 크기 상한 초과.                                                             |

오류 응답은 `{"error": {code, category, message, retryable}}`입니다. <a href="/docs/ko/datahub/api/reference/introduction#errors">오류</a> 참고.

## 클라이언트 라이브러리

Python / JavaScript SDK는 아직 이 엔드포인트를 감싸지 않습니다. REST를 직접 호출하세요.
