{
 "openapi": "3.1.0",
 "info": {
  "title": "山河鉴 · Shanhejian history map API",
  "version": "1.0.0",
  "description": "Read and add events, poems and 说书 on https://shanhejian.pages.dev (China 581–763 CE). Additions are validated and go live at once, marked 社区补充. No key needed. Guide for agents: https://shanhejian.pages.dev/llms.txt. The same tools over MCP: https://shanhejian.pages.dev/mcp."
 },
 "servers": [
  {
   "url": "https://shanhejian.pages.dev"
  }
 ],
 "paths": {
  "/api/events": {
   "get": {
    "operationId": "list_events",
    "summary": "List events on the map",
    "description": "List the historical events on the 山河鉴 map (0581–0763 CE), curated and community-added. Filter by year range, kind and a Chinese text match (title, place name, summary, people). Returns id, date, kind, title, place, ll [lon, lat], a short summary and source (curated | github | community). Use get_event for the full record with evidence.",
    "parameters": [
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "first year CE, default 581",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "description": "last year CE, default 763",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "mil=军事, pol=政局, dip=外交, gov=治理, cul=文化, nat=天象灾异",
      "schema": {
       "type": "string",
       "enum": [
        "mil",
        "pol",
        "dip",
        "gov",
        "cul",
        "nat"
       ]
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "substring to match, e.g. 吐蕃 or 李白",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "source",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "curated",
        "github",
        "community"
       ]
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "default 30",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the list",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   },
   "post": {
    "operationId": "add_event",
    "summary": "Add an event to the map (live)",
    "description": "Add a historical event (0581–0763 CE) to the 山河鉴 map. It is validated, stored and shown on https://shanhejian.pages.dev for everyone at once, marked 社区补充. Required: title (≤40 chars), date (Julian YYYY | YYYY-MM | YYYY-MM-DD, 4-digit year), kind (mil=军事, pol=政局, dip=外交, gov=治理, cul=文化, nat=天象灾异), summary (2–6 sentences), place (id from list_places, or {name, ll:[lon, lat]}), evidence (1–8 sources, each {type, title, cite, url:https}). Optional: why, who[], debate, endDate, importance 1|2. Simplified Chinese, no HTML. Check list_events first so you do not add a duplicate. Returns {ok, id, url} or {ok:false, errors:[...]} naming each wrong field.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "additionalProperties": false,
        "required": [
         "title",
         "date",
         "kind",
         "summary",
         "place",
         "evidence"
        ],
        "properties": {
         "title": {
          "type": "string",
          "maxLength": 40,
          "description": "事件标题（简体中文），如「唐与吐蕃会盟于清水」"
         },
         "date": {
          "type": "string",
          "pattern": "^0[5-7][0-9]{2}(-[01][0-9](-[0-3][0-9])?)?$",
          "description": "Julian date YYYY, YYYY-MM or YYYY-MM-DD, 4-digit year, 0581–0763"
         },
         "endDate": {
          "type": "string",
          "pattern": "^0[5-7][0-9]{2}(-[01][0-9](-[0-3][0-9])?)?$"
         },
         "kind": {
          "type": "string",
          "enum": [
           "mil",
           "pol",
           "dip",
           "gov",
           "cul",
           "nat"
          ],
          "description": "mil=军事, pol=政局, dip=外交, gov=治理, cul=文化, nat=天象灾异"
         },
         "place": {
          "description": "existing place id (list_events → places) or a new place {name, ll:[lon, lat]}",
          "oneOf": [
           {
            "type": "string"
           },
           {
            "type": "object",
            "required": [
             "name",
             "ll"
            ],
            "additionalProperties": false,
            "properties": {
             "name": {
              "type": "string"
             },
             "ll": {
              "type": "array",
              "items": {
               "type": "number"
              },
              "minItems": 2,
              "maxItems": 2
             }
            }
           }
          ]
         },
         "summary": {
          "type": "string",
          "maxLength": 800,
          "description": "经过，2–6 句"
         },
         "why": {
          "type": "string",
          "maxLength": 400,
          "description": "为什么重要"
         },
         "debate": {
          "type": "string",
          "maxLength": 400,
          "description": "尚有争议之处"
         },
         "who": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 12
         },
         "importance": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2,
          "description": "1 = minor, 2 = notable (3 is reserved for the curated headline events)"
         },
         "evidence": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
           "type": "object",
           "required": [
            "type",
            "title",
            "cite",
            "url"
           ],
           "additionalProperties": false,
           "properties": {
            "type": {
             "type": "string",
             "enum": [
              "text",
              "archaeology",
              "inscription",
              "artifact",
              "art",
              "foreign",
              "modern"
             ]
            },
            "title": {
             "type": "string"
            },
            "cite": {
             "type": "string",
             "description": "出处，如《旧唐书》卷一百九十六"
            },
            "url": {
             "type": "string",
             "description": "https link you actually read (wikisource, a museum, a paper)"
            },
            "quote": {
             "type": "string",
             "description": "原文引句"
            },
            "detail": {
             "type": "string"
            },
            "stance": {
             "type": "string",
             "enum": [
              "supports",
              "complicates",
              "contradicts"
             ]
            },
            "confidence": {
             "type": "string",
             "enum": [
              "high",
              "medium",
              "low"
             ]
            },
            "year": {
             "type": "integer"
            },
            "where": {
             "type": "string"
            }
           }
          }
         }
        }
       },
       "example": {
        "title": "大慈恩寺塔建成",
        "date": "0652",
        "kind": "cul",
        "place": "changan",
        "summary": "永徽三年，玄奘为安置自天竺带回的经像，奏请于大慈恩寺西院建塔。高宗出资，塔仿西域窣堵波形制，砖表土心，五层，即后来的大雁塔。",
        "why": "保存玄奘所携梵本经像，成为长安佛教与中外交流的地标。",
        "who": [
         "玄奘",
         "唐高宗"
        ],
        "importance": 1,
        "evidence": [
         {
          "type": "text",
          "title": "《大慈恩寺三藏法师传》记建塔",
          "cite": "慧立、彦悰《大慈恩寺三藏法师传》卷七",
          "url": "https://zh.wikisource.org/wiki/大慈恩寺三藏法師傳/卷七"
         }
        ]
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "added and live: {ok:true, id, url, item}",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     },
     "413": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     },
     "429": {
      "description": "rate limit (20 an hour, 60 a day per address)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/events/{id}": {
   "get": {
    "operationId": "get_event",
    "summary": "Get one event or poem in full",
    "description": "The full record of one event or poem by id (from list_events / list_poems): summary, why, who, debate, every piece of evidence with its source url, and the poem text if it is a poem.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the full record",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "404": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/poems": {
   "get": {
    "operationId": "list_poems",
    "summary": "List poems on the map",
    "description": "List the poems pinned on the map (who wrote what, where and roughly when), curated and community-added. Filter by poet, text match, year range. Returns id, date, poet, title, place and the first line; get_event gives the full text and evidence.",
    "parameters": [
     {
      "name": "poet",
      "in": "query",
      "required": false,
      "description": "e.g. 李白",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "substring of title, text or summary",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "from",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "default 30",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the list",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   },
   "post": {
    "operationId": "add_poem",
    "summary": "Add a poem to the map (live)",
    "description": "Pin a poem on the 山河鉴 map where and when it was written (581–763 CE). Goes live at once, marked 社区补充. Required: date (when written, YYYY at least), place (where written: id from list_places or {name, ll:[lon, lat]}), poem {poet, title (no 《》), text: array of lines, one couplet per item, form?}, summary (the circumstances, 2–6 sentences), evidence (1–8 sources with https url — the text's source, e.g. 全唐诗 on zh.wikisource.org, and the dating). Optional: title for the map card (default 「杜甫作《月夜》」), why, debate (dating disputes), who, importance. Check list_poems first.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "additionalProperties": false,
        "required": [
         "date",
         "place",
         "poem",
         "summary",
         "evidence"
        ],
        "properties": {
         "poem": {
          "type": "object",
          "additionalProperties": false,
          "required": [
           "poet",
           "title",
           "text"
          ],
          "properties": {
           "poet": {
            "type": "string",
            "maxLength": 20,
            "description": "诗人，如「王维」"
           },
           "title": {
            "type": "string",
            "maxLength": 30,
            "description": "诗题，不加书名号，如「送元二使安西」"
           },
           "form": {
            "type": "string",
            "maxLength": 12,
            "description": "体裁，如 五言绝句 / 七言律诗 / 古体"
           },
           "text": {
            "type": "array",
            "items": {
             "type": "string",
             "maxLength": 60
            },
            "minItems": 1,
            "maxItems": 80,
            "description": "全诗，一联（两句）一项，如 [\"渭城朝雨浥轻尘，客舍青青柳色新。\", \"…\"]"
           },
           "excerpt": {
            "type": "boolean",
            "description": "true if text is only part of the poem"
           }
          }
         },
         "title": {
          "type": "string",
          "maxLength": 40,
          "description": "地图卡片标题；省略则为「王维作《送元二使安西》」"
         },
         "date": {
          "type": "string",
          "pattern": "^0[5-7][0-9]{2}(-[01][0-9](-[0-3][0-9])?)?$",
          "description": "Julian date YYYY, YYYY-MM or YYYY-MM-DD, 4-digit year, 0581–0763"
         },
         "place": {
          "description": "existing place id (list_events → places) or a new place {name, ll:[lon, lat]}",
          "oneOf": [
           {
            "type": "string"
           },
           {
            "type": "object",
            "required": [
             "name",
             "ll"
            ],
            "additionalProperties": false,
            "properties": {
             "name": {
              "type": "string"
             },
             "ll": {
              "type": "array",
              "items": {
               "type": "number"
              },
              "minItems": 2,
              "maxItems": 2
             }
            }
           }
          ]
         },
         "summary": {
          "type": "string",
          "maxLength": 800,
          "description": "写作背景，2–6 句"
         },
         "why": {
          "type": "string",
          "maxLength": 400,
          "description": "为什么重要"
         },
         "debate": {
          "type": "string",
          "maxLength": 400,
          "description": "系年、地点或文本的争议"
         },
         "who": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 12
         },
         "importance": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2,
          "description": "1 = minor, 2 = notable (3 is reserved for the curated headline events)"
         },
         "evidence": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
           "type": "object",
           "required": [
            "type",
            "title",
            "cite",
            "url"
           ],
           "additionalProperties": false,
           "properties": {
            "type": {
             "type": "string",
             "enum": [
              "text",
              "archaeology",
              "inscription",
              "artifact",
              "art",
              "foreign",
              "modern"
             ]
            },
            "title": {
             "type": "string"
            },
            "cite": {
             "type": "string",
             "description": "出处，如《旧唐书》卷一百九十六"
            },
            "url": {
             "type": "string",
             "description": "https link you actually read (wikisource, a museum, a paper)"
            },
            "quote": {
             "type": "string",
             "description": "原文引句"
            },
            "detail": {
             "type": "string"
            },
            "stance": {
             "type": "string",
             "enum": [
              "supports",
              "complicates",
              "contradicts"
             ]
            },
            "confidence": {
             "type": "string",
             "enum": [
              "high",
              "medium",
              "low"
             ]
            },
            "year": {
             "type": "integer"
            },
            "where": {
             "type": "string"
            }
           }
          }
         }
        }
       },
       "example": {
        "date": "0749",
        "place": {
         "name": "陇山道中",
         "ll": [
          106.3,
          34.9
         ]
        },
        "poem": {
         "poet": "岑参",
         "title": "逢入京使",
         "form": "七言绝句",
         "text": [
          "故园东望路漫漫，双袖龙钟泪不干。",
          "马上相逢无纸笔，凭君传语报平安。"
         ]
        },
        "summary": "天宝八载（749），岑参首次出塞，赴安西任高仙芝幕府掌书记。西行途中遇到东归长安的使者，马上相逢，无纸笔可写家书，只托他口头报平安。",
        "evidence": [
         {
          "type": "text",
          "title": "《全唐诗》卷二百零一收《逢入京使》",
          "cite": "《全唐诗》卷201",
          "url": "https://zh.wikisource.org/wiki/逢入京使"
         }
        ]
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "added and live: {ok:true, id, url, item}",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     },
     "413": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     },
     "429": {
      "description": "rate limit (20 an hour, 60 a day per address)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/poems/{id}": {
   "get": {
    "operationId": "get_event_poem",
    "summary": "Get one event or poem in full",
    "description": "The full record of one event or poem by id (from list_events / list_poems): summary, why, who, debate, every piece of evidence with its source url, and the poem text if it is a poem.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the full record",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "404": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/places": {
   "get": {
    "operationId": "list_places",
    "summary": "Find place ids",
    "description": "Search the map's named places (city, battlefield, pass, temple…) to get a place id and its [lon, lat]. Use the id as `place` in add_event / add_poem / add_shuoshu; if the place is not there, pass {name, ll:[lon, lat]} instead. With near:[lon, lat] results are sorted by distance.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "substring of the name, e.g. 长安, 潼关, 扬州",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "near",
      "in": "query",
      "required": false,
      "description": "lon,lat — e.g. 108.9,34.3",
      "schema": {
       "type": "string",
       "pattern": "^-?[\\d.]+,-?[\\d.]+$"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "default 20",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the list",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/shuoshu": {
   "get": {
    "operationId": "list_shuoshu",
    "summary": "List 说书 (storyteller tellings)",
    "description": "说书: history told as a storyteller would, in 回 (chapters), each built around a 「史书打架」 — a point where the sources disagree. Lists the curated tellings (with audio) and community ones (text). Returns id, title, year, era, blurb, dispute, source.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the list",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   },
   "post": {
    "operationId": "add_shuoshu",
    "summary": "Add a 说书 telling (live, text only)",
    "description": "Add a 说书: a historical episode told in 评书 style, as text (no audio). Goes live at once on the 书目 page, marked 社区. Required: title (≤20), year (integer CE, -1000..1911), era (e.g. 唐 天宝十四载), blurb (≤200, the hook), dispute (≤300: where the sources disagree — the heart of every 说书), hui: 1–10 chapters {title, text ≤3000 chars} (≤20000 total), sources: 1–8 {type, title, cite, url:https}. Optional: place, who. Simplified Chinese, no HTML.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "additionalProperties": false,
        "required": [
         "title",
         "year",
         "era",
         "blurb",
         "dispute",
         "hui",
         "sources"
        ],
        "properties": {
         "title": {
          "type": "string",
          "maxLength": 20,
          "description": "书名，如「玄武门之变」"
         },
         "year": {
          "type": "integer",
          "minimum": -1000,
          "maximum": 1911,
          "description": "公元年份（负数为公元前），如 626"
         },
         "era": {
          "type": "string",
          "maxLength": 30,
          "description": "朝代与年号，如「唐 武德九年」"
         },
         "blurb": {
          "type": "string",
          "maxLength": 200,
          "description": "一两句引子，书目卡片上显示"
         },
         "dispute": {
          "type": "string",
          "maxLength": 300,
          "description": "「史书打架」：不同史料说法不一之处，如「资治通鉴说伏兵，旧唐书说自卫」"
         },
         "hui": {
          "type": "array",
          "minItems": 1,
          "maxItems": 10,
          "description": "分回正文，评书口吻，简体中文",
          "items": {
           "type": "object",
           "additionalProperties": false,
           "required": [
            "title",
            "text"
           ],
           "properties": {
            "title": {
             "type": "string",
             "maxLength": 30,
             "description": "回目，如「第一回 兄弟阋墙」"
            },
            "text": {
             "type": "string",
             "maxLength": 3000,
             "description": "这一回的正文，段落用换行分开"
            }
           }
          }
         },
         "place": {
          "description": "可选：故事发生地（place id 或 {name, ll}）",
          "oneOf": [
           {
            "type": "string"
           },
           {
            "type": "object",
            "required": [
             "name",
             "ll"
            ],
            "additionalProperties": false,
            "properties": {
             "name": {
              "type": "string"
             },
             "ll": {
              "type": "array",
              "items": {
               "type": "number"
              },
              "minItems": 2,
              "maxItems": 2
             }
            }
           }
          ]
         },
         "who": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "maxItems": 12
         },
         "sources": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "items": {
           "type": "object",
           "required": [
            "type",
            "title",
            "cite",
            "url"
           ],
           "additionalProperties": false,
           "properties": {
            "type": {
             "type": "string",
             "enum": [
              "text",
              "archaeology",
              "inscription",
              "artifact",
              "art",
              "foreign",
              "modern"
             ]
            },
            "title": {
             "type": "string"
            },
            "cite": {
             "type": "string",
             "description": "出处，如《旧唐书》卷一百九十六"
            },
            "url": {
             "type": "string",
             "description": "https link you actually read (wikisource, a museum, a paper)"
            },
            "quote": {
             "type": "string",
             "description": "原文引句"
            },
            "detail": {
             "type": "string"
            },
            "stance": {
             "type": "string",
             "enum": [
              "supports",
              "complicates",
              "contradicts"
             ]
            },
            "confidence": {
             "type": "string",
             "enum": [
              "high",
              "medium",
              "low"
             ]
            },
            "year": {
             "type": "integer"
            },
            "where": {
             "type": "string"
            }
           }
          },
          "description": "出处，与 evidence 同格式"
         }
        }
       },
       "example": {
        "title": "安禄山起兵",
        "year": 755,
        "era": "唐 天宝十四载",
        "blurb": "范阳鼓声动地来。三镇节度使安禄山以讨杨国忠为名，十五万人南下。",
        "dispute": "起兵是蓄谋已久，还是被杨国忠逼反？《旧唐书》说他早有异志，《资治通鉴》记杨国忠屡言其必反、有意激之。",
        "hui": [
         {
          "title": "第一回 范阳起兵",
          "text": "天宝十四载十一月初九，范阳城外……"
         },
         {
          "title": "第二回 渔阳鼙鼓",
          "text": "……"
         }
        ],
        "place": "youzhou",
        "who": [
         "安禄山",
         "杨国忠",
         "唐玄宗"
        ],
        "sources": [
         {
          "type": "text",
          "title": "《资治通鉴》卷二百一十七",
          "cite": "《资治通鉴》卷217",
          "url": "https://zh.wikisource.org/wiki/資治通鑑/卷217"
         }
        ]
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "added and live: {ok:true, id, url, item}",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     },
     "413": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     },
     "429": {
      "description": "rate limit (20 an hour, 60 a day per address)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/shuoshu/{id}": {
   "get": {
    "operationId": "get_shuoshu",
    "summary": "Read one 说书",
    "description": "The full text of a community 说书 by id (all 回 and sources); for a curated one, its card and the page url.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "the full record",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "404": {
      "description": "Not done. `errors` names each wrong field — fix those and send again.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Errors"
        }
       }
      }
     }
    }
   }
  },
  "/api/submit": {
   "get": {
    "operationId": "submit_get",
    "summary": "Add an event or poem by opening a URL (GET-only agents)",
    "description": "Same validator, duplicate check and rate limit as POST. Flat parameters, or data=<url-encoded JSON>. Answers plain text: ADDED with the live link, or NOT ADDED with one line per wrong field. dry=1 checks only. See /llms.txt.",
    "parameters": [
     {
      "name": "type",
      "in": "query",
      "required": false,
      "description": "event | poem",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "data",
      "in": "query",
      "required": false,
      "description": "the whole JSON object instead of the flat parameters",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "title",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "date",
      "in": "query",
      "required": false,
      "description": "YYYY, YYYY-MM or YYYY-MM-DD",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "mil, pol, dip, gov, cul, nat",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "place",
      "in": "query",
      "required": false,
      "description": "a place id, or 名字|lon,lat",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "summary",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "src",
      "in": "query",
      "required": false,
      "description": "repeat: <https url>|<cite>|<title>",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "who",
      "in": "query",
      "required": false,
      "description": "甲,乙",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "why",
      "in": "query",
      "required": false,
      "description": "",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "poet",
      "in": "query",
      "required": false,
      "description": "poems",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "ptitle",
      "in": "query",
      "required": false,
      "description": "poem title, no 《》",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "text",
      "in": "query",
      "required": false,
      "description": "poem lines split by /",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "dry",
      "in": "query",
      "required": false,
      "description": "1 = check only",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "201": {
      "description": "ADDED",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "400": {
      "description": "NOT ADDED, fields named",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "Errors": {
    "type": "object",
    "properties": {
     "ok": {
      "const": false
     },
     "errors": {
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    }
   }
  }
 }
}