{
  "openapi": "3.1.0",
  "info": {
    "title": "Range Coach Content API",
    "version": "1.0.0",
    "summary": "Read-only access to Range Coach's public drill, qualification-course and zeroing guides.",
    "description": "Every page on myrangecoach.com is public and read-only. Request any page with `Accept: text/markdown` to get a clean Markdown version instead of HTML. No authentication. Range Coach app data (shot groups, logs) is stored only in each user's browser and is not available through this interface. Content-use preferences are declared in /robots.txt (Content-Signal: search=yes, ai-input=yes, ai-train=no)."
  },
  "servers": [
    {
      "url": "https://myrangecoach.com"
    }
  ],
  "externalDocs": {
    "description": "Human-readable documentation",
    "url": "https://myrangecoach.com/api-docs"
  },
  "paths": {
    "/": {
      "get": {
        "operationId": "getHome",
        "summary": "Home page (app overview)",
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/drill-library/": {
      "get": {
        "operationId": "listDrills",
        "summary": "Index of all drill library pages",
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/drill-library/{slug}": {
      "get": {
        "operationId": "getDrill",
        "summary": "A single drill library page",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "5x5-drill",
                "ball-and-dummy-drill",
                "bill-drill",
                "box-drill",
                "dot-torture-drill",
                "el-presidente-drill",
                "failure-to-stop-mozambique-drill",
                "reload-drill",
                "strong-support-hand-only-drill",
                "wall-drill-dry-fire"
              ]
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/qualifications/": {
      "get": {
        "operationId": "listQualificationCourses",
        "summary": "Index of all qualifications pages",
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/qualifications/{slug}": {
      "get": {
        "operationId": "getQualificationCourse",
        "summary": "A single qualifications page",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "air-force-weapons-qualification-catm",
                "army-pistol-qualification-m17-m18",
                "army-rifle-qualification-m4-m16",
                "atf-federal-law-enforcement-pistol-qualification",
                "dea-firearms-qualification-course",
                "doe-protective-force-firearms-qualification",
                "fbi-pistol-qualification-q-course",
                "federal-air-marshal-service-qualification-course",
                "navy-pistol-qualification-m9-m18",
                "nra-ppc-police-pistol-combat-course",
                "state-trooper-highway-patrol-qualification-course",
                "usmc-rifle-qualification-table-1-2"
              ]
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/zeroing/": {
      "get": {
        "operationId": "listZeroingGuides",
        "summary": "Index of all zeroing pages",
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/zeroing/{slug}": {
      "get": {
        "operationId": "getZeroingGuide",
        "summary": "A single zeroing page",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "pistol-red-dot-zero-15-yards",
                "rifle-zero-25-yards-battlesight",
                "rifle-zero-50-yards"
              ]
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "text/markdown"
            },
            "description": "Send `text/markdown` to receive the Markdown version of the page."
          }
        ],
        "responses": {
          "200": {
            "description": "The page. HTML by default; Markdown (with YAML front matter) when the request sends `Accept: text/markdown`.",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes `Accept`."
              },
              "x-markdown-tokens": {
                "schema": {
                  "type": "integer"
                },
                "description": "Estimated token count (Markdown responses only)."
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No such page."
          }
        }
      }
    },
    "/sitemap.xml": {
      "get": {
        "operationId": "getSitemap",
        "summary": "XML sitemap of every page",
        "responses": {
          "200": {
            "description": "Sitemap",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Service health check",
        "responses": {
          "200": {
            "description": "The site is serving requests.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    }
                  },
                  "required": [
                    "status"
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
}
