{
  "openapi": "3.1.1",
  "info": {
    "title": "Ohmforge Magnetic Declination (WMM2025) API",
    "version": "1.0.0",
    "summary": "Magnetic declination, inclination and field strength for any place and date (2025–2030).",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://ohmforgemagneticdeclination.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Magnetic declination, inclination and field strength for any place and date (2025–2030).",
        "description": "Computes the Earth's main magnetic field with the World Magnetic Model WMM2025 of NOAA and the British Geological Survey: declination (how far a compass needle points away from true north), inclination, horizontal and total field strength, the yearly change and the grid variation near the poles. Optionally converts a compass bearing to a true bearing. Same model as the compass in Ohmforge's Pocket instruments.\n\nMethodology:\n- The World Magnetic Model WMM2025 (degree and order 12, epoch 2025.0) is evaluated as a spherical-harmonic series: geodetic WGS84 coordinates are converted to geocentric spherical ones, Schmidt semi-normalised Legendre functions are built by recursion, the Gauss coefficients are moved to the date with their yearly change, and the field vector is rotated back to the local north/east/down frame.\n- Declination D = atan2(east, north), inclination I = atan2(down, horizontal); their yearly changes follow from the yearly change of the components. Near the poles (|latitude| ≥ 55°) the grid variation (declination relative to grid north of a polar stereographic map) is also given.\n- The model reproduces all 100 points of the official WMM2025 test value list to the printed precision (0.01° and 10⁻⁶ nT). A true bearing is the magnetic bearing plus the declination.\n- Where the horizontal field is below 6000 nT a compass becomes sluggish (caution zone); below 2000 nT the WMM report calls the declination unreliable (blackout zone).\n\nThe WMM describes the main field from the Earth's core only. Local magnetism (rocks, steel, cars, power lines, the phone itself) and magnetic storms can turn a compass by several degrees; do not rely on a phone compass for navigation where safety matters.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "ohmforge_magnetic_declination",
        "x-owner-app": "ohmforge",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OhmforgeMagneticDeclinationInput"
              },
              "examples": {
                "example1": {
                  "summary": "Berlin, 8 November 2026",
                  "value": {
                    "latitude": 52.52,
                    "longitude": 13.405,
                    "height": 34,
                    "date": "2026-11-08"
                  }
                },
                "example2": {
                  "summary": "Seattle with a compass bearing of 90° (east)",
                  "value": {
                    "latitude": 47.6062,
                    "longitude": -122.3321,
                    "height": 50,
                    "date": "2027-06-01",
                    "bearing": 90
                  }
                },
                "example3": {
                  "summary": "WMM2025 test point: 80° S, 240° E at 100 km, 2027.5",
                  "value": {
                    "latitude": -80,
                    "longitude": 240,
                    "height": 100000,
                    "date": "2027.5"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OhmforgeMagneticDeclinationResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "OhmforgeMagneticDeclinationInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "latitude": {
            "title": "Latitude",
            "description": "North positive, south negative (WGS84).",
            "type": "number",
            "minimum": -90,
            "maximum": 90,
            "default": 52.52,
            "x-unit": "°"
          },
          "longitude": {
            "title": "Longitude",
            "description": "East positive, west negative.",
            "type": "number",
            "minimum": -180,
            "maximum": 360,
            "default": 13.405,
            "x-unit": "°"
          },
          "height": {
            "title": "Height above sea level",
            "description": "Treated as height above the WGS84 ellipsoid; the difference (up to about 100 m) does not matter here.",
            "type": "number",
            "minimum": -1000,
            "maximum": 850000,
            "default": 0,
            "x-unit": "m"
          },
          "date": {
            "title": "Date",
            "description": "YYYY-MM-DD or a decimal year such as 2027.5, between 2025.0 and 2030.0. Empty = today.",
            "type": "string",
            "maxLength": 12
          },
          "bearing": {
            "title": "Compass bearing to convert (optional)",
            "description": "A magnetic bearing read from a compass; the result adds the declination to get the true bearing.",
            "type": "number",
            "minimum": 0,
            "maximum": 360,
            "x-unit": "°"
          }
        },
        "required": []
      },
      "OhmforgeMagneticDeclinationResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "model",
              "year",
              "declination",
              "inclination",
              "horizontalIntensity",
              "northComponent",
              "eastComponent",
              "downComponent",
              "totalIntensity",
              "gridVariation",
              "declinationChange",
              "inclinationChange",
              "totalIntensityChange",
              "zone",
              "trueBearing"
            ],
            "properties": {
              "model": {
                "type": "string"
              },
              "year": {
                "type": "number",
                "description": "Decimal year used."
              },
              "declination": {
                "type": "number",
                "description": "Degrees, east positive."
              },
              "inclination": {
                "type": "number",
                "description": "Degrees, down positive."
              },
              "horizontalIntensity": {
                "type": "number"
              },
              "northComponent": {
                "type": "number"
              },
              "eastComponent": {
                "type": "number"
              },
              "downComponent": {
                "type": "number"
              },
              "totalIntensity": {
                "type": "number"
              },
              "gridVariation": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Only for |latitude| ≥ 55°."
              },
              "declinationChange": {
                "type": "number",
                "description": "Degrees per year."
              },
              "inclinationChange": {
                "type": "number"
              },
              "totalIntensityChange": {
                "type": "number",
                "description": "nT per year."
              },
              "zone": {
                "type": "string",
                "enum": [
                  "ok",
                  "caution",
                  "unreliable"
                ]
              },
              "trueBearing": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}