{
  "openapi": "3.1.0",
  "info": {
    "title": "SpotCrime API",
    "version": "1.0",
    "summary": "Real-time crime data, neighborhood safety scores, and crime alerts across 22,000+ U.S. cities.",
    "description": "The SpotCrime API delivers real-time and historical crime incident data, neighborhood safety scores (SpotScore), and trend timeseries for any U.S. address.\n\n**Coverage:** 22,000+ cities, 500M+ historical records, updated every 15 minutes.\n\n**Pricing:** Developer $199/mo, Pro $599/mo, Enterprise custom. Full pricing at https://spotcrime.io/api-pricing.\n\n**Get an API key:** https://spotcrime.io/request-access.\n\n**For AI agents:** https://spotcrime.io/for-ai-agents.",
    "termsOfService": "https://spotcrime.io/api-terms",
    "contact": {
      "name": "SpotCrime",
      "url": "https://spotcrime.io/request-access",
      "email": "feedback@spotcrime.com"
    },
    "license": {
      "name": "Commercial — see terms of service",
      "url": "https://spotcrime.io/api-terms"
    }
  },
  "externalDocs": {
    "description": "SpotCrime API documentation",
    "url": "https://spotcrime.io/api/docs"
  },
  "servers": [
    {
      "url": "https://api.spotcrime.com",
      "description": "Live production API (stable)"
    },
    {
      "url": "https://api.spotcrime.com/v1",
      "description": "v1 API (planned — not yet live)"
    }
  ],
  "security": [
    {
      "apiKeyQuery": []
    },
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Live API",
      "description": "Endpoints available today."
    },
    {
      "name": "v1 (planned)",
      "description": "Planned v1 surface — not yet live."
    },
    {
      "name": "Developer",
      "description": "Available on the Developer plan ($199/mo)."
    },
    {
      "name": "Pro",
      "description": "Available on the Pro plan ($599/mo)."
    },
    {
      "name": "Enterprise",
      "description": "Available on Enterprise plans."
    }
  ],
  "paths": {
    "/crimes.json": {
      "get": {
        "operationId": "get-crimes-json",
        "summary": "Recent incidents near a point",
        "description": "Returns the most recent ~50 reported incidents within a radius of a lat/lon. This is the endpoint powering SpotCrime's public products today.\n\n- `radius` on this legacy endpoint is in decimal degrees, not miles. 1 mile ≈ 0.01448°. The planned `/v1/incidents` endpoint accepts `radius_mi` in miles.\n- Capped at 50 results per call. Use multiple smaller radii or the planned `/v1/incidents` endpoint with cursor pagination for larger result sets.\n- Date format is local-time `MM/DD/YY HH:MM AM/PM` without a timezone suffix.\n- Incident `type` values include Shooting, Assault, Robbery, Burglary, Theft, Arson, Vandalism, Arrest, Other.",
        "tags": [
          "Live API",
          "Developer",
          "Pro",
          "Enterprise"
        ],
        "x-status": "stable",
        "x-plans": [
          "Developer",
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "apiKeyQuery": []
          }
        ],
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude, decimal degrees.",
            "schema": {
              "type": "number",
              "example": 39.4143
            },
            "example": 39.4143
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude, decimal degrees.",
            "schema": {
              "type": "number",
              "example": -76.6019
            },
            "example": -76.6019
          },
          {
            "name": "radius",
            "in": "query",
            "required": true,
            "description": "Radius in degrees. 0.01 equals approximately one mile.",
            "schema": {
              "type": "number",
              "example": 0.01
            },
            "example": 0.01
          },
          {
            "name": "key",
            "in": "query",
            "required": true,
            "description": "Your API key.",
            "schema": {
              "type": "string",
              "example": "***"
            },
            "example": "***"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "crimes": [
                    {
                      "cdid": 285636408,
                      "type": "Assault",
                      "date": "06/02/26 09:17 PM",
                      "address": "15600 BLK OLD COLUMBIA PIKE",
                      "link": "https://spotcrime.com/crime/285636408-965bf3969effb73027bded29be470326",
                      "lat": 39.11131,
                      "lon": -76.932
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/incidents": {
      "get": {
        "operationId": "get-v1-incidents",
        "summary": "Crime incidents with full filtering & pagination",
        "description": "Same dataset as /crimes.json but with cursor pagination, ISO-8601 timestamps, time-range filtering, and structured type categories.",
        "tags": [
          "v1 (planned)",
          "Developer",
          "Pro",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Developer",
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude.",
            "schema": {
              "type": "number",
              "example": 39.4143
            },
            "example": 39.4143
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude.",
            "schema": {
              "type": "number",
              "example": -76.6019
            },
            "example": -76.6019
          },
          {
            "name": "radius_mi",
            "in": "query",
            "required": true,
            "description": "Radius in miles.",
            "schema": {
              "type": "number",
              "example": 0.5
            },
            "example": 0.5
          },
          {
            "name": "start",
            "in": "query",
            "required": false,
            "description": "Earliest occurred_at (inclusive).",
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2026-05-01T00:00:00Z"
            },
            "example": "2026-05-01T00:00:00Z"
          },
          {
            "name": "end",
            "in": "query",
            "required": false,
            "description": "Latest occurred_at (inclusive).",
            "schema": {
              "type": "string",
              "format": "date-time",
              "example": "2026-06-01T00:00:00Z"
            },
            "example": "2026-06-01T00:00:00Z"
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "description": "Filter by incident type.",
            "schema": {
              "type": "string",
              "example": "shooting,robbery"
            },
            "example": "shooting,robbery"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor returned by the prior page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–500. Default 100.",
            "schema": {
              "type": "integer",
              "example": 100
            },
            "example": 100
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "incidents": [
                    {
                      "id": "285636408",
                      "type": "assault",
                      "raw_type": "Assault",
                      "occurred_at": "2026-06-02T21:17:00-04:00",
                      "address": "15600 BLK OLD COLUMBIA PIKE",
                      "lat": 39.11131,
                      "lon": -76.932,
                      "url": "https://spotcrime.com/crime/285636408-..."
                    }
                  ],
                  "next_cursor": "eyJvIjoxMjM0NX0"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/score": {
      "get": {
        "operationId": "get-v1-score",
        "summary": "Neighborhood safety score (SpotScore)",
        "description": "Returns a 0–100 safety score for the point, with letter grade and category breakdown. Updated daily.",
        "tags": [
          "v1 (planned)",
          "Developer",
          "Pro",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Developer",
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude.",
            "schema": {
              "type": "number",
              "example": 39.4143
            },
            "example": 39.4143
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude.",
            "schema": {
              "type": "number",
              "example": -76.6019
            },
            "example": -76.6019
          },
          {
            "name": "radius_mi",
            "in": "query",
            "required": false,
            "description": "Radius in miles. Default 0.5.",
            "schema": {
              "type": "number",
              "example": 0.5
            },
            "example": 0.5
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "score": 78,
                  "grade": "B−",
                  "radius_mi": 0.5,
                  "updated_at": "2026-06-03T06:00:00Z",
                  "breakdown": {
                    "violent": 12,
                    "property": 41,
                    "quality_of_life": 25
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/trends": {
      "get": {
        "operationId": "get-v1-trends",
        "summary": "Crime trend timeseries",
        "description": "Returns incident counts bucketed by day/week/month over a window, optionally split by category.",
        "tags": [
          "v1 (planned)",
          "Pro",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "radius_mi",
            "in": "query",
            "required": true,
            "description": "Radius in miles.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "interval",
            "in": "query",
            "required": false,
            "description": "day | week | month. Default week.",
            "schema": {
              "type": "string",
              "example": "week"
            },
            "example": "week"
          },
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "ISO-8601 duration. Default P12W.",
            "schema": {
              "type": "string",
              "example": "P12W"
            },
            "example": "P12W"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "interval": "week",
                  "buckets": [
                    {
                      "start": "2026-03-09",
                      "end": "2026-03-15",
                      "count": 14,
                      "by_type": {
                        "assault": 3,
                        "theft": 7,
                        "other": 4
                      }
                    },
                    {
                      "start": "2026-03-16",
                      "end": "2026-03-22",
                      "count": 11,
                      "by_type": {
                        "assault": 2,
                        "theft": 6,
                        "other": 3
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/history": {
      "get": {
        "operationId": "get-v1-history",
        "summary": "Historical incidents (up to 36 months)",
        "description": "Same shape as /v1/incidents but allows querying the full 36-month archive.",
        "tags": [
          "v1 (planned)",
          "Pro",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "radius_mi",
            "in": "query",
            "required": true,
            "description": "Radius in miles.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "start",
            "in": "query",
            "required": true,
            "description": "Earliest occurred_at.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "end",
            "in": "query",
            "required": true,
            "description": "Latest occurred_at.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "incidents": [
                    {
                      "id": "271110021",
                      "type": "burglary",
                      "occurred_at": "2024-09-12T03:14:00-04:00",
                      "lat": 39.41,
                      "lon": -76.6
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/batch": {
      "post": {
        "operationId": "post-v1-batch",
        "summary": "Batch query up to 500 locations",
        "description": "Submit up to 500 points in one call; receive an array of per-point results. Useful for branch portfolios and listing pages.",
        "tags": [
          "v1 (planned)",
          "Pro",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "{ points: [{ id, lat, lon, radius_mi }], fields: ['score','count'] }"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "results": [
                    {
                      "id": "BR-001",
                      "score": 78,
                      "count_30d": 24
                    },
                    {
                      "id": "BR-002",
                      "score": 41,
                      "count_30d": 71
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/alerts/subscribe": {
      "post": {
        "operationId": "post-v1-alerts-subscribe",
        "summary": "Subscribe to crime alerts",
        "description": "Create a webhook subscription that fires when new incidents land within a geofence.",
        "tags": [
          "v1 (planned)",
          "Pro",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Pro",
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "{ webhook_url, geofences: [{ lat, lon, radius_mi }], types?: string[] }"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "subscription_id": "sub_01HZ...",
                  "webhook_url": "https://example.com/hooks/crime",
                  "created_at": "2026-06-03T15:49:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    },
    "/v1/executive-risk": {
      "get": {
        "operationId": "get-v1-executive-risk",
        "summary": "Executive protection risk package",
        "description": "Aggregated risk profile for a principal's home, office, and travel itinerary. Includes scores, recent incidents, and trend deltas.",
        "tags": [
          "v1 (planned)",
          "Enterprise"
        ],
        "x-status": "planned",
        "x-plans": [
          "Enterprise"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "principal_id",
            "in": "query",
            "required": true,
            "description": "Enterprise-defined principal identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "principal_id": "P-001",
                  "locations": [
                    {
                      "label": "Home",
                      "lat": 39.41,
                      "lon": -76.6,
                      "score": 82
                    },
                    {
                      "label": "Office",
                      "lat": 38.9,
                      "lon": -77.03,
                      "score": 64
                    }
                  ],
                  "generated_at": "2026-06-03T15:49:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Body: { errors: [string, ...] }"
          },
          "401": {
            "description": "Invalid or missing API key."
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After header included."
          },
          "5XX": {
            "description": "Server error."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "key",
        "description": "Per-customer API key passed as the `key` query parameter. Used by the current /crimes.json endpoint. Request one at https://spotcrime.io/request-access."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer token authentication used by the planned v1 surface. Header form: `Authorization: Bearer YOUR_KEY`."
      }
    }
  },
  "x-spotcrime": {
    "brand": "SpotCrime",
    "site": "https://spotcrime.io",
    "forAgents": "https://spotcrime.io/for-ai-agents",
    "llmsTxt": "https://spotcrime.io/llms.txt",
    "llmsFullTxt": "https://spotcrime.io/llms-full.txt",
    "contactEmail": "feedback@spotcrime.com"
  }
}