{
  "openapi": "3.0.3",
  "info": {
    "title": "teacher.place 公開課程 API",
    "version": "1.0.0",
    "description": "公開課程唯讀 API。支援跨網站 GET；登入、註冊、購課與正式教材透過課程回應中的 links 開啟原教學網站。"
  },
  "servers": [
    {
      "url": "https://{schoolHost}/api/v1",
      "variables": {
        "schoolHost": {
          "default": "your-school.example",
          "description": "後台 API 串接頁所顯示的教學站台 hostname"
        }
      }
    }
  ],
  "security": [],
  "paths": {
    "/courses/{courseId}": {
      "get": {
        "operationId": "getCourse",
        "summary": "取得已上架課程",
        "description": "取得已上架課程",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "courseId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,128}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Course"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "data": {
                    "id": "COURSE_ID",
                    "name": "水彩入門",
                    "description": "從基礎筆法開始學習水彩。",
                    "introductionHtml": "<p>課程介紹</p>",
                    "coverUrl": "https://images.example/course.jpg",
                    "hero": {
                      "type": "image",
                      "imageUrls": [],
                      "videoUrl": ""
                    },
                    "price": 1200,
                    "currency": "TWD",
                    "paymentType": "one_time",
                    "learningPoints": [
                      "掌握基礎筆法"
                    ],
                    "includedItems": [
                      "線上教材"
                    ],
                    "links": {
                      "course": "https://school.example.com/courses/watercolor",
                      "login": "https://school.example.com/courses/watercolor?auth=login",
                      "register": "https://school.example.com/courses/watercolor?auth=register",
                      "checkout": "https://school.example.com/checkout?courseId=COURSE_ID",
                      "learning": "https://school.example.com/course/watercolor/"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗回應。依 HTTP status 與 error.code 處理，勿直接重送。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/courses/{courseId}/page-data": {
      "get": {
        "operationId": "getCoursePageData",
        "summary": "取得一頁式課程資料",
        "description": "一次取得站台、課程、章節與操作連結。此格式與平台 Liquid 銷售頁共用，適合自訂到達頁。",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "courseId",
            "required": true,
            "schema": { "type": "string", "pattern": "^[A-Za-z0-9_-]{1,128}$" }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "data": { "$ref": "#/components/schemas/CoursePageData" } },
                  "required": ["data"]
                },
                "example": {
                  "data": {
                    "schemaVersion": "course-page.v1",
                    "site": { "id": "site_demo", "name": "示範教學網站", "logoUrl": "" },
                    "course": { "id": "COURSE_ID", "name": "水彩入門", "price": 1200, "priceText": "NT$ 1,200", "isFree": false, "chapterCount": 1, "unitCount": 2 },
                    "chapters": [{ "id": "CHAPTER_ID", "index": 1, "name": "第一章", "units": [{ "id": "UNIT_ID", "index": 1, "name": "工具介紹", "preview": true }] }],
                    "links": { "course": "https://school.example.com/courses/watercolor", "login": "https://school.example.com/courses/watercolor?auth=login", "register": "https://school.example.com/courses/watercolor?auth=register", "checkout": "https://school.example.com/checkout?courseId=COURSE_ID", "learning": "https://school.example.com/course/watercolor/" }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗回應。依 HTTP status 與 error.code 處理，勿直接重送。",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/courses/{courseId}/chapters": {
      "get": {
        "operationId": "getChapters",
        "summary": "取得已發布章節與單元",
        "description": "按後台順序回傳；preview=true 的單元可直接試閱。此接口不回傳付費影片來源。",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "courseId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,128}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Chapter"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "id": "CHAPTER_ID",
                      "name": "第一章・認識水彩",
                      "units": [
                        {
                          "id": "UNIT_ID",
                          "name": "工具介紹",
                          "preview": true
                        },
                        {
                          "id": "PAID_UNIT_ID",
                          "name": "進階技法",
                          "preview": false
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "description": "失敗回應。依 HTTP status 與 error.code 處理，勿直接重送。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/courses/{courseId}/units/{chapterId}/{unitId}": {
      "get": {
        "operationId": "getMaterial",
        "summary": "取得公開試閱教材",
        "description": "僅限已發布且 preview=true 的單元。非試閱單元回 403，不接受學生 Token 解鎖。Mux 簽章約一小時，過期需重新取得。",
        "security": [],
        "parameters": [
          {
            "in": "path",
            "name": "courseId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,128}$"
            }
          },
          {
            "in": "path",
            "name": "chapterId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,128}$"
            }
          },
          {
            "in": "path",
            "name": "unitId",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,128}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Material"
                    }
                  },
                  "required": [
                    "data"
                  ]
                },
                "example": {
                  "data": {
                    "id": "UNIT_ID",
                    "chapterId": "CHAPTER_ID",
                    "name": "工具介紹",
                    "contentHtml": "<p>今天一起認識水彩工具。</p>",
                    "video": {
                      "provider": "url",
                      "url": "https://video.example/lesson.mp4"
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "失敗回應。依 HTTP status 與 error.code 處理，勿直接重送。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Course": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "課程永久 ID。"
          },
          "name": {
            "type": "string",
            "description": "課程名稱。"
          },
          "description": {
            "type": "string",
            "description": "課程摘要。"
          },
          "introductionHtml": {
            "type": "string",
            "description": "課程介紹 HTML，呈現前請清理內容。"
          },
          "coverUrl": {
            "type": "string",
            "description": "課程封面網址。"
          },
          "hero": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "image",
                  "video"
                ]
              },
              "imageUrls": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "videoUrl": {
                "type": "string"
              }
            },
            "required": [
              "type",
              "imageUrls",
              "videoUrl"
            ],
            "description": "主視覺類型、圖片與介紹影片網址。"
          },
          "price": {
            "type": "integer",
            "minimum": 0,
            "description": "TWD 整數售價，0 表示免費。"
          },
          "currency": {
            "type": "string",
            "enum": [
              "TWD"
            ],
            "description": "幣別，固定為 TWD。"
          },
          "paymentType": {
            "type": "string",
            "enum": [
              "one_time",
              "subscription"
            ],
            "description": "one_time 為單次付費；subscription 為訂閱。"
          },
          "learningPoints": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "課程學習重點。"
          },
          "includedItems": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "課程包含項目。"
          },
          "links": {
            "type": "object",
            "description": "原站台的頁面連結，供使用者點擊開啟。訂閱型課程的 checkout 指向原課程方案頁。",
            "properties": {
              "course": {
                "type": "string",
                "format": "uri"
              },
              "login": {
                "type": "string",
                "format": "uri"
              },
              "register": {
                "type": "string",
                "format": "uri"
              },
              "checkout": {
                "type": "string",
                "format": "uri"
              },
              "learning": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "course",
              "login",
              "register",
              "checkout",
              "learning"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "introductionHtml",
          "coverUrl",
          "hero",
          "price",
          "currency",
          "paymentType",
          "learningPoints",
          "includedItems",
          "links"
        ]
      },
      "CoursePageData": {
        "type": "object",
        "properties": {
          "schemaVersion": { "type": "string", "enum": ["course-page.v1"], "description": "資料格式版本。" },
          "site": { "type": "object", "description": "公開站台名稱與 Logo。" },
          "course": { "type": "object", "description": "課程內容，並補上 priceText、isFree、chapterCount、unitCount。" },
          "chapters": { "type": "array", "items": { "$ref": "#/components/schemas/Chapter" }, "description": "已發布章節與單元。" },
          "links": { "type": "object", "description": "課程、登入、註冊、結帳與開始上課連結。" }
        },
        "required": ["schemaVersion", "site", "course", "chapters", "links"]
      },
      "Chapter": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "units": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "preview": {
                  "type": "boolean"
                }
              },
              "required": [
                "id",
                "name",
                "preview"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "units"
        ]
      },
      "Material": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "chapterId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "contentHtml": {
            "type": "string"
          },
          "video": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "url"
                    ]
                  },
                  "url": {
                    "type": "string"
                  }
                },
                "required": [
                  "provider",
                  "url"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "vimeo"
                    ]
                  },
                  "videoId": {
                    "type": "string"
                  }
                },
                "required": [
                  "provider",
                  "videoId"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "mux"
                    ]
                  },
                  "playbackId": {
                    "type": "string"
                  },
                  "signed": {
                    "type": "boolean",
                    "enum": [
                      false
                    ]
                  }
                },
                "required": [
                  "provider",
                  "playbackId",
                  "signed"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "mux"
                    ]
                  },
                  "playbackId": {
                    "type": "string"
                  },
                  "signed": {
                    "type": "boolean",
                    "enum": [
                      true
                    ]
                  },
                  "tokens": {
                    "type": "object",
                    "properties": {
                      "playback": {
                        "type": "string"
                      },
                      "thumbnail": {
                        "type": "string"
                      },
                      "storyboard": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "playback",
                      "thumbnail",
                      "storyboard"
                    ]
                  },
                  "expiresAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "provider",
                  "playbackId",
                  "signed",
                  "tokens",
                  "expiresAt"
                ]
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          }
        },
        "required": [
          "id",
          "chapterId",
          "name",
          "contentHtml",
          "video"
        ]
      }
    }
  },
  "externalDocs": {
    "url": "https://teacher.place/api-docs",
    "description": "亦可在你的站台 /api-docs 或 /api/guide.md 閱讀"
  }
}
