{
  "openapi": "3.0.3",
  "info": {
    "title": "insjiexi · Instagram Media Parser API",
    "version": "1.0.0",
    "description": "Instagram 媒体解析接口。支持 Post / Reel / Reels / IGTV / 轮播多图。返回直链可用于图片预览、视频播放、下载。\n\n**主要能力**:\n- 输入任意 IG 链接，返回作者、标题、点赞/评论/播放数、媒体直链（含多分辨率、缩略图、时长）。\n- 内置代理下载接口，规避 IG CDN 的 Referer / CORS 限制。\n- 多账号 sessionid cookie 轮询，单账号被风控时自动切换。\n\n**部署**: 香港机房直连 Instagram，无需翻墙。",
    "contact": {
      "name": "insjiexi",
      "url": "https://ins.baziapi.site"
    },
    "license": { "name": "MIT" }
  },
  "servers": [
    { "url": "https://ins.baziapi.site", "description": "生产环境" }
  ],
  "tags": [
    { "name": "Parse", "description": "解析 Instagram 链接，提取媒体直链" },
    { "name": "Download", "description": "服务器代理下载远端媒体（绕开 Referer / CORS 限制）" },
    { "name": "Health", "description": "健康检查" },
    { "name": "Admin", "description": "Cookie 池管理（需要 ADMIN_TOKEN）" }
  ],
  "paths": {
    "/healthz": {
      "get": {
        "tags": ["Health"],
        "summary": "健康检查",
        "description": "返回当前服务存活状态。",
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": { "type": "boolean", "example": true },
                    "ts": { "type": "integer", "format": "int64", "example": 1778760565023 }
                  }
                }
              }
            }
          }
        }
      }
    },

    "/ins/parse": {
      "get": {
        "tags": ["Parse"],
        "summary": "解析 IG 链接（GET）",
        "description": "传入任意 Instagram 链接（Post / Reel / Reels / IGTV），返回标准化的媒体信息。\n\n支持的 URL 格式:\n- `https://www.instagram.com/p/{shortcode}/`\n- `https://www.instagram.com/reel/{shortcode}/`\n- `https://www.instagram.com/reels/{shortcode}/`\n- `https://www.instagram.com/tv/{shortcode}/`",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "description": "Instagram 完整链接。`url` 和 `url_b64` 二选一。",
            "required": false,
            "schema": { "type": "string" },
            "example": "https://www.instagram.com/reels/DXkcccJud-w/"
          },
          {
            "name": "url_b64",
            "in": "query",
            "description": "Instagram 链接的 base64 编码版（用于规避中间链路对 `instagram.com` 关键字的嗅探。HTTPS 接入后通常不需要）。",
            "required": false,
            "schema": { "type": "string" },
            "example": "aHR0cHM6Ly93d3cuaW5zdGFncmFtLmNvbS9yZWVscy9EWGtjY2NKdWQtdy8="
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ParseResponse" },
                "examples": {
                  "video": { "$ref": "#/components/examples/VideoExample" }
                }
              }
            }
          },
          "400": {
            "description": "参数错误",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "500": {
            "description": "解析失败（所有策略都失败时返回，含每个策略的失败原因）",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Parse"],
        "summary": "解析 IG 链接（POST）",
        "description": "等价于 GET /ins/parse，但参数通过 JSON body 提交。",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": { "type": "string", "example": "https://www.instagram.com/reels/DXkcccJud-w/" },
                  "url_b64": { "type": "string", "description": "可选，url 的 base64 版本" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ParseResponse" } }
            }
          },
          "400": { "description": "参数错误", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } },
          "500": { "description": "解析失败", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },

    "/ins/download": {
      "get": {
        "tags": ["Download"],
        "summary": "代理下载远端媒体",
        "description": "把 IG CDN 上的视频 / 图片 / 头像通过本服务流式转发回客户端。\n\n用途:\n- 前端 `<img>` `<video>` 引用 IG CDN 资源时常被 Referer 校验拒绝，走此代理可规避。\n- 配合 `Content-Disposition: attachment` 让浏览器弹出下载窗。",
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "description": "媒体直链（一般来自 `/ins/parse` 返回的 `data.media[].url` / `data.author.avatar`）",
            "required": true,
            "schema": { "type": "string" },
            "example": "https://scontent-hkg1-2.cdninstagram.com/.../video.mp4"
          },
          {
            "name": "filename",
            "in": "query",
            "description": "下载时的文件名（不含扩展名，服务器根据 Content-Type 自动加 .mp4 / .jpg / .png / .webp）",
            "required": false,
            "schema": { "type": "string" },
            "example": "haleyybaylee-DXkcccJud-w"
          }
        ],
        "responses": {
          "200": {
            "description": "流式返回媒体二进制内容",
            "content": {
              "video/mp4": { "schema": { "type": "string", "format": "binary" } },
              "image/jpeg": { "schema": { "type": "string", "format": "binary" } },
              "image/png":  { "schema": { "type": "string", "format": "binary" } },
              "image/webp": { "schema": { "type": "string", "format": "binary" } }
            }
          },
          "400": { "description": "url 缺失或非法" },
          "500": { "description": "远端拉取失败" }
        }
      }
    },

    "/ins/admin/cookies": {
      "get": {
        "tags": ["Admin"],
        "summary": "列出当前 cookie 池（脱敏）",
        "security": [{ "bearerAuth": [] }],
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": { "type": "integer", "example": 0 },
                    "msg": { "type": "string", "example": "ok" },
                    "count": { "type": "integer", "example": 2 },
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/CookieInfo" }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "未授权（Bearer token 不正确）" },
          "503": { "description": "服务端未配置 ADMIN_TOKEN" }
        }
      },
      "post": {
        "tags": ["Admin"],
        "summary": "全量替换 cookie 池",
        "description": "用提交的 cookies 数组覆盖当前所有 cookie。立即热生效并写回服务器 `.env`。",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["cookies"],
                "properties": {
                  "cookies": {
                    "type": "array",
                    "items": { "type": "string" },
                    "example": ["csrftoken=xxx; ds_user_id=123; sessionid=123%3Axxx%3A7%3AAYxx"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "已替换", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CookieListResponse" } } } },
          "400": { "description": "参数错误" },
          "401": { "description": "未授权" }
        }
      }
    },

    "/ins/admin/cookies/append": {
      "post": {
        "tags": ["Admin"],
        "summary": "追加一个 cookie",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["cookie"],
                "properties": {
                  "cookie": {
                    "type": "string",
                    "example": "csrftoken=xxx; ds_user_id=123; sessionid=123%3Axxx%3A7%3AAYxx"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "ok (重复时不报错，msg 会显示 duplicate_or_empty)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CookieListResponse" } } } },
          "401": { "description": "未授权" }
        }
      }
    },

    "/ins/admin/cookies/{idx}": {
      "delete": {
        "tags": ["Admin"],
        "summary": "删除指定位置的 cookie",
        "security": [{ "bearerAuth": [] }],
        "parameters": [
          {
            "name": "idx",
            "in": "path",
            "required": true,
            "description": "目标 cookie 在池中的索引（0 起，可从 GET /ins/admin/cookies 的 data[].index 取）",
            "schema": { "type": "integer", "minimum": 0 },
            "example": 1
          }
        ],
        "responses": {
          "200": { "description": "ok / not_found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CookieListResponse" } } } },
          "401": { "description": "未授权" }
        }
      }
    },

    "/ins/admin/cookies/test": {
      "post": {
        "tags": ["Admin"],
        "summary": "测试 cookie 池中每个 cookie 是否仍然有效",
        "description": "对池中每个 cookie 单独发起一次 IG Web API 解析请求，返回每条的成功/失败状态、耗时、作者用户名等。\n\n常用于发现失效 cookie 并定向删除。",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "测试用的 IG 链接，默认 https://www.instagram.com/reel/DXkcccJud-w/",
                    "example": "https://www.instagram.com/reel/DXkcccJud-w/"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": { "type": "integer", "example": 0 },
                    "msg": { "type": "string", "example": "ok" },
                    "testedUrl": { "type": "string" },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "index": { "type": "integer" },
                          "ok": { "type": "boolean" },
                          "ms": { "type": "integer", "description": "耗时毫秒" },
                          "source": { "type": "string", "nullable": true },
                          "mediaType": { "type": "string", "nullable": true },
                          "author": { "type": "string", "nullable": true },
                          "error": { "type": "string", "nullable": true }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "未授权" }
        }
      }
    }
  },

  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "管理员 token，从服务器 .env 的 ADMIN_TOKEN 读取。请求头: `Authorization: Bearer <ADMIN_TOKEN>`"
      }
    },
    "schemas": {
      "ParseResponse": {
        "type": "object",
        "properties": {
          "code": { "type": "integer", "example": 0, "description": "0 表示成功，其它为错误" },
          "msg": { "type": "string", "example": "ok" },
          "data": { "$ref": "#/components/schemas/ParseData" }
        }
      },
      "ParseData": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": ["web_api_v1", "graphql", "embed"],
            "description": "实际命中的解析策略"
          },
          "shortcode": { "type": "string", "example": "DXkcccJud-w" },
          "mediaId": { "type": "string", "example": "3883353878375817136", "description": "IG 内部 64 位数字 ID" },
          "type": {
            "type": "string",
            "enum": ["image", "video", "carousel"],
            "description": "顶层媒体类型"
          },
          "kind": {
            "type": "string",
            "enum": ["post", "reel", "tv", "unknown"],
            "description": "从 URL 路径推断出的内容类型"
          },
          "caption": { "type": "string", "description": "作者发文文案" },
          "takenAt": { "type": "integer", "format": "int64", "description": "拍摄/发布 Unix 时间戳（秒）" },
          "likeCount": { "type": "integer", "nullable": true },
          "commentCount": { "type": "integer", "nullable": true },
          "playCount": { "type": "integer", "nullable": true, "description": "视频播放次数（仅 video）" },
          "author": { "$ref": "#/components/schemas/Author" },
          "media": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/MediaItem" }
          },
          "_cookieIndex": { "type": "integer", "description": "本次解析命中的 cookie 在池中的索引（调试用）" }
        }
      },
      "Author": {
        "type": "object",
        "nullable": true,
        "properties": {
          "id": { "type": "string", "example": "197441822" },
          "username": { "type": "string", "example": "haleyybaylee" },
          "fullName": { "type": "string" },
          "avatar": { "type": "string", "description": "头像 CDN 直链" },
          "isVerified": { "type": "boolean" }
        }
      },
      "MediaItem": {
        "type": "object",
        "properties": {
          "type": { "type": "string", "enum": ["image", "video"] },
          "url": { "type": "string", "description": "媒体直链（IG CDN）" },
          "thumbnail": { "type": "string", "nullable": true, "description": "封面图直链（image 时与 url 相同）" },
          "width": { "type": "integer", "nullable": true },
          "height": { "type": "integer", "nullable": true },
          "duration": { "type": "number", "nullable": true, "description": "视频时长秒，仅 video 有" }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "code": { "type": "integer", "example": 500 },
          "msg": { "type": "string", "example": "all_strategies_failed" },
          "data": { "type": "object", "nullable": true, "example": null },
          "errors": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": {
                "stage": { "type": "string", "example": "web_api_v1" },
                "message": { "type": "string", "example": "webapi_v1_cookie#0_failed: challenge_required" }
              }
            }
          }
        }
      },
      "CookieInfo": {
        "type": "object",
        "properties": {
          "index": { "type": "integer", "example": 0 },
          "dsUserId": { "type": "string", "nullable": true, "example": "25577116124" },
          "sessionidMasked": { "type": "string", "nullable": true, "example": "2557711612...m0lA" },
          "hasCsrf": { "type": "boolean", "example": true },
          "length": { "type": "integer", "example": 265 }
        }
      },
      "CookieListResponse": {
        "type": "object",
        "properties": {
          "code": { "type": "integer", "example": 0 },
          "msg": { "type": "string", "example": "replaced" },
          "count": { "type": "integer", "example": 2 },
          "data": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CookieInfo" }
          }
        }
      }
    },
    "examples": {
      "VideoExample": {
        "summary": "Reel 视频解析示例",
        "value": {
          "code": 0,
          "msg": "ok",
          "data": {
            "source": "web_api_v1",
            "shortcode": "DXkcccJud-w",
            "mediaId": "3883353878375817136",
            "type": "video",
            "kind": "reel",
            "caption": "the way I actually started using @headandshoulders ...",
            "takenAt": 1777152328,
            "likeCount": 1452474,
            "commentCount": 7817,
            "playCount": 18728596,
            "author": {
              "id": "197441822",
              "username": "haleyybaylee",
              "fullName": "H A L E Y   B A Y L E E",
              "avatar": "https://scontent-hkg4-2.cdninstagram.com/.../avatar.jpg",
              "isVerified": true
            },
            "media": [
              {
                "type": "video",
                "url": "https://scontent-hkg1-2.cdninstagram.com/.../AQNV...mp4",
                "thumbnail": "https://scontent-hkg4-2.cdninstagram.com/.../cover.jpg",
                "width": 720,
                "height": 1280,
                "duration": 32.48
              }
            ]
          }
        }
      }
    }
  }
}
