{
  "openapi": "3.1.0",
  "info": {
    "title": "BackpackMap",
    "version": "1.0.0",
    "summary": "Join the free BackpackMap TestFlight beta, and read the site through MCP.",
    "description": "BackpackMap is a free iPhone hiking app in a free TestFlight beta. Rules for agents, including consent for sign-ups: https://backpackmap.app/AGENTS.md"
  },
  "servers": [{ "url": "https://backpackmap.app" }],
  "externalDocs": { "description": "For AI agents", "url": "https://backpackmap.app/agents/" },
  "paths": {
    "/api/beta-signup": {
      "post": {
        "operationId": "joinBeta",
        "summary": "Join a person to the free TestFlight beta",
        "description": "Call only when the person asks, with their own name and the email of their own Apple ID. Apple emails the TestFlight invite to that address. Limit: 5 sign-ups per network per hour.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name", "email"],
                "properties": {
                  "name": { "type": "string", "maxLength": 60, "description": "The person's name, for the invite." },
                  "email": { "type": "string", "format": "email", "maxLength": 254, "description": "The email of the person's Apple ID. TestFlight sends the invite there." },
                  "phone": { "type": "string", "description": "Optional. The iPhone number the person will text Signal Fire from, with area code (10 to 15 digits)." },
                  "model": { "type": "string", "maxLength": 40, "description": "Optional. The iPhone model the person will hike with, for example \"iPhone 15 Pro\"." }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved. invited is true when Apple is emailing the TestFlight invite now, false when the person is on the list for one.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": { "ok": { "const": true }, "invited": { "type": "boolean" } }
            } } }
          },
          "400": {
            "description": "A field is wrong. Nothing was saved. field names it and message says how to fix it.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "ok": { "const": false },
                "field": { "type": "string", "enum": ["name", "email", "phone"] },
                "message": { "type": "string" }
              }
            } } }
          },
          "429": {
            "description": "Too many sign-ups from this network in the last hour. Nothing was saved. Wait an hour; do not retry in a loop.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": { "ok": { "const": false }, "message": { "type": "string" } }
            } } }
          },
          "500": {
            "description": "The server could not save the sign-up. Nothing was saved. Try again in a minute.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": { "ok": { "const": false }, "message": { "type": "string" } }
            } } }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "Read-only MCP server (Streamable HTTP, stateless)",
        "description": "Send one JSON-RPC 2.0 message per request: initialize, tools/list, tools/call, resources/list, resources/read or ping. Tools: get_overview, compare_satellite_devices, get_agent_rules, list_pages, read_page. Card: https://backpackmap.app/.well-known/mcp-server-card.json",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["jsonrpc", "method"],
            "properties": {
              "jsonrpc": { "const": "2.0" },
              "id": { "type": ["string", "integer"] },
              "method": { "type": "string" },
              "params": { "type": "object" }
            }
          } } }
        },
        "responses": {
          "200": { "description": "The JSON-RPC answer.", "content": { "application/json": { "schema": { "type": "object" } } } },
          "202": { "description": "A notification was accepted. No body." },
          "400": { "description": "The body is not valid JSON." }
        }
      }
    }
  }
}
