# 고객 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/client/create POST /v1/client 새 고객(`Client`)을 생성합니다. `status.id` 미지정 시 비즈니스의 기본 클라이언트 상태가 할당될 수 있으니, 원하는 상태가 있다면 명시적으로 전달하세요. 별도 알림 없음. ### 커스텀 필드 * 플러그 Openapi는 고객의 커스텀 필드 값 수정을 지원합니다. * 커스텀 필드 자체의 수정은 비즈니스 설정 - 필드 설정 탭에서 수정하실 수 있습니다. * 수정 API의 `field_set` 필드를 활용하여 각 커스텀 필드의 값을 수정하실 수 있습니다. * 커스텀 필드는 총 8가지의 타입을 지원합니다. * 데이터 입력 예
데이터 타입 입력 예시
텍스트 (String)
          
            \{
                "field": \{
                     "id": 1
                },
                "value": "text"
            }
          
        
숫자 (Number) * 소수점 입력 가능
          
            \{
                "field": \{
                     "id": 2
                },
                "value": 12345
            }
          
        
멤버 (Member) * 해당 필드의 'member\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 3
                },
                "value": \[
                    \{
                        "id": 1
                    },
                    \{
                        "id": 2
                    }
                ]
            }
          
        
날짜 (Date)
          
            \{
                "field": \{
                     "id": 4
                },
                "value": "2025-03-01"
            }
          
        
시간 (Time)
          
            \{
                "field": \{
                     "id": 5
                },
                "value": "10:00:00"
            }
          
        
토글 (Boolean)
          
            \{
                "field": \{
                     "id": 6
                },
                "value": true
            }
          
        
단수선택 리스트 (Single List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 7
                },
                "value": \{
                    "id": "FEWKSLVE2"
                }
            }
          
        
복수선택 리스트 (Multi List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 8
                },
                "value": \[
                    \{
                        "id": "EFI4VLB2D"
                    },
                    \{
                        "id": "BORE32VKE"
                    }
                ]
            }
          
        
# 고객 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/client/delete DELETE /v1/client/{client_id} 고객을 삭제합니다. **Soft delete** (Client는 `SoftDeleteOrderedBaseModel`) — `is_deleted=True`로 마킹되며 목록 조회에서 제외됩니다. 연결된 의뢰/계약은 자동으로 해제되지 않습니다 (FK 참조 유지). 필요 시 각 자원의 수정 API로 별도 처리하세요. # 고객 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/client/list GET /v1/client 비즈니스의 고객 목록을 최신순(`created` DESC)으로 조회합니다. **검색:** `search` 쿼리 파라미터는 복수 전달 시 AND 결합으로 동작합니다 (예: `?search=A&search=B`는 회사명/담당자/연락처/이메일 중 A·B 모두 포함하는 고객만 반환). **filter:** `OpenapiClientFilter`로 status 등 필터링 가능. # 고객 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/client/patch PATCH /v1/client/{client_id} 고객 정보를 부분 수정합니다. `status.id` 변경 시 별도 상태 이력은 기록되지 않습니다 (의뢰와 달리). ### 커스텀 필드 * 플러그 Openapi는 고객의 커스텀 필드 값 수정을 지원합니다. * 커스텀 필드 자체의 수정은 비즈니스 설정 - 필드 설정 탭에서 수정하실 수 있습니다. * 수정 API의 `field_set` 필드를 활용하여 각 커스텀 필드의 값을 수정하실 수 있습니다. * 커스텀 필드는 총 8가지의 타입을 지원합니다. * 데이터 입력 예
데이터 타입 입력 예시
텍스트 (String)
          
            \{
                "field": \{
                     "id": 1
                },
                "value": "text"
            }
          
        
숫자 (Number) * 소수점 입력 가능
          
            \{
                "field": \{
                     "id": 2
                },
                "value": 12345
            }
          
        
멤버 (Member) * 해당 필드의 'member\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 3
                },
                "value": \[
                    \{
                        "id": 1
                    },
                    \{
                        "id": 2
                    }
                ]
            }
          
        
날짜 (Date)
          
            \{
                "field": \{
                     "id": 4
                },
                "value": "2025-03-01"
            }
          
        
시간 (Time)
          
            \{
                "field": \{
                     "id": 5
                },
                "value": "10:00:00"
            }
          
        
토글 (Boolean)
          
            \{
                "field": \{
                     "id": 6
                },
                "value": true
            }
          
        
단수선택 리스트 (Single List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 7
                },
                "value": \{
                    "id": "FEWKSLVE2"
                }
            }
          
        
복수선택 리스트 (Multi List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 8
                },
                "value": \[
                    \{
                        "id": "EFI4VLB2D"
                    },
                    \{
                        "id": "BORE32VKE"
                    }
                ]
            }
          
        
# 고객 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/client/retrieve GET /v1/client/{client_id} 단일 고객의 상세 정보를 조회합니다. 회사 정보, 담당자, 연락처, 상태(`status`)가 nested로 포함됩니다. # 고객 상태 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/client/status/list GET /v1/client/status 비즈니스의 고객 상태(`ClientStatus`) 카탈로그를 조회합니다. 고객 생성/수정 시 `status.id`로 참조합니다. 각 상태는 비즈니스별로 별도 관리됩니다. # 계약 카테고리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/category/list GET /v1/contract/category 비즈니스의 계약 카테고리(ContractCategory) 카탈로그를 `order` 내림차순으로 조회합니다. 카테고리는 계약(`Contract`)의 분류 태그로 사용되며, 한 계약에 여러 카테고리를 다대다로 연결할 수 있습니다. # 계약 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/create POST /v1/contract 새 계약을 생성합니다. **관계 연결:** - `inquiry.id` 지정 시 해당 의뢰와 1:1 연결 (한 의뢰당 최대 1개 계약) - `client.id`로 고객 연결 (필수) - `category_set`에 ContractCategory ID를 전달하면 다대다 연결 **정산 관련 필드(`settlement_day`)** 의미는 필드 스키마의 help_text 참조. # 계약 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/delete DELETE /v1/contract/{contract_id} 계약을 삭제합니다. **Soft delete** (Contract는 `SoftDeleteOrderedBaseModel`) — `is_deleted=True`로 마킹되며 목록 조회에서 제외됩니다. 연결된 의뢰의 `contract` 참조는 자동 해제되지 않으니 필요 시 의뢰 수정 API로 별도 처리. # 계약 히스토리 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/history/create POST /v1/contract/{contract_id}/history 계약에 새 텍스트 히스토리를 추가합니다. `member` 미지정 시 작성 멤버는 null로 기록됩니다 (외부 API 호출 컨텍스트). 별도 알림은 발송되지 않습니다. # 계약 히스토리 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/history/delete DELETE /v1/contract/{contract_id}/history/{history_id} 텍스트 히스토리를 삭제합니다. **Hard delete** (`ContractTextHistory`는 `BaseModel`) — DB에서 영구 제거됩니다. # 계약 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/history/list GET /v1/contract/{contract_id}/history 특정 계약의 텍스트 히스토리(`ContractTextHistory`) 목록을 조회합니다. 각 항목은 content, 작성 멤버(`member`), 생성 시간(`created`)을 포함합니다. # 계약 히스토리 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/history/patch PATCH /v1/contract/{contract_id}/history/{history_id} 텍스트 히스토리의 `content` 필드를 수정합니다. 별도 알림 없음. # 계약 히스토리 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/history/retrieve GET /v1/contract/{contract_id}/history/{history_id} 단일 텍스트 히스토리의 상세를 조회합니다. content, 작성 멤버, 생성 시간을 포함합니다. # 계약 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/list GET /v1/contract 비즈니스의 계약 목록을 최신순(`created` DESC)으로 조회합니다. **관련 자원:** 연결된 의뢰(`inquiry`), 고객(`client`), 카테고리(`category_set`) 정보가 nested로 포함됩니다. **filter:** `OpenapiContractFilter`로 client/inquiry/category/status 등 필터링 가능. # 계약 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/patch PATCH /v1/contract/{contract_id} 계약 정보를 부분 수정합니다. `inquiry` 변경 시 의뢰 ↔ 계약 1:1 관계가 재설정되며, 기존 연결된 의뢰는 자동으로 해제됩니다. `category_set`은 전체 재설정 방식. # 계약 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/contract/retrieve GET /v1/contract/{contract_id} 단일 계약의 상세 정보를 조회합니다. 연결된 의뢰, 고객, 카테고리, 정산 관련 필드를 모두 포함합니다. # 견적서 항목 템플릿 분류 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/estimate/item/classification/list GET /v1/estimate/item/classification 비즈니스의 견적서 항목 분류(`BusinessEstimateItemClassification`) 카탈로그를 조회합니다. 분류는 견적서 항목의 그룹화 단위입니다 (예: '디자인', '개발', '운영'). 항목 생성 시 `classification.id`로 참조하며, 분류 자체의 순서는 `order` 필드로 관리됩니다. # 견적서 항목 템플릿 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/estimate/item/create POST /v1/estimate/item 새 견적서 항목을 생성합니다. `classification.id`로 분류를 지정합니다(별도 분류 목록 API 참조). 단가(`unit_cost`), 단위(`unit`), 설명 등 필드는 스키마의 help_text 참조. # 견적서 항목 템플릿 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/estimate/item/delete DELETE /v1/estimate/item/{item_id} 견적서 항목을 삭제합니다. **Hard delete** (`BusinessEstimateItem`은 `BaseModel`) — DB에서 영구 제거됩니다. 참고: 이 항목을 사용 중이던 견적서(Estimate)의 기존 라인은 영향받지 않습니다 (라인은 별도 모델에 복사 저장). # 견적서 항목 템플릿 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/estimate/item/list GET /v1/estimate/item 비즈니스의 견적서 항목(`BusinessEstimateItem`) 목록을 조회합니다. 각 항목은 분류(`classification`)로 그룹화됩니다. **filter:** `OpenapiEstimateItemFilter`로 classification 등 필터링 가능. # 견적서 항목 템플릿 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/estimate/item/patch PATCH /v1/estimate/item/{item_id} 견적서 항목의 단가(`unit_cost`), 단위(`unit`), 분류(`classification`) 등을 수정합니다. 별도 알림 없음. # 견적서 항목 템플릿 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/estimate/item/retrieve GET /v1/estimate/item/{item_id} 단일 견적서 항목의 상세 정보를 조회합니다. 분류, 단가, 단위, 설명 등을 포함합니다. # 필드 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/field/list GET /v1/field 비즈니스의 커스텀 필드(`Field`) 목록을 조회합니다. 각 필드는 옵션(`option_set`)을 nested로 포함합니다. **용도:** 의뢰 생성/수정 시 `field_set[].field_id`로 참조됩니다. 필드 타입(`type`)에 따라 옵션 형태가 달라집니다 (텍스트, 숫자, 단일 선택, 다중 선택 등). 옵션 ID는 단일/다중 선택 타입에서 `value`로 사용됩니다. **filter:** `OpenapiFieldFilter`로 type 등 필터링 가능. # 폴더 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/folder/list GET /v1/folder 비즈니스의 폴더(`Folder`) 목록을 조회합니다. **정렬:** `is_default=True`인 기본 폴더가 먼저, 그 다음 생성순 역순(`-created`). **용도:** 의뢰 상태(InquiryStatus)가 폴더에 속하며, 의뢰 생성 시 폴더는 status를 통해 간접 지정됩니다. 기본 폴더는 시스템상 1개 보장되며 삭제 불가입니다. **filter:** `OpenapiFolderFilter` 사용 가능. # 의뢰 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/create POST /v1/inquiry 새 의뢰를 생성합니다. **자동 처리:** - `status` 미입력 시 기본 폴더의 기본 상태로 자동 할당 - 생성 직후 `InquiryStatusHistory` 1건 자동 생성 - `in_charge_set` 지정 시 알림 설정이 켜진 담당자에게 `MemberNotification` + 이메일/푸시 알림 발송 (비동기) - `inquiry_date` 미입력 시 오늘 날짜, `estimate` 미입력 시 0, `name` 미입력 시 '의뢰 제목' **파일 첨부:** `file_set`에 presigned API 응답의 `name`/`path`를 전달. 최대 30개. ### 커스텀 필드 * 플러그 Openapi는 의뢰의 커스텀 필드 값 수정을 지원합니다. * 커스텀 필드 자체의 수정은 비즈니스 설정 - 필드 설정 탭에서 수정하실 수 있습니다. * 수정 API의 `field_set` 필드를 활용하여 각 커스텀 필드의 값을 수정하실 수 있습니다. * 커스텀 필드는 총 8가지의 타입을 지원합니다. * 데이터 입력 예
데이터 타입 입력 예시
텍스트 (String)
          
            \{
                "field": \{
                     "id": 1
                },
                "value": "text"
            }
          
        
숫자 (Number) * 소수점 입력 가능
          
            \{
                "field": \{
                     "id": 2
                },
                "value": 12345
            }
          
        
멤버 (Member) * 해당 필드의 'member\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 3
                },
                "value": \[
                    \{
                        "id": 1
                    },
                    \{
                        "id": 2
                    }
                ]
            }
          
        
날짜 (Date)
          
            \{
                "field": \{
                     "id": 4
                },
                "value": "2025-03-01"
            }
          
        
시간 (Time)
          
            \{
                "field": \{
                     "id": 5
                },
                "value": "10:00:00"
            }
          
        
토글 (Boolean)
          
            \{
                "field": \{
                     "id": 6
                },
                "value": true
            }
          
        
단수선택 리스트 (Single List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 7
                },
                "value": \{
                    "id": "FEWKSLVE2"
                }
            }
          
        
복수선택 리스트 (Multi List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 8
                },
                "value": \[
                    \{
                        "id": "EFI4VLB2D"
                    },
                    \{
                        "id": "BORE32VKE"
                    }
                ]
            }
          
        
# 의뢰 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/delete DELETE /v1/inquiry/{inquiry_id} 의뢰를 삭제합니다. **Soft delete** (Inquiry는 `SoftDeleteOrderedBaseModel`) — DB에서는 `is_deleted=True`로 마킹되며 목록 조회에서 자동 제외됩니다. 삭제된 의뢰의 첨부 파일, 텍스트 히스토리, 상태/폴더 이력은 별도 정리되지 않습니다 (참조 무결성 위해 보존). # 의뢰 이메일 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/email-history/list GET /v1/inquiry/{inquiry_id}/email_history 의뢰에서 발송한 이메일 이력을 조회합니다. 수신자(to), 참조(cc), 발송 상태(S:발송, D:임시저장, C:발송예약, F:실패) 정보를 포함합니다. # 의뢰 이메일 회신 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/email-reply-history/list GET /v1/inquiry/{inquiry_id}/email_reply_history 의뢰에 대해 수신된 답장 이메일 이력을 조회합니다. 발신자(from), 수신자(to), 참조(cc), 읽지 않음 여부(is_unread) 정보를 포함합니다. # 의뢰 파일 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/file/delete DELETE /v1/inquiry/{inquiry_id}/file/{file_id} 의뢰에 첨부된 특정 파일을 삭제합니다. 삭제할 파일의 ID는 의뢰 상세 조회 API의 `file_set[].id`에서 확인할 수 있습니다. # 의뢰 폴더 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/folder-history/list GET /v1/inquiry/{inquiry_id}/folder_history 의뢰의 폴더 이동 이력을 조회합니다. 이전 폴더명, 현재 폴더명, 변경한 멤버 정보를 포함합니다. # 의뢰 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/list GET /v1/inquiry 비즈니스의 의뢰 목록을 최신순(`created` DESC)으로 조회합니다. **검색:** `search` 쿼리 파라미터는 복수 전달 시 AND 결합으로 동작합니다 (예: `?search=A&search=B`는 의뢰명/고객사명/담당자/연락처/이메일 중 A·B 모두 포함하는 의뢰만 반환). **filter:** `OpenapiInquiryFilter`로 status/folder/contract 등 필터링 가능. # 의뢰 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/patch PATCH /v1/inquiry/{inquiry_id} 의뢰 정보를 부분 수정합니다. **파일 추가:** `file_set`에 presigned API로 발급받은 name과 path를 전달하면 기존 파일은 유지한 채 새 파일만 추가됩니다 (append). 파일 삭제는 별도의 DELETE API를 사용하세요. 최대 30개까지 첨부 가능합니다 (기존 + 추가분 합산). **부수효과:** - `status` 변경 시: `InquiryStatusHistory` 자동 생성, folder가 함께 바뀌면 `InquiryFolderHistory`도 생성. 알림 설정이 켜진 담당자에게 상태 변경 알림 발송. - `in_charge_set` 변경 시: 신규 담당자에게 'XX 담당자로 지정되었어요' 알림 발송 (알림 설정 켜진 경우). - 알림은 모두 비동기 처리 (`transaction.on_commit` 후 Celery task 발송). ### 커스텀 필드 * 플러그 Openapi는 의뢰의 커스텀 필드 값 수정을 지원합니다. * 커스텀 필드 자체의 수정은 비즈니스 설정 - 필드 설정 탭에서 수정하실 수 있습니다. * 수정 API의 `field_set` 필드를 활용하여 각 커스텀 필드의 값을 수정하실 수 있습니다. * 커스텀 필드는 총 8가지의 타입을 지원합니다. * 데이터 입력 예
데이터 타입 입력 예시
텍스트 (String)
          
            \{
                "field": \{
                     "id": 1
                },
                "value": "text"
            }
          
        
숫자 (Number) * 소수점 입력 가능
          
            \{
                "field": \{
                     "id": 2
                },
                "value": 12345
            }
          
        
멤버 (Member) * 해당 필드의 'member\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 3
                },
                "value": \[
                    \{
                        "id": 1
                    },
                    \{
                        "id": 2
                    }
                ]
            }
          
        
날짜 (Date)
          
            \{
                "field": \{
                     "id": 4
                },
                "value": "2025-03-01"
            }
          
        
시간 (Time)
          
            \{
                "field": \{
                     "id": 5
                },
                "value": "10:00:00"
            }
          
        
토글 (Boolean)
          
            \{
                "field": \{
                     "id": 6
                },
                "value": true
            }
          
        
단수선택 리스트 (Single List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 7
                },
                "value": \{
                    "id": "FEWKSLVE2"
                }
            }
          
        
복수선택 리스트 (Multi List) * 해당 필드의 'option\_set'에서 id 선택
          
            \{
                "field": \{
                     "id": 8
                },
                "value": \[
                    \{
                        "id": "EFI4VLB2D"
                    },
                    \{
                        "id": "BORE32VKE"
                    }
                ]
            }
          
        
# 의뢰 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/retrieve GET /v1/inquiry/{inquiry_id} 의뢰 상세 정보를 조회합니다. `file_set`에 첨부 파일 목록이 presigned 다운로드 URL과 함께 포함됩니다. # 의뢰 단계 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/status-history/list GET /v1/inquiry/{inquiry_id}/status_history 의뢰의 상태 변경 이력을 조회합니다. 변경된 상태명, 상징 색, 변경한 멤버 정보를 포함합니다. # 의뢰 단계 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/status/list GET /v1/inquiry/status 비즈니스의 의뢰 상태(InquiryStatus) 카탈로그를 조회합니다. 각 상태는 특정 폴더에 속하며 (`folder` 필드), 의뢰 생성/수정 시 `status.id`로 참조됩니다. 기본 폴더의 기본 상태는 의뢰 생성 시 status 미지정 시 자동 할당됩니다. # 의뢰 웹폼 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/submit-history/list GET /v1/inquiry/{inquiry_id}/submit_history 의뢰에 연결된 웹 폼 제출 이력을 조회합니다. 제출된 폼의 ID와 제목 정보를 포함합니다. # 의뢰 텍스트 히스토리 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/text-history/create POST /v1/inquiry/{inquiry_id}/text_history 의뢰에 새로운 텍스트 히스토리를 추가합니다. 담당자에게 알림이 발송됩니다. # 의뢰 텍스트 히스토리 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/text-history/delete DELETE /v1/inquiry/{inquiry_id}/text_history/{history_id} 텍스트 히스토리를 삭제합니다. **Hard delete** (`InquiryTextHistory`는 `BaseModel`) — DB에서 영구 제거됩니다. 별도 알림 없음. # 의뢰 텍스트 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/text-history/list GET /v1/inquiry/{inquiry_id}/text_history 의뢰의 텍스트 히스토리를 조회합니다. 내용, 작성 멤버, 생성 시간 정보를 포함합니다. # 의뢰 텍스트 히스토리 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/text-history/patch PATCH /v1/inquiry/{inquiry_id}/text_history/{history_id} 텍스트 히스토리의 `content` 필드를 수정합니다. **알림은 발송되지 않습니다** (생성 시에만 발송). # 의뢰 텍스트 히스토리 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/text-history/retrieve GET /v1/inquiry/{inquiry_id}/text_history/{history_id} 특정 텍스트 히스토리의 상세 정보를 조회합니다. content, 작성 멤버(`member`), 생성 시간(`created`)을 포함합니다. # 의뢰 작업 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/inquiry/work/list GET /v1/inquiry/work 비즈니스에 등록된 업무(Work) 카탈로그를 조회합니다. 의뢰 생성/수정 시 `work_set[].name`으로 업무를 참조합니다. 업무는 의뢰별로 다대다 연결됩니다. # 로그 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/log/list GET /v1/log/ 현 비즈니스의 openapi 호출 로그를 조회합니다. **범위:** 최근 14일 이내 호출만 반환합니다. **응답 필드:** method, path, status_code, ip_address, referrer, request_body(JSON), response_body(JSON), created. openapi.json 조회와 swagger UI 요청은 로깅에서 제외됩니다. # 멤버 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/member/list GET /v1/member 비즈니스의 멤버(`Member`) 목록을 최신순(`created` DESC)으로 조회합니다. 각 멤버는 사용자 정보(`user`)와 등급(`grade`)을 nested로 포함합니다. **플랜 제약:** FREE/TEAM/AGENCY 플랜에서만 사용 가능 — 다른 플랜은 403 `PLAN_PERMISSION_DENIED`. **검색:** `search` 쿼리 파라미터는 복수 전달 시 AND 결합으로 동작합니다 (예: `?search=A&search=B`는 닉네임/이메일 중 A·B 모두 포함하는 멤버만 반환). **용도:** 의뢰 담당자(`in_charge_set`) 지정 시 `Member.id`로 참조됩니다. # Presigned URL 발급 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/presigned/create POST /v1/presigned S3 업로드용 presigned PUT URL을 발급합니다. **사용 흐름:** 1. 이 API를 호출하여 presigned URL과 path를 발급받습니다. 2. 응답의 `url`로 파일을 직접 업로드합니다. (PUT 요청, Content-Type: 파일 MIME 타입, Body: 파일 바이너리) 3. 응답의 `path`를 의뢰 생성/수정 API의 `file_set[].file` 필드에 전달합니다. **제약 사항:** - 허용 확장자: pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, jpg, jpeg, png, gif, zip - presigned URL 유효 시간: 60초 - 파일당 1회 호출 필요 # 프로젝트 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/project/create POST /v1/project 새 프로젝트를 생성합니다. `contract.id`로 계약 연결 가능 (선택). **플랜 제약:** FREE 또는 AGENCY 플랜에서만 사용 가능. # 프로젝트 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/project/delete DELETE /v1/project/{project_id} 프로젝트를 삭제합니다. **Soft delete** (Project는 `SoftDeleteBaseModel`) — `is_deleted=True`로 마킹. **플랜 제약:** FREE/AGENCY 전용. # 프로젝트 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/project/list GET /v1/project 비즈니스의 프로젝트 목록을 조회합니다. 연결된 계약(`contract`)이 nested로 포함됩니다. **플랜 제약:** FREE 또는 AGENCY 플랜에서만 사용 가능 — 다른 플랜은 403 `PLAN_PERMISSION_DENIED`. **filter:** `OpenapiProjectFilter`로 contract/status 등 필터링 가능. # 프로젝트 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/project/patch PATCH /v1/project/{project_id} 프로젝트 정보를 부분 수정합니다. 상태(`status`) 의미는 필드 help_text 참조 (예정/진행 중/추가 기간/종료됨). **플랜 제약:** FREE/AGENCY 전용. # 프로젝트 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/project/retrieve GET /v1/project/{project_id} 단일 프로젝트의 상세 정보를 조회합니다. **플랜 제약:** FREE/AGENCY 전용. # 정산 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/create POST /v1/settlement 새 정산을 생성합니다. **필수 관계:** `contract.id`(계약 ID), `type.id`(정산 형태 ID, 미수금 OUTSTANDING_PAYMENT는 사용 불가). 정산 형태에 따라 단일 결제/정기 결제 등 정산 흐름이 결정됩니다. 정산 상태 변경 이력은 정산 상세/수정 API의 부수효과로 자동 기록됩니다. ### 🚫 제한사항 1. 계약 * 계약은 시작일과 종료일이 모두 지정되어 있어야 합니다. * 중단된 계약에 대해서는 정산을 생성할 수 없습니다. 2. 정산 형태 * 다차수 생성을 허용하지 않는 정산 형태는 같은 형태로 여러개 생성할 수 없습니다. (추가 정산, 미수 정산 제외) # 정산 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/delete DELETE /v1/settlement/{settlement_id} 정산을 삭제합니다. **Soft delete** (Settlement는 `SoftDeleteOrderedBaseModel`) — `is_deleted=True`로 마킹되며 목록에서 제외됩니다. # 정산 히스토리 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/history/create POST /v1/settlement/{settlement_id}/history 정산에 새 텍스트 히스토리를 추가합니다. `member` 미지정 시 작성 멤버는 null (외부 API 호출 컨텍스트). 별도 알림 없음. # 정산 히스토리 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/history/delete DELETE /v1/settlement/{settlement_id}/history/{history_id} 텍스트 히스토리를 삭제합니다. **Hard delete** (`SettlementTextHistory`는 `BaseModel`) — DB에서 영구 제거됩니다. # 정산 히스토리 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/history/list GET /v1/settlement/{settlement_id}/history 특정 정산의 텍스트 히스토리(`SettlementTextHistory`) 목록을 조회합니다. 각 항목은 content, 작성 멤버(`member`), 생성 시간을 포함합니다. # 정산 히스토리 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/history/patch PATCH /v1/settlement/{settlement_id}/history/{history_id} 텍스트 히스토리의 `content` 필드를 수정합니다. 별도 알림 없음. # 정산 히스토리 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/history/retrieve GET /v1/settlement/{settlement_id}/history/{history_id} 단일 텍스트 히스토리의 상세를 조회합니다. content, 작성 멤버, 생성 시간을 포함합니다. # 정산 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/list GET /v1/settlement 비즈니스의 정산 목록을 최신순(`created` DESC)으로 조회합니다. 연결된 계약(`contract`)과 정산 형태(`type`)가 nested로 포함됩니다. **filter:** `OpenapiSettlementFilter`로 contract/type/status 필터링 가능. # 정산 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/patch PATCH /v1/settlement/{settlement_id} 정산 정보를 부분 수정합니다. **부수효과:** `status` 변경 시 `SettlementStatusHistory`가 자동 생성됩니다. 변경 이력은 정산 히스토리 API로 조회할 수 있습니다. # 정산 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/retrieve GET /v1/settlement/{settlement_id} 단일 정산의 상세 정보를 조회합니다. 계약/정산 형태/날짜 필드 일체를 포함합니다. # 정산 형태 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/settlement/type/list GET /v1/settlement/type 비즈니스의 정산 형태(`SettlementType`) 카탈로그를 생성순(`created`)으로 조회합니다. **제외:** `base_type == OUTSTANDING_PAYMENT`(미수금)은 시스템 내부용이므로 응답에서 제외됩니다. 정산 생성 시 `type.id`로 참조됩니다. # Todo 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/todo/create POST /v1/todo 새 Todo를 생성합니다. `inquiry.id`(필수)로 의뢰 연결, `in_charge.id`로 담당자 지정. Todo 타입(`type`), 마감 시간(`due_time`) 등 필드는 스키마 help_text 참조. # Todo 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/todo/delete DELETE /v1/todo/{todo_id} Todo를 삭제합니다. **Hard delete** (`InquiryTodo`는 `BaseModel`) — DB에서 영구 제거됩니다. # Todo 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/todo/list GET /v1/todo 비즈니스의 Todo 목록(`InquiryTodo`)을 조회합니다. Todo는 의뢰(`Inquiry`)에 종속되며 담당자(`in_charge`)가 지정됩니다. **filter:** `OpenapiTodoFilter`로 inquiry/in_charge/completed 등 필터링 가능. # Todo 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/todo/patch PATCH /v1/todo/{todo_id} Todo 정보를 부분 수정합니다. **완료 처리** (`is_completed=true`)할 때 `completed_in_charge`가 자동 설정됩니다. 별도 알림은 발송되지 않습니다. # Todo 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/todo/retrieve GET /v1/todo/{todo_id} 단일 Todo의 상세 정보를 조회합니다. 의뢰, 담당자, 완료 담당자(`completed_in_charge`) 정보를 포함합니다. # 실무자 생성 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/worker/create POST /v1/worker 새 실무자를 생성합니다. `position.id`로 직급 연결(선택). **플랜 제약:** FREE/AGENCY 전용. # 실무자 삭제 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/worker/delete DELETE /v1/worker/{worker_id} 실무자를 삭제합니다. **Soft delete** (Worker는 `SoftDeleteBaseModel`, `perform_destroy`에서 `instance.delete()` 호출 시 `is_deleted=True`로 마킹). 삭제된 실무자는 목록 조회에서 제외됩니다. **플랜 제약:** FREE/AGENCY 전용. # 실무자 목록 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/worker/list GET /v1/worker 비즈니스의 실무자(`Worker`) 목록을 조회합니다. 삭제된 실무자(`is_deleted=True`)는 제외됩니다. **플랜 제약:** FREE 또는 AGENCY 플랜에서만 사용 가능 — 다른 플랜은 403 `PLAN_PERMISSION_DENIED`. **filter:** `OpenapiWorkerFilter`로 position 등 필터링 가능. # 실무자 부분 수정 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/worker/patch PATCH /v1/worker/{worker_id} 실무자 정보를 부분 수정합니다. `position.id` 변경 시 직급이 재할당됩니다. **플랜 제약:** FREE/AGENCY 전용. # 실무자 단일 조회 Source: https://docs.openapi.pluuug.com/api-reference/endpoints/worker/retrieve GET /v1/worker/{worker_id} 단일 실무자의 상세 정보를 조회합니다. 직급(`position`) 정보를 포함합니다. **플랜 제약:** FREE/AGENCY 전용. # 🔐 인증 방식 Source: https://docs.openapi.pluuug.com/authentication 플러그 오픈 API는 API Key와 Signature 기반의 인증 방식을 사용합니다. ## 인증 방식 안내 플러그 오픈 API는 **API Key + Signature** 기반의 인증 방식을 사용합니다. 모든 API 요청 시 두 가지 인증 정보를 **반드시 헤더에 포함**해야 합니다. 모든 API 요청 시 아래 헤더를 포함해야 합니다. * `X-API-KEY`: 발급받은 API Key * `X-Signature`: 요청 본문에 대한 HMAC 서명값 `X-Signature`가 없는 요청은 인증되지 않으며, 서버에서 거부됩니다. Signature는 API Key 발급 시 함께 제공된 Secret Key를 사용하여 생성합니다. * 알고리즘: HMAC-SHA256 * 서명 대상: 요청 본문 (`request.body`) * 서버는 클라이언트가 보낸 Signature가 유효한지 검증합니다. Signature는 요청의 무결성을 보장하며, 위변조 방지 목적이 있습니다. ### 💡 언어별 서명 예시 API 요청 시 `request.body`를 기준으로 HMAC-SHA256 서명을 생성합니다. 요청 본문이 없을 경우, 자동으로 빈 문자열(`""`)을 서명 대상으로 처리합니다. ```java theme={null} import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; public class HmacSignature { public static void main(String[] args) throws Exception { String secretKey = "your-secret-key"; String body = getBody(); // 요청 본문이 있으면 JSON 문자열, 없으면 "" Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] hash = sha256_HMAC.doFinal(body.getBytes(StandardCharsets.UTF_8)); String signature = bytesToHex(hash); System.out.println(signature); } private static String getBody() { // 본문이 있을 경우 직렬화된 문자열 반환 // 없으면 return ""; return "{\"name\":\"pluuug\",\"type\":\"openapi\"}"; } private static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } } ``` ```python theme={null} import json, hmac, hashlib payload = {"name": "pluuug", "type": "openapi"} # 본문이 없으면 None body = json.dumps(payload, separators=(",", ":")) if payload else "" secret_key = "your-secret-key" signature = hmac.new(secret_key.encode(), body.encode(), hashlib.sha256).hexdigest() print(signature) ``` ```js theme={null} const payload = { name: "pluuug", type: "openapi" }; // 없으면 null const body = payload ? JSON.stringify(payload) : ""; async function generateSignature(secretKey, body) { const encoder = new TextEncoder(); const key = await crypto.subtle.importKey( "raw", encoder.encode(secretKey), { name: "HMAC", hash: "SHA-256" }, false, ["sign"] ); const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(body)); return [...new Uint8Array(signature)] .map(b => b.toString(16).padStart(2, "0")) .join(""); } generateSignature("your-secret-key", body).then(console.log); ``` ```js theme={null} const crypto = require("crypto"); const payload = { name: "pluuug", type: "openapi" }; // 없으면 null const body = payload ? JSON.stringify(payload) : ""; const secretKey = "your-secret-key"; const signature = crypto .createHmac("sha256", secretKey) .update(body) .digest("hex"); console.log(signature); ``` ```php theme={null} $payload = ['name' => 'pluuug', 'type' => 'openapi']; // 없으면 null $body = $payload ? json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : ""; $secretKey = 'your-secret-key'; $signature = hash_hmac('sha256', $body, $secretKey); echo $signature; ``` ```go theme={null} package main import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" ) func main() { payload := map[string]string{ "name": "pluuug", "type": "openapi", } var bodyBytes []byte if payload != nil { bodyBytes, _ = json.Marshal(payload) } else { bodyBytes = []byte("") } secretKey := []byte("your-secret-key") h := hmac.New(sha256.New, secretKey) h.Write(bodyBytes) signature := hex.EncodeToString(h.Sum(nil)) fmt.Println(signature) } ``` # 📋 변경 기록 Source: https://docs.openapi.pluuug.com/changelog 플러그 오픈 API의 버전별 변경 사항을 안내합니다. ## 2026-04-08 ### 🆕 추가 * **의뢰 고유번호(`uniqueId`) 필드** — 모든 의뢰 관련 응답에 추가 * 의뢰 목록(`GET /v1/inquiry`), 상세(`GET /v1/inquiry/{id}`) 응답에 포함 * 계약, 할일 등 의뢰를 참조하는 중첩 객체에도 포함 * UI에 표시되는 의뢰 고유번호(예: `Bw4TXy1JAl`)와 동일한 값 * 읽기 전용, nullable ## 2026-03-23 ### 🆕 추가 * **의뢰 파일 첨부 기능** 추가 * `POST /v1/presigned` — 파일 업로드용 Presigned URL 발급 * 의뢰 생성(`POST`), 수정(`PATCH`) 시 `file_set`으로 파일 첨부 지원 (최대 30개) * 의뢰 조회(`GET`) 시 첨부 파일 목록 및 다운로드 URL 포함 * `DELETE /v1/inquiry/{inquiry_id}/file/{file_id}` — 의뢰 첨부 파일 삭제 * **의뢰 작업 목록 API** 신규 추가 * `GET /v1/inquiry/work` — 의뢰 작업 목록 조회 * **로그 API** 신규 추가 * `GET /v1/log/` — 로그 목록 조회 ## 2026-03-06 ### 🔄 변경 * **의뢰 API** — `fileLinkSet` (링크 첨부) 필드 추가 * 의뢰 생성(`POST`), 조회(`GET`), 수정(`PATCH`) 시 링크 첨부 지원 * **전체 API** — nullable 필드 처리 개선 및 필수/선택 정리 * 미입력 시 기본값이 생성되는 필드들을 nullable + optional로 변경 * **고객**: `status`, `contact`, `email`, `inCharge` 등 대부분 필드 선택으로 변경 (`companyName`만 필수) * **의뢰**: `client`, `contract`, `funnel`, `status`, `name` 등 선택으로 변경 (미입력 시 기본값 생성) * **계약**: `endDate`, `startDate`, `client`, `inquiry`, `fieldSet` 등 선택으로 변경 * **견적서**: `classification`, `description` 선택으로 변경 * **정산**: `dueDate`, `inChargeSet`, `settledDate` 등 선택으로 변경 * **Todo**: `inCharge`, `completedInCharge` nullable 처리 * **실무자**: `position` nullable 처리 ## 2026-03-03 ### 🆕 추가 * **프로젝트 API** 신규 추가 * `GET /v1/project` — 프로젝트 목록 조회 * `POST /v1/project` — 프로젝트 생성 * `GET /v1/project/{project_id}` — 프로젝트 단일 조회 * `PATCH /v1/project/{project_id}` — 프로젝트 부분 수정 * `DELETE /v1/project/{project_id}` — 프로젝트 삭제 * **실무자 API** 신규 추가 * `GET /v1/worker` — 실무자 목록 조회 * `POST /v1/worker` — 실무자 생성 * `GET /v1/worker/{worker_id}` — 실무자 단일 조회 * `PATCH /v1/worker/{worker_id}` — 실무자 부분 수정 * `DELETE /v1/worker/{worker_id}` — 실무자 삭제 * **의뢰 히스토리 API** 신규 추가 * `GET /v1/inquiry/{inquiry_id}/email_history` — 의뢰 이메일 히스토리 목록 조회 * `GET /v1/inquiry/{inquiry_id}/email_reply_history` — 의뢰 이메일 회신 히스토리 목록 조회 * `GET /v1/inquiry/{inquiry_id}/folder_history` — 의뢰 폴더 히스토리 목록 조회 * `GET /v1/inquiry/{inquiry_id}/status_history` — 의뢰 단계 히스토리 목록 조회 * `GET /v1/inquiry/{inquiry_id}/submit_history` — 의뢰 웹폼 히스토리 목록 조회 * `GET /v1/inquiry/{inquiry_id}/text_history` — 의뢰 텍스트 히스토리 목록 조회 * `POST /v1/inquiry/{inquiry_id}/text_history` — 의뢰 텍스트 히스토리 생성 * `GET /v1/inquiry/{inquiry_id}/text_history/{history_id}` — 의뢰 텍스트 히스토리 단일 조회 * `PATCH /v1/inquiry/{inquiry_id}/text_history/{history_id}` — 의뢰 텍스트 히스토리 부분 수정 * `DELETE /v1/inquiry/{inquiry_id}/text_history/{history_id}` — 의뢰 텍스트 히스토리 삭제 ### ⚠️ Deprecated * **의뢰 히스토리 API** Deprecated * `GET /v1/inquiry/{inquiry_id}/history` → `GET /v1/inquiry/{inquiry_id}/text_history` 로 대체 * `POST /v1/inquiry/{inquiry_id}/history` → `POST /v1/inquiry/{inquiry_id}/text_history` 로 대체 * `GET /v1/inquiry/{inquiry_id}/history/{history_id}` → `GET /v1/inquiry/{inquiry_id}/text_history/{history_id}` 로 대체 * `PATCH /v1/inquiry/{inquiry_id}/history/{history_id}` → `PATCH /v1/inquiry/{inquiry_id}/text_history/{history_id}` 로 대체 * `DELETE /v1/inquiry/{inquiry_id}/history/{history_id}` → `DELETE /v1/inquiry/{inquiry_id}/text_history/{history_id}` 로 대체 ### 🔒 보안 강화 * **X-Signature 필수화 예정** * 기존에는 `X-API-KEY`만으로 API에 접근할 수 있었지만, 앞으로 `X-Signature` 입력이 필수로 변경될 예정입니다. * `X-Signature`는 Secret Key를 기반으로 요청마다 생성되는 서명 값으로, API Key가 외부에 노출되더라도 무단 접근을 방지할 수 있습니다. * 정식 적용 일정은 추후 별도 공지를 통해 안내될 예정입니다. 현재 `X-Signature` 없이 API를 사용 중이시라면, 미리 서명 생성 로직을 적용해두시는 것을 권장합니다. * 자세한 서명 생성 방법은 [인증 가이드](/authentication)를 참고해주세요. *** ## 2026-02-27 ### 🆕 추가 * **Todo API** 신규 추가 * `GET /v1/todo` — Todo 목록 조회 * `POST /v1/todo` — Todo 생성 * `GET /v1/todo/{todo_id}` — Todo 단일 조회 * `PATCH /v1/todo/{todo_id}` — Todo 부분 수정 * `DELETE /v1/todo/{todo_id}` — Todo 삭제 *** ## 2026-02-25 ### 🔄 변경 * **목록 조회 API**에 `is_hidden` 필터 파라미터 추가 * `GET /v1/inquiry` · `GET /v1/contract` · `GET /v1/client` · `GET /v1/settlement` * `true`: 숨김 항목만 조회 / `false`: 비숨김 항목만 조회 / 미전달: 전체 조회 *** # 🤖 MCP 통합 Source: https://docs.openapi.pluuug.com/integrations/mcp Claude Desktop, Cursor 등에서 플러그 API를 자동 호출하도록 MCP(Model Context Protocol) 서버를 설치합니다. ## 개요 [MCP(Model Context Protocol)](https://modelcontextprotocol.io)는 AI 에이전트가 외부 도구를 호출할 수 있게 해주는 표준입니다. 플러그가 제공하는 MCP 서버를 자기 컴퓨터에 띄우면 Claude Desktop, Cursor 등에서 의뢰/계약/정산 등 플러그 데이터를 LLM 명령으로 다룰 수 있습니다. **예시:** "이번 달 신규 의뢰 보여줘", "ABC 회사 계약 상세 알려줘", "오늘 마감인 Todo 생성해줘" 같은 자연어 요청을 LLM이 알아서 플러그 API로 변환합니다. ## 사전 준비 플러그 관리자 페이지에서 발급합니다. **Secret Key는 발급 직후 1회만 표시**되므로 안전한 곳(1Password, OS 키체인 등)에 즉시 저장하세요. Secret Key를 잃어버리면 재발급이 필요합니다. 발급 즉시 저장하세요. 공식 사이트에서 다운로드: [https://claude.ai/download](https://claude.ai/download) Python 의존성(`uv`)이 없으면 아래 설치 명령이 자동으로 설치합니다. 별도 사전 준비는 필요 없습니다. ## 설치 (1줄 명령) 터미널을 열고 다음 명령을 실행하세요. 키 입력 prompt가 나오면 발급받은 값을 붙여넣으면 됩니다. ```bash theme={null} curl -fsSL https://raw.githubusercontent.com/postoo-io/pluuug-openapi-mcp/main/scripts/install.sh | bash ``` 스크립트가 자동으로 수행하는 작업: 1. macOS / Claude Desktop 설치 확인 2. `uv` 자동 설치 (미설치 시) 3. API Key / Secret Key 대화형 입력 4. Claude Desktop 설정 파일 백업 + `pluuug` MCP 서버 등록 5. wrapper 다운로드 + 의존성 설치 (20\~40초) 6. Claude Desktop 재기동 안내 **설치 전에 스크립트 내용을 확인하고 싶다면** — [scripts/install.sh](https://github.com/postoo-io/pluuug-openapi-mcp/blob/main/scripts/install.sh)에서 코드 전문을 볼 수 있습니다. 검증 후 실행하려면: ```bash theme={null} curl -O https://raw.githubusercontent.com/postoo-io/pluuug-openapi-mcp/main/scripts/install.sh shasum -a 256 install.sh # 게시된 hash와 대조 bash install.sh ``` 현재 **macOS만 지원**합니다. Windows/Linux는 추후 지원 예정입니다. ## Claude Desktop 재기동 설치 직후 Claude Desktop을 완전히 재기동해야 새 MCP 서버가 인식됩니다. 화면 **상단 메뉴바**의 \[Claude] 메뉴 → \[Claude 종료] 창의 빨간 X 버튼만 누르면 안 됩니다. 메뉴바 트레이에 살아있으면 설정이 적용되지 않습니다. Spotlight(Cmd+Space) 또는 Launchpad에서 Claude를 다시 실행합니다. ## 동작 검증 Claude Desktop 새 대화에서 다음과 같은 자연어를 입력해보세요: ``` "내 비즈니스의 최근 의뢰 5건 보여줘" ``` LLM이 자동으로 의뢰 목록 tool(`inquiry_list`)을 호출하고 결과를 보여주면 정상 동작입니다. **노출 도구 수:** 약 72개. 의뢰, 계약, 정산, 고객, 견적, 프로젝트, Todo, 실무자, 멤버, 폴더, 커스텀 필드, Presigned URL, 호출 로그 도메인이 모두 사용 가능합니다. ## 트러블슈팅 `PLUUUG_SECRET_KEY` 값이 잘못되었거나 누락된 경우입니다. HMAC 서명을 만들 수 없어 백엔드가 거부합니다. **해결:** 발급받은 Secret Key가 맞는지 확인하고, 위 설치 명령을 다시 실행해 키를 갱신하세요. 기존 설정은 자동 백업됩니다. `PLUUUG_API_KEY` 값이 잘못되었거나 누락된 경우입니다. **해결:** 관리자에서 발급받은 API Key가 맞는지 확인하고, 위 설치 명령을 다시 실행해 키를 갱신하세요. 플랜 제약입니다. 일부 도메인은 특정 플랜에서만 사용 가능합니다: * **project / worker:** FREE 또는 AGENCY 플랜 전용 * **member:** FREE / TEAM / AGENCY 플랜 전용 플랜 업그레이드 또는 사용 가능한 다른 도구를 사용하세요. Secret Key는 정책상 발급 시 1회만 표시됩니다. 잃어버린 경우 관리자에서 **새 API Key를 재발급**해야 합니다. 재발급 후 위 설치 명령을 다시 실행해 키를 갱신하세요(기존 설정 자동 백업). 분당 호출 한도(1,000회)를 초과했습니다. 호출 빈도를 조정하거나 잠시 대기 후 다시 시도하세요. Claude Desktop이 wrapper 응답을 거부하는 케이스입니다. wrapper(`pluuug-openapi-mcp`)가 최신이면 보통 자동 우회됩니다. **해결:** 위 설치 명령을 다시 실행하면 wrapper 최신 버전을 받아옵니다. 문제 지속 시 [GitHub Issue](https://github.com/postoo-io/pluuug-openapi-mcp/issues)에 환경 정보(macOS 버전 / Claude Desktop 버전 / 명령)를 포함해 등록해 주세요. 스크립트가 도중에 멈춘 경우 출력된 에러 메시지를 확인하세요. 자주 발생하는 케이스: * `Claude Desktop이 설치돼 있지 않습니다` → [https://claude.ai/download](https://claude.ai/download)에서 먼저 설치 * `python3가 PATH에 없습니다` → `xcode-select --install`로 Command Line Tools 설치 * `uv 설치 후 PATH에서 찾을 수 없습니다` → 새 터미널을 열고 다시 시도 그래도 해결되지 않으면 출력 전문을 [Issue](https://github.com/postoo-io/pluuug-openapi-mcp/issues)에 첨부해 주세요. ## FAQ * **MCP wrapper (실행 코드):** [github.com/postoo-io/pluuug-openapi-mcp](https://github.com/postoo-io/pluuug-openapi-mcp) (MIT) * **설치 스크립트:** [scripts/install.sh](https://github.com/postoo-io/pluuug-openapi-mcp/blob/main/scripts/install.sh) wrapper는 내부적으로 `awslabs/openapi-mcp-server`를 사용하고, 플러그 백엔드 호출 시 HMAC-SHA256 서명을 자동으로 추가합니다. 네. MCP 표준 stdio 프로토콜을 따르므로 MCP를 지원하는 모든 클라이언트에서 사용 가능합니다. 단, 본 install.sh는 Claude Desktop 설정 파일을 기준으로 작성됐습니다. 다른 클라이언트는 [wrapper README](https://github.com/postoo-io/pluuug-openapi-mcp#readme)를 참고해 직접 등록하세요. 아니요. wrapper가 매 요청마다 자동으로 X-Signature를 계산해 헤더에 추가합니다. 키 두 개를 설정에 넣어두면 끝입니다. 1. 관리자에서 새 API Key 발급 2. 위 설치 명령을 다시 실행 (`curl -fsSL ... | bash`) 3. 기존 설정은 자동 백업되고 새 키로 덮어쓰기됩니다 4. Claude Desktop 완전 종료 후 재시작 구 키는 더 이상 사용 불가합니다. 플러그 API 호출 정책에 따릅니다. 상세는 별도 안내 페이지 또는 영업 담당자에 문의하세요. ## 관련 자원 * **MCP wrapper:** [github.com/postoo-io/pluuug-openapi-mcp](https://github.com/postoo-io/pluuug-openapi-mcp) * **설치 스크립트 소스:** [scripts/install.sh](https://github.com/postoo-io/pluuug-openapi-mcp/blob/main/scripts/install.sh) * **API Reference:** [/api-reference](/api-reference) (전체 endpoint 목록) * **인증 상세 (수동 구현 시):** [/authentication](/authentication) * **MCP 표준:** [https://modelcontextprotocol.io](https://modelcontextprotocol.io) # 플러그 개발자센터 Source: https://docs.openapi.pluuug.com/introduction 플러그 개발자 문서에 오신 것을 환영합니다. ## 오픈 API 시작하기 플러그에서 제공되는 다양한 오픈 API를 활용하여 서비스를 연동할 수 있어요. 플러그는 **Agency 플랜 이용 고객 한정**으로 API Key를 발급해드리고 있어요. 1. 플러그 Agency 플랜 구독을 시작해 주세요. 2. 비즈니스 설정 > 웹훅 & API 메뉴를 클릭하세요. 3. 웹훅 생성: \[웹훅] 탭에서 \[생성하기] 버튼을 클릭하세요. 4. API Key 발급: \[오픈 API] 탭에서 \[API Key 발급하기] 버튼을 클릭하세요. 5. Agency 플랜 중단 혹은 다운그레이드 시, 웹훅 및 오픈 API 이용이 제한돼요. 아래의 Base URL을 복사하여 사용해 주세요. ``` https://openapi.pluuug.com ``` 비즈니스(워크스페이스) 별로 API 호출 제한 횟수가 적용돼요. * 모든 endpoint를 기준으로 호출 횟수 제한이 적용돼요. * 최대 분당 1,000회 요청을 제공해요. * 요청이 초과되었을 경우, 아래 메세지를 리턴해요. ```django theme={null} // HTTP Status Code 429 { "code": 429, "message": "요청이 지연(throttled)되었습니다. Expected available in 60 seconds." } ``` # 🔄 웹훅 Source: https://docs.openapi.pluuug.com/webhook 플러그 API는 특정 이벤트가 발생할 때 자동으로 HTTP POST 요청을 보내는 웹훅을 지원합니다. ## 웹훅 설정 웹훅을 사용하려면 다음 단계를 따르세요 1. 웹훅 URL을 플러그 대시보드(비즈니스 설정 -> 웹훅 & API)에서 설정합니다 2. 수신할 이벤트 유형을 선택합니다 ## 지원 이벤트 플러그 API에서 지원하는 웹훅 이벤트 ### 의뢰 이벤트 * 제목 변경 * 단계 변경 * 예상 견적 변경 * 문의 일시 변경 * 연결 고객 변경 ### 견적서 이벤트 * 제목 변경 * 견적일자 변경 * 견적번호 변경 * 담당자 정보 변경 * 수신자 정보 변경 * 견적서 상태 변경 * 통화 변경 * VAT 옵션 변경 각 이벤트는 사용자가 웹훅 설정에서 개별적으로 선택할 수 있습니다. 필요한 이벤트만 선택하여 불필요한 알림을 줄일 수 있습니다. ## 웹훅 페이로드 구조 모든 웹훅은 다음과 같은 기본 구조를 가집니다: ```json theme={null} { "event_type": "inquiry", "timestamp": "2024-01-15T10:30:45.123456", "changed_fields": ["name", "status"], "data": { // 이벤트 관련 데이터 } } ``` ### 필드 설명 | 필드 | 타입 | 설명 | | ---------------- | ------ | ------------------------------------ | | `event_type` | string | 발생한 이벤트 유형 ("inquiry" 또는 "estimate") | | `timestamp` | string | 이벤트 발생 시간 (ISO 8601 형식) | | `changed_fields` | array | 변경된 필드 목록 | | `data` | object | 이벤트와 관련된 실제 데이터 | ## 이벤트별 페이로드 예시 ### 의뢰 변경 이벤트 ```json theme={null} { "event_type": "inquiry", "timestamp": "2024-01-15T10:30:45.123456", "changed_fields": ["name", "status", "inquiry_date", "estimate", "client"], "data": { "id": 1234, "name": "모바일 앱 개발 프로젝트 의뢰", "status": { "id": 2, "title": "검토 중" }, "estimate": "15000000", "inquiry_date": "2024-01-15T09:00:00", "client": { "id": 567, "company_name": "(주)테크스타트업", "ceo_name": "김대표", "email": "ceo@techstartup.co.kr", "contact": "010-1234-5678", "in_charge": "박매니저" } } } ``` ### 견적서 변경 이벤트 ```json theme={null} { "data": { "id": 886, "note": "프로젝트 관련 메모", "title": "모바일 앱 개발 견적서", "status": "확정", "has_vat": true, "vat_type": "부가세 별도", "total_vat": 0.0, "currency_code": "KRW", "discount_rate": 0, "estimate_date": "2024-01-16", "unique_number": "202401-001", "discount_amount": 0.0, "final_total_amount": 0.0, "total_supply_amount": 0.0, "total_category_amount": 0.0, "total_discount_amount": 0.0, "inquiry": { "id": 32030, "name": "모바일 앱 개발 프로젝트 의뢰" }, "language": "KOR", "receiver": { "id": 853, "email": "customer@company.com", "contact": "010-1234-5678", "ceo_name": "김대표", "company_name": "(주)테크스타트업", "company_address": "서울특별시 강남구 테헤란로 123", "business_registration_number": "123-45-67890" }, "supplier": { "id": 853, "email": "supplier@pluuug.com", "ceo_name": "박플러그", "company_name": "플러그개발", "company_address": "서울특별시 서초구 플러그로 456", "business_registration_number": "987-65-43210" }, "in_charge": { "id": 164, "name": "이담당", "email": "manager@pluuug.com", "phone": "0507-1234-5678" }, "category_set": [ { "id": 2546, "type": "품목", "title": "개발비", "item_set": [ { "id": 3706, "unit": "일", "title": "UI/UX 디자인", "quantity": 0.0, "unit_cost": 0.0, "total_cost": 0.0, "description": "모바일 앱 UI/UX 디자인", "number_of_people": 1 } ], "information_type": null, "item_display_name": "항목", "total_item_amount": 0.0, "unit_display_name": "단위", "display_item_image": false, "information_content": null, "quantity_display_name": "수량", "unit_cost_display_name": "단가", "total_cost_display_name": "금액", "description_display_name": "설명", "number_of_people_display_name": "인원" } ] }, "timestamp": "2024-01-15T14:22:15.789012", "event_type": "estimate", "changed_fields": ["title", "status", "unique_number", "estimate_date", "currency_code", "vat_type", "in_charge", "receiver"] } ``` ## 인증 웹훅 요청의 보안을 위해 Authorization 헤더에 토큰을 포함하여 전송합니다. ### 인증 방법 웹훅 요청은 다음과 같은 Authorization 헤더를 포함합니다: ``` Authorization: Bearer your-webhook-token ``` 웹훅 엔드포인트에서는 이 토큰을 검증하여 요청의 유효성을 확인해야 합니다.