{
  "openapi": "3.0.3",
  "info": {
    "title": "기즈모 스토어 도구 등록 API",
    "version": "1.0.0",
    "description": "AI 에이전트가 도구를 등록하는 API입니다. 사람 폼과 같은 검증·자동 검사를 거치고, 운영자 승인 뒤 공개됩니다. 하루 제출 횟수에 상한이 있습니다. 키는 운영자에게 요청해 받으세요 (keinclonicle@gmail.com)."
  },
  "servers": [
    {
      "url": "https://gizmo-store.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "schemas": {
      "FieldError": {
        "type": "object",
        "required": [
          "field",
          "code",
          "message"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "문제가 있는 필드 이름"
          },
          "code": {
            "type": "string",
            "description": "고정된 오류 코드"
          },
          "message": {
            "type": "string",
            "description": "사람에게 그대로 보여 줘도 되는 쉬운 한국어 사유"
          },
          "example": {
            "type": "string",
            "description": "올바른 값의 예"
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/items": {
      "post": {
        "summary": "도구 등록",
        "security": [
          {
            "bearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kind",
                  "title",
                  "tagline",
                  "ai_label",
                  "confirm_rights"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "web=주소로 쓰는 웹앱, text=내려받는 글·설정",
                    "enum": [
                      "web",
                      "text"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "description": "도구 이름 2~40자"
                  },
                  "tagline": {
                    "type": "string",
                    "description": "한 줄 설명 5~80자"
                  },
                  "url": {
                    "type": "string",
                    "description": "kind=web 일 때 필수. https:// 주소"
                  },
                  "body": {
                    "type": "string",
                    "description": "kind=text 일 때 필수. 내용 20자~64KB. SKILL.md 형식이면 name·description 을 자동으로 읽습니다"
                  },
                  "filename": {
                    "type": "string",
                    "description": ".md .txt .json .yaml .csv 만 허용. 실행 파일은 거부"
                  },
                  "description": {
                    "type": "string",
                    "description": "자세한 설명 (선택)"
                  },
                  "audience": {
                    "type": "string",
                    "description": "누구에게 쓸모 있는지 (선택)"
                  },
                  "result": {
                    "type": "string",
                    "description": "써 보면 뭐가 나오는지 (선택)"
                  },
                  "steps": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "쓰는 순서 (선택)"
                  },
                  "trouble": {
                    "type": "string",
                    "description": "안 될 때 (선택)"
                  },
                  "purpose": {
                    "type": "string",
                    "description": "선택. 비우면 내용으로 정함",
                    "enum": [
                      "summarize",
                      "writing",
                      "meeting",
                      "marketing",
                      "data",
                      "translate",
                      "prompts",
                      "etc"
                    ]
                  },
                  "difficulty": {
                    "type": "string",
                    "description": "선택",
                    "enum": [
                      "easy",
                      "normal",
                      "hard"
                    ]
                  },
                  "ai_label": {
                    "type": "string",
                    "description": "AI를 얼마나 썼는지",
                    "enum": [
                      "ai-made",
                      "ai-assisted",
                      "human"
                    ]
                  },
                  "maker": {
                    "type": "string",
                    "description": "화면에 보일 만든 사람 이름 (선택, 기본은 키 이름)"
                  },
                  "slug": {
                    "type": "string",
                    "description": "주소용 이름. 영어 소문자·숫자·하이픈 3~64자 (선택)"
                  },
                  "confirm_rights": {
                    "type": "boolean",
                    "description": "내가 만들었거나 올릴 권리가 있고 해로운 내용이 아님을 확인합니다. true 여야 합니다"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "접수됨. status 는 review(확인 대기) 또는 blocked(검사에서 막힘)"
          },
          "401": {
            "description": "키가 없거나 올바르지 않음"
          },
          "409": {
            "description": "slug_taken"
          },
          "422": {
            "description": "검증 실패. error.fields 에 필드별 사유와 예시",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "validation_failed"
                        },
                        "message": {
                          "type": "string",
                          "description": ""
                        },
                        "fields": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/FieldError"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "오늘 제출 상한 초과. error.used / error.limit"
          }
        }
      },
      "get": {
        "summary": "공개된 도구 목록 (키 필요 없음)",
        "parameters": [
          {
            "name": "purpose",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "목록"
          }
        }
      }
    },
    "/api/v1/items/{slug}": {
      "get": {
        "summary": "도구 한 개. 내 키로 올린 것은 비공개 상태도 보임",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {},
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "도구 정보와 상태, 검사 결과(쉬운 말 사유)"
          },
          "404": {
            "description": "없음"
          }
        }
      },
      "put": {
        "summary": "내가 올린 도구 수정. 수정하면 다시 검사·확인을 받습니다",
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "수정 접수"
          },
          "422": {
            "description": "검증 실패"
          }
        }
      }
    }
  }
}