{
  "openapi": "3.1.0",
  "info": {
    "title": "LaunchDetect Free Detection API",
    "version": "1.0.0",
    "description": "Connect the free LaunchDetect detection API to AI agents, Python, QGIS, Leaflet and MapLibre. JSON endpoints, field definitions, rate limits and a GeoJSON example.",
    "termsOfService": "https://launchdetect.com/tos/",
    "contact": {
      "name": "LAUNCHDETECT LLC",
      "email": "ops@launchdetect.com"
    }
  },
  "servers": [
    {
      "url": "https://launchdetect.com"
    }
  ],
  "security": [],
  "externalDocs": {
    "url": "https://launchdetect.com/blog/free-detection-api/"
  },
  "paths": {
    "/evidence/v1/signals/latest.json": {
      "get": {
        "operationId": "getLatestDetection",
        "summary": "Get the latest published detection and evidence links",
        "description": "Read-only public snippet API. No API key. Poll at most once every 300 seconds; approximate limit 60 requests per 300 seconds per IP. Inspect generatedAt and detectedAt separately.",
        "responses": {
          "200": {
            "description": "Cached published JSON",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LatestDetection"
                }
              }
            }
          },
          "304": {
            "description": "Not modified for a conditional request"
          },
          "429": {
            "description": "Rate limited. Wait at least 300 seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Request blocked or static object unavailable"
          },
          "404": {
            "description": "Record unavailable"
          }
        }
      }
    },
    "/evidence/v1/signals/index.json": {
      "get": {
        "operationId": "listRecentDetections",
        "summary": "List up to 100 recent detection snippets",
        "description": "Read-only public snippet API. No API key. Poll at most once every 300 seconds; approximate limit 60 requests per 300 seconds per IP. Inspect generatedAt and detectedAt separately.",
        "responses": {
          "200": {
            "description": "Cached published JSON",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DetectionIndex"
                }
              }
            }
          },
          "304": {
            "description": "Not modified for a conditional request"
          },
          "429": {
            "description": "Rate limited. Wait at least 300 seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Request blocked or static object unavailable"
          },
          "404": {
            "description": "Record unavailable"
          }
        }
      }
    },
    "/evidence/v1/signals/{id}.json": {
      "get": {
        "operationId": "getDetection",
        "summary": "Get one public detection record",
        "description": "Read-only public snippet API. No API key. Poll at most once every 300 seconds; approximate limit 60 requests per 300 seconds per IP. Inspect generatedAt and detectedAt separately.",
        "responses": {
          "200": {
            "description": "Cached published JSON",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Detection"
                }
              }
            }
          },
          "304": {
            "description": "Not modified for a conditional request"
          },
          "429": {
            "description": "Rate limited. Wait at least 300 seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Request blocked or static object unavailable"
          },
          "404": {
            "description": "Record unavailable"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ld-[a-f0-9]{16}$"
            }
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "Detection": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "missionName",
          "vehicle",
          "siteName",
          "lat",
          "lon",
          "scheduledT0",
          "status",
          "detected",
          "detectedAt",
          "generatedAt",
          "source"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ld-[a-f0-9]{16}$"
          },
          "missionName": {
            "type": [
              "string",
              "null"
            ]
          },
          "vehicle": {
            "type": [
              "string",
              "null"
            ]
          },
          "siteName": {
            "type": [
              "string",
              "null"
            ]
          },
          "lat": {
            "type": [
              "number",
              "null"
            ],
            "minimum": -90,
            "maximum": 90,
            "description": "Launch-site latitude, not plume location."
          },
          "lon": {
            "type": [
              "number",
              "null"
            ],
            "minimum": -180,
            "maximum": 180,
            "description": "Launch-site longitude, not plume location."
          },
          "scheduledT0": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "detected": {
            "type": "boolean"
          },
          "detectedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "generatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "source": {
            "const": "LaunchDetect"
          }
        }
      },
      "LatestDetection": {
        "type": "object",
        "required": [
          "schemaVersion",
          "generatedAt",
          "available",
          "detection",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "const": 1
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "available": {
            "type": "boolean"
          },
          "coordinateMeaning": {
            "const": "launch_site"
          },
          "coordinateReferenceSystem": {
            "const": "EPSG:4326"
          },
          "recommendedPollSeconds": {
            "const": 300
          },
          "detection": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Detection"
              },
              {
                "type": "null"
              }
            ]
          },
          "links": {
            "type": "object",
            "properties": {
              "record": {
                "type": "string",
                "format": "uri"
              },
              "snippet": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "DetectionIndex": {
        "type": "object",
        "required": [
          "schemaVersion",
          "generatedAt",
          "source",
          "window",
          "count",
          "total",
          "limit",
          "truncated",
          "detections"
        ],
        "properties": {
          "schemaVersion": {
            "const": 1
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "const": "LaunchDetect"
          },
          "window": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date-time"
              },
              "to": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "const": 100
          },
          "truncated": {
            "type": "boolean"
          },
          "detections": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/Detection"
            }
          }
        }
      }
    }
  }
}