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

# 잠정 주문 (VDP)

> 가변 데이터를 포함한 잠정 주문을 넣습니다. 그 외에는 잠정 주문과 같습니다.

보내는 방법이 두 가지입니다.

- **`vdp_dataset`(JSON)**: `Content-Type: application/json`으로 보냅니다. dataset 객체를 그대로 넣습니다. 서버가 직렬화하므로 미리 stringify하지 않습니다. 대량 데이터에는 맞지 않습니다.
- **`vdp_dataset_file`(파일)**: `Content-Type: multipart/form-data`로 보냅니다. JSON 문자열이 담긴 File 또는 Blob이어야 합니다. 대량 데이터는 이쪽을 씁니다.

multipart로 보낼 때는 `vdp_dataset_file`을 제외한 모든 필드가 문자열로 전달되고, 서버가 숫자와 불리언으로 바꿔 검증합니다. `vdp_dataset_file`이 있으면 `vdp_dataset`은 무시됩니다.

<Warning>VDP를 포함한 주문을 취소하면 `vdp_dataset`은 삭제되고 복구되지 않습니다.</Warning>



## OpenAPI

````yaml /api-reference/openapi.json post /v2/projects/{project_id}/order/tentative_with_vdp
openapi: 3.1.0
info:
  title: Edicus Server API
  version: 1.1.5
  description: >-
    Edicus 편집기 연동에 필요한 서버 API입니다. 토큰 발급, 프로젝트 조회, 주문 처리, 폰트와 상품 정보, 템플릿 등록을
    다룹니다.


    ## 반드시 서버에서만 호출합니다


    모든 엔드포인트는 `edicus-api-key` 헤더를 요구합니다. 이 키는 고객사 서버에만 두고 브라우저 코드나 공개 저장소에 넣지
    않습니다. 브라우저에는 이 API로 발급받은 토큰만 내려보냅니다.


    ## 오류 응답


    `api.edicus.io`는 실패를 4xx와 5xx 상태 코드로 알리고, body는 언제나 `{"error": {"code",
    "message", "details", "request_id"}}` 모양입니다. `error.code`로 분기합니다. 같은
    `request_id`가 응답 헤더 `x-request-id`에도 실립니다.


    `resource-dot-edicusbase.appspot.com`은 방식이 다릅니다. 파라미터 누락은 `400`, 인증 실패는
    `401`, 그 밖의 모든 실패는 `500`이고, body에 `error` 객체가 없습니다.


    ## 응답 형식


    응답의 `content-type`은 `application/json`입니다.
  contact:
    name: 모션원
    url: https://edicus.io
servers:
  - url: https://api.edicus.io
    description: Server API 호스트
security:
  - edicusApiKey: []
tags:
  - name: Auth
    description: 토큰 발급
  - name: Projects
    description: 프로젝트 조회, 삭제, 복제
  - name: Orders
    description: 잠정 주문, 확정 주문, 취소
  - name: Fonts
    description: 폰트 그룹과 폰트 목록
  - name: Products
    description: 상품과 상품 카테고리 정보
  - name: Templates
    description: 리소스 토큰과 템플릿 패키지 등록
  - name: Resources
    description: 리소스 검색과 사용자 이미지
paths:
  /v2/projects/{project_id}/order/tentative_with_vdp:
    post:
      tags:
        - Orders
      summary: 잠정 주문 (VDP)
      description: >-
        가변 데이터를 포함한 잠정 주문을 넣습니다. 그 외에는 잠정 주문과 같습니다.


        보내는 방법이 두 가지입니다.


        - **`vdp_dataset`(JSON)**: `Content-Type: application/json`으로 보냅니다.
        dataset 객체를 그대로 넣습니다. 서버가 직렬화하므로 미리 stringify하지 않습니다. 대량 데이터에는 맞지 않습니다.

        - **`vdp_dataset_file`(파일)**: `Content-Type: multipart/form-data`로 보냅니다.
        JSON 문자열이 담긴 File 또는 Blob이어야 합니다. 대량 데이터는 이쪽을 씁니다.


        multipart로 보낼 때는 `vdp_dataset_file`을 제외한 모든 필드가 문자열로 전달되고, 서버가 숫자와 불리언으로
        바꿔 검증합니다. `vdp_dataset_file`이 있으면 `vdp_dataset`은 무시됩니다.


        <Warning>VDP를 포함한 주문을 취소하면 `vdp_dataset`은 삭제되고 복구되지 않습니다.</Warning>
      operationId: createTentativeOrderWithVdp
      parameters:
        - name: project_id
          in: path
          required: true
          description: 프로젝트 id
          schema:
            type: string
            minLength: 1
          example: '-LiBngTbCFYNjcOVcxcY'
        - name: edicus-uid
          in: header
          required: true
          description: >-
            고객사가 사용자에게 부여한 고유 id입니다. 1~70자이고 `a-z`, `A-Z`, `0-9`, `_`, `!`, `@`,
            `-`, `+`, `=`만 쓸 수 있습니다. 없거나 규칙을 어기면 `400 invalid_request`입니다.
          schema:
            type: string
            minLength: 1
            maxLength: 70
            pattern: ^[a-zA-Z0-9_!@\-+=]+$
          example: kr46KCD8vWOnOGo8CBO7c6ctSge2
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TentativeOrderBody'
            example:
              order_count: 1
              total_price: 23500
              vdp_dataset:
                rows:
                  - cols:
                      - id: name
                        value:
                          text: 홍길동
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TentativeOrderMultipartBody'
      responses:
        '200':
          description: 잠정 주문이 들어갔습니다.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TentativeOrderResult'
              example:
                order_id: 100023
                status: ordering
        '400':
          description: >-
            헤더나 body가 형식에 맞지 않습니다. `order_count`가 1 미만이거나, `userdata_json`이 JSON
            문자열이 아니거나 1000자를 넘는 경우 등입니다. `error.code`는 `invalid_request`이고
            `error.details.issues`에 어긋난 항목이 있습니다.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
              example:
                error:
                  code: invalid_request
                  message: 요청 형식이 맞지 않습니다
                  details:
                    issues:
                      - code: custom
                        path:
                          - userdata_json
                        message: userdata_json은 JSON 문자열이어야 합니다
                  request_id: 4bf92f3577b34da6a3ce929d0e0e4736
        '401':
          description: >-
            인증 실패입니다. `error.code`는 `no_credentials`(자격 증명 헤더가 없음) 또는
            `invalid_api_key`(API 키가 틀림)입니다.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
              examples:
                invalid_api_key:
                  summary: invalid_api_key
                  value:
                    error:
                      code: invalid_api_key
                      message: edicus-api-key 값을 확인하세요
                      request_id: 4bf92f3577b34da6a3ce929d0e0e4736
                no_credentials:
                  summary: no_credentials
                  value:
                    error:
                      code: no_credentials
                      message: edicus-api-key 또는 edicus-id-token이 필요합니다
                      request_id: 4bf92f3577b34da6a3ce929d0e0e4736
        '404':
          description: 프로젝트가 없습니다. `error.code`는 `project_not_found`입니다.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
              example:
                error:
                  code: project_not_found
                  message: 프로젝트가 없습니다
                  request_id: 4bf92f3577b34da6a3ce929d0e0e4736
        '409':
          description: >-
            지금 상태에서는 잠정 주문을 넣을 수 없습니다. `error.code`는 다음 중 하나입니다.


            - `project_locked`: 같은 프로젝트에 주문이 이미 진행 중입니다. 잠시 후 다시 시도합니다

            - `project_not_editing`: 이미 주문된 프로젝트입니다. `error.details.status`에 현재
            상태, `error.details.order_id`에 기존 주문 id가 있습니다

            - `doc_not_found`: 저장된 문서가 없습니다
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorBody'
              examples:
                project_not_editing:
                  summary: project_not_editing
                  value:
                    error:
                      code: project_not_editing
                      message: 잠정 주문은 status가 editing일 때만 가능합니다 (현재 ordering)
                      details:
                        status: ordering
                        order_id: 100023
                      request_id: 4bf92f3577b34da6a3ce929d0e0e4736
                project_locked:
                  summary: project_locked
                  value:
                    error:
                      code: project_locked
                      message: project -LiBngTbCFYNjcOVcxcY는 이미 주문 처리 중입니다
                      request_id: 4bf92f3577b34da6a3ce929d0e0e4736
                doc_not_found:
                  summary: doc_not_found
                  value:
                    error:
                      code: doc_not_found
                      message: 저장된 문서가 없습니다
                      request_id: 4bf92f3577b34da6a3ce929d0e0e4736
components:
  schemas:
    TentativeOrderBody:
      type: object
      properties:
        order_count:
          type: integer
          minimum: 1
          description: 주문 수량. 1 이상의 정수입니다
        total_price:
          type: number
          minimum: 0
          description: 실 결제 금액. 0 이상입니다
        partner_order_id:
          type: string
          maxLength: 255
          description: 파트너사 주문 번호. 255자 이내입니다
        order_name:
          type: string
          maxLength: 255
          description: >-
            주문을 구분하는 이름(주문명). 형식은 정해져 있지 않아 주문자 이름을 넣어도 됩니다. 255자 이내입니다. 렌더링 변수
            $OT는 userdata_json의 order_name이 없을 때 이 값을 씁니다
        order_for_test:
          type: boolean
          default: false
          description: 렌더링 테스트용 주문 여부입니다. `true`면 테스트용 렌더링 환경에서만 렌더링됩니다
        link_order:
          type: boolean
          default: false
          description: Edicus Link 주문 여부입니다. 일반 연동에서는 보내지 않습니다
        userdata_json:
          type: string
          maxLength: 1000
          default: '{}'
          description: >-
            사용자 데이터를 JSON 문자열로 저장합니다. 렌더링할 때 고객 정보가 필요하면 이 필드로 전달합니다. 1000자 이내의
            JSON 문자열이어야 하고, 아니면 `400 invalid_request`입니다.


            ```json

            {
              "user_name": "주문자 이름",
              "receiver_name": "수령인 이름",
              "order_name": "주문명",
              "production_count": 1,
              "title": "제목"
            }

            ```
        vdp_dataset:
          allOf:
            - $ref: '#/components/schemas/VariableDataSet'
          description: >-
            가변 데이터입니다. dataset 객체를 그대로 넣습니다. 서버가 직렬화해서 저장하므로 미리 stringify하지
            않습니다. 대량 데이터는 잠정 주문(VDP)의 `vdp_dataset_file`을 씁니다
      required:
        - order_count
        - total_price
      description: 잠정 주문을 넣을 때 보내는 body입니다. `order_count`와 `total_price`는 필수입니다.
    TentativeOrderMultipartBody:
      type: object
      description: >-
        multipart/form-data로 보낼 때의 필드입니다. `vdp_dataset_file`을 뺀 모든 값이 문자열로 전달되고
        서버가 숫자와 불리언으로 바꿉니다.
      properties:
        order_count:
          type: string
          description: 주문 수량. 1 이상의 정수입니다
        total_price:
          type: string
          description: 실 결제 금액. 0 이상입니다
        partner_order_id:
          type: string
          description: 파트너사 주문 번호. 255자 이내입니다
        order_name:
          type: string
          description: >-
            주문을 구분하는 이름(주문명). 형식은 정해져 있지 않아 주문자 이름을 넣어도 됩니다. 255자 이내입니다. 렌더링 변수
            $OT는 userdata_json의 order_name이 없을 때 이 값을 씁니다
        order_for_test:
          type: string
          description: 렌더링 테스트용 주문 여부입니다. `true`면 테스트용 렌더링 환경에서만 렌더링됩니다
        link_order:
          type: string
          description: Edicus Link 주문 여부입니다. 일반 연동에서는 보내지 않습니다
        userdata_json:
          type: string
          description: >-
            사용자 데이터를 JSON 문자열로 저장합니다. 렌더링할 때 고객 정보가 필요하면 이 필드로 전달합니다. 1000자 이내의
            JSON 문자열이어야 하고, 아니면 `400 invalid_request`입니다.


            ```json

            {
              "user_name": "주문자 이름",
              "receiver_name": "수령인 이름",
              "order_name": "주문명",
              "production_count": 1,
              "title": "제목"
            }

            ```
        vdp_dataset_file:
          type: string
          format: binary
          description: JSON 문자열이 담긴 File 또는 Blob입니다. 있으면 `vdp_dataset`보다 우선합니다
      required:
        - order_count
        - total_price
    TentativeOrderResult:
      type: object
      properties:
        order_id:
          type: integer
          description: 주문 id. 고객사 DB에 기록해 둡니다
        status:
          type: string
          enum:
            - ordering
      required:
        - order_id
        - status
    ErrorBody:
      type: object
      description: '`api.edicus.io`의 모든 4xx와 5xx 응답 body입니다. 클라이언트는 `error.code`로 분기합니다.'
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: snake_case 오류 코드. 이 값으로 분기합니다
              example: project_not_found
            message:
              type: string
              description: 사람이 읽는 설명입니다. 파싱하지 않습니다
            details:
              type: object
              additionalProperties: true
              description: 선택. 검증 실패면 `issues`에 어긋난 항목 목록이, 상태 충돌이면 현재 상태가 들어 있습니다
            request_id:
              type: string
              description: 요청 id입니다. 응답 헤더 `x-request-id`와 같은 값이고, 문의할 때 함께 알려 줍니다
          required:
            - code
            - message
            - request_id
      required:
        - error
      example:
        error:
          code: project_not_found
          message: 프로젝트가 없습니다
          request_id: 4bf92f3577b34da6a3ce929d0e0e4736
    VariableDataSet:
      type: object
      description: 가변 데이터 전체. 한 행(`VariableDataRow`)이 출력물 하나에 대응한다.
      properties:
        rows:
          type: array
          items:
            $ref: '#/components/schemas/VariableDataRow'
      example:
        rows:
          - cols:
              - id: name
                value:
                  text: 전 지 현
                shrink: true
              - id: title-role
                value:
                  text: 최강미모
    VariableDataRow:
      type: object
      properties:
        cols:
          type: array
          items:
            $ref: '#/components/schemas/VariableData'
    VariableData:
      type: object
      required:
        - id
        - value
      properties:
        id:
          type: string
          description: 템플릿에 정의된 변수 id
        value:
          type: object
          properties:
            text:
              type: string
        shrink:
          type: boolean
          description: >-
            true면 텍스트가 줄바꿈되지 않도록 편집기가 장평을 자동 계산한다. 이 옵션을 쓰는 텍스트박스는 InDesign
            템플릿에서 장평값이 단일해야 한다.
        segment:
          type: boolean
          description: data merge 방식으로 만든 변수인 경우 true
  securitySchemes:
    edicusApiKey:
      type: apiKey
      in: header
      name: edicus-api-key
      description: 모션원에서 발급받는 API 키입니다. 외부에 유출되지 않도록 각별히 주의합니다.

````

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