{
    "openapi": "3.1.0",
    "info": {
        "title": "BrandShyp San Antonio Crime Data API",
        "version": "1.0.0",
        "summary": "Reconciled SAPD reported offences, aggregated by ZIP code.",
        "description": "A read-only public API over 42+ months of San Antonio Police Department NIBRS Group A offences, cleaned and aggregated to ZIP code. It serves the same reconciled dataset that powers the map at https://brandshyp.org/san-antonio-crime-map/.\n\nThe cube is rebuilt monthly from the City of San Antonio open-data portal and reconciled against an independent row count at build time: it is not published if the aggregate disagrees with the source. The finest geography the source publishes is the ZIP code; there is no latitude/longitude or street address in the data.\n\nData is licensed CC BY 4.0 (City of San Antonio). Cleaning, aggregation, and analysis by BrandShyp.",
        "contact": {
            "name": "BrandShyp",
            "url": "https://brandshyp.org/contact-us/"
        },
        "license": {
            "name": "CC BY 4.0",
            "url": "https://creativecommons.org/licenses/by/4.0/"
        },
        "termsOfService": "https://brandshyp.org/terms-of-service/"
    },
    "externalDocs": {
        "description": "Human documentation and methodology",
        "url": "https://brandshyp.org/crime-data-api/"
    },
    "servers": [
        {
            "url": "https://brandshyp.org/api/v1",
            "description": "Production"
        }
    ],
    "security": [],
    "tags": [
        {
            "name": "discovery",
            "description": "Self-describing entry points"
        },
        {
            "name": "datasets",
            "description": "The offences data, in full"
        },
        {
            "name": "reference",
            "description": "Lookup tables"
        }
    ],
    "paths": {
        "/crime": {
            "get": {
                "operationId": "getDiscovery",
                "tags": [
                    "discovery"
                ],
                "summary": "Discovery document",
                "description": "A self-describing root document: coverage, provenance, the reconciliation guarantee, license, and links to every other endpoint.",
                "responses": {
                    "200": {
                        "description": "The discovery document.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DiscoveryDocument"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many requests. Public endpoints are rate-limited at the CDN edge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The dataset is temporarily unavailable.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/crime/offenses": {
            "get": {
                "operationId": "getOffences",
                "tags": [
                    "datasets"
                ],
                "summary": "The full offences cube (JSON)",
                "description": "Counts of reported offences by ZIP code, month, and offence type, with the category trees and the pre-computed analysis series (day-of-week, seasonal, peer-city benchmark, timing). This is the complete dataset in a single compact document.",
                "responses": {
                    "200": {
                        "description": "The offences cube.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OffencesCube"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many requests. Public endpoints are rate-limited at the CDN edge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The dataset is temporarily unavailable.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/crime/offenses.csv": {
            "get": {
                "operationId": "getOffencesCsv",
                "tags": [
                    "datasets"
                ],
                "summary": "The offences cube (tidy CSV)",
                "description": "The same cube as a tidy, one-row-per-(ZIP, month, offence) CSV, for spreadsheets and data tools.",
                "responses": {
                    "200": {
                        "description": "The offences cube as CSV.",
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "type": "string"
                                },
                                "example": "zip,month,offence,group,crime_against,offences\n78201,2023-01,\"Aggravated Assault\",Assault,Person,12"
                            }
                        }
                    },
                    "429": {
                        "description": "Too many requests. Public endpoints are rate-limited at the CDN edge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/crime/geo": {
            "get": {
                "operationId": "getGeo",
                "tags": [
                    "reference"
                ],
                "summary": "ZIP boundary geometry",
                "description": "Pre-projected ZIP-boundary SVG paths (flat, build-time projection), centroids, and area in square miles. Used to draw the choropleth without a map library.",
                "responses": {
                    "200": {
                        "description": "ZIP geometry.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/GeoDocument"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many requests. Public endpoints are rate-limited at the CDN edge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The dataset is temporarily unavailable.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/crime/zips": {
            "get": {
                "operationId": "getZips",
                "tags": [
                    "reference"
                ],
                "summary": "ZIP directory",
                "description": "One row per ZIP code: the general \"part of town\" area name, U.S. Census ACS population, and area in square miles. Population is null where the ACS has none (for example PO-box ZIPs).",
                "responses": {
                    "200": {
                        "description": "The ZIP directory.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/ZipDirectory"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many requests. Public endpoints are rate-limited at the CDN edge.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The dataset is temporarily unavailable.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "DiscoveryDocument": {
                "type": "object",
                "properties": {
                    "api": {
                        "type": "string"
                    },
                    "version": {
                        "type": "string",
                        "examples": [
                            "v1"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "examples": [
                            "stable"
                        ]
                    },
                    "description": {
                        "type": "string"
                    },
                    "generated": {
                        "type": "string",
                        "description": "When the dataset was last built (human-readable, America/Chicago)."
                    },
                    "coverage": {
                        "type": "object",
                        "properties": {
                            "first_month": {
                                "type": "string",
                                "examples": [
                                    "2023-01"
                                ]
                            },
                            "last_month": {
                                "type": "string",
                                "examples": [
                                    "2026-06"
                                ]
                            },
                            "n_months": {
                                "type": "integer"
                            },
                            "n_zips": {
                                "type": "integer"
                            },
                            "n_cells": {
                                "type": "integer"
                            },
                            "geography": {
                                "type": "string"
                            },
                            "measure": {
                                "type": "string"
                            }
                        }
                    },
                    "integrity": {
                        "type": "object",
                        "description": "The reconcile-or-refuse guarantee and the row accounting.",
                        "properties": {
                            "method": {
                                "type": "string",
                                "examples": [
                                    "reconcile-or-refuse"
                                ]
                            },
                            "note": {
                                "type": "string"
                            },
                            "rows_source": {
                                "type": [
                                    "integer",
                                    "null"
                                ]
                            },
                            "rows_mapped": {
                                "type": [
                                    "integer",
                                    "null"
                                ]
                            },
                            "rows_excluded": {
                                "type": [
                                    "integer",
                                    "null"
                                ]
                            }
                        }
                    },
                    "source": {
                        "type": "object",
                        "description": "Upstream source metadata (name, url, license, scope, population basis, row counts)."
                    },
                    "license": {
                        "$ref": "#/components/schemas/License"
                    },
                    "endpoints": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        }
                    },
                    "documentation": {
                        "type": "string",
                        "format": "uri"
                    },
                    "openapi": {
                        "type": "string",
                        "format": "uri"
                    },
                    "methodology": {
                        "type": "string",
                        "format": "uri"
                    },
                    "versioning": {
                        "type": "string"
                    }
                }
            },
            "OffencesCube": {
                "type": "object",
                "description": "The complete offences cube. Arrays are index-aligned: zips[i] has population pop[i]. Cells encode [zipIndex, codeIndex, monthIndex, count].",
                "properties": {
                    "generated": {
                        "type": "string"
                    },
                    "source": {
                        "type": "object"
                    },
                    "months": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "YYYY-MM, chronological."
                    },
                    "zips": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "pop": {
                        "type": "array",
                        "items": {
                            "type": [
                                "integer",
                                "null"
                            ]
                        },
                        "description": "Index-aligned to zips[]."
                    },
                    "codes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Offence-type labels."
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "NIBRS group labels."
                    },
                    "againsts": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "Crime-against categories (Person/Property/Society)."
                    },
                    "cells": {
                        "type": "array",
                        "description": "Non-zero counts. Each cell is [zipIndex, codeIndex, monthIndex, offences].",
                        "items": {
                            "type": "array",
                            "items": {
                                "type": "integer"
                            },
                            "minItems": 4,
                            "maxItems": 4
                        }
                    },
                    "dow": {
                        "type": "object",
                        "description": "Day-of-week distribution (by crime-against)."
                    },
                    "dowg": {
                        "type": "object",
                        "description": "Day-of-week + seasonal distribution by NIBRS group."
                    },
                    "fbi": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "FBI peer-city benchmark (rates per 100k), or null if unavailable."
                    },
                    "calls": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Violent-crime 911-call timing grid (7 days x 24 hours), or null."
                    },
                    "has_arrests": {
                        "type": "boolean"
                    }
                }
            },
            "GeoDocument": {
                "type": "object",
                "properties": {
                    "viewBox": {
                        "type": "string"
                    },
                    "zips": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "object",
                            "properties": {
                                "d": {
                                    "type": "string",
                                    "description": "SVG path."
                                },
                                "cx": {
                                    "type": "string"
                                },
                                "cy": {
                                    "type": "string"
                                },
                                "name": {
                                    "type": "string"
                                },
                                "area": {
                                    "type": "string",
                                    "description": "General part-of-town name."
                                },
                                "sqmi": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            },
            "ZipDirectory": {
                "type": "object",
                "properties": {
                    "count": {
                        "type": "integer"
                    },
                    "note": {
                        "type": "string"
                    },
                    "attribution": {
                        "type": "string"
                    },
                    "zips": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ZipEntry"
                        }
                    }
                }
            },
            "ZipEntry": {
                "type": "object",
                "required": [
                    "zip"
                ],
                "properties": {
                    "zip": {
                        "type": "string",
                        "examples": [
                            "78205"
                        ]
                    },
                    "area": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "General part-of-town name.",
                        "examples": [
                            "Downtown"
                        ]
                    },
                    "population": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "U.S. Census ACS 5-year (2023). Null where unavailable."
                    },
                    "sq_miles": {
                        "type": [
                            "number",
                            "null"
                        ]
                    }
                }
            },
            "License": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "attribution": {
                        "type": "string"
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "error": {
                        "type": "string"
                    },
                    "status": {
                        "type": "integer"
                    }
                }
            }
        }
    }
}