{
 "openapi": "3.1.0",
 "info": {
  "title": "Licensed Septic data API",
  "version": "1",
  "description": "Read-only static JSON. No key, no sign-up, no rate limit beyond the host's. A license or registration is claimed only when a listing carries a \"licenses\" entry. An empty \"licenses\" array never means unlicensed or unregistered."
 },
 "servers": [
  {
   "url": "https://licensedseptic.com"
  }
 ],
 "externalDocs": {
  "description": "Sources, filters and endpoint notes",
  "url": "https://licensedseptic.com/data/"
 },
 "paths": {
  "/api/v1/index.json": {
   "get": {
    "operationId": "getIndex",
    "summary": "Counts, sources and the endpoint list",
    "responses": {
     "200": {
      "description": "Site totals and endpoints",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/states.json": {
   "get": {
    "operationId": "listStates",
    "summary": "Every state with counts and whether a state list is loaded",
    "responses": {
     "200": {
      "description": "States",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "type": "object",
          "properties": {
           "code": {
            "type": "string",
            "description": "Two-letter code."
           },
           "name": {
            "type": "string",
            "description": "State name."
           },
           "url": {
            "type": "string",
            "description": "State page."
           },
           "api": {
            "type": "string",
            "description": "State listings as JSON."
           },
           "listings": {
            "type": "integer"
           },
           "towns": {
            "type": "integer"
           },
           "licenseCheck": {
            "type": "boolean"
           },
           "licenseSource": {
            "type": [
             "object",
             "null"
            ]
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/states/{code}.json": {
   "get": {
    "operationId": "getState",
    "summary": "Every listing in one state, with its license or registration records",
    "parameters": [
     {
      "name": "code",
      "in": "path",
      "required": true,
      "description": "Two-letter state code, lowercase.",
      "schema": {
       "type": "string",
       "enum": [
        "al",
        "ak",
        "az",
        "ar",
        "ca",
        "co",
        "ct",
        "de",
        "fl",
        "ga",
        "hi",
        "id",
        "il",
        "in",
        "ia",
        "ks",
        "ky",
        "la",
        "me",
        "md",
        "ma",
        "mi",
        "mn",
        "ms",
        "mo",
        "mt",
        "ne",
        "nv",
        "nh",
        "nj",
        "nm",
        "ny",
        "nc",
        "nd",
        "oh",
        "ok",
        "or",
        "pa",
        "ri",
        "sc",
        "sd",
        "tn",
        "tx",
        "ut",
        "vt",
        "va",
        "wa",
        "wv",
        "wi",
        "wy"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "State listings",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "state": {
           "type": "string",
           "description": "Two-letter code."
          },
          "name": {
           "type": "string",
           "description": "State name."
          },
          "url": {
           "type": "string",
           "description": "State page."
          },
          "licenseCheck": {
           "type": "boolean"
          },
          "licenseSource": {
           "type": [
            "object",
            "null"
           ]
          },
          "dataBuiltLocalDate": {
           "type": "string",
           "description": "Build day, US Pacific, YYYY-MM-DD."
          },
          "listings": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Listing"
           }
          },
          "recordsWithoutListing": {
           "type": "array",
           "description": "Records on the state list that have no listing here. Filled only for a list that covers other trades.",
           "items": {
            "type": "object",
            "properties": {
             "kind": {
              "type": "string",
              "description": "license or registration."
             },
             "number": {
              "type": "string",
              "description": "As printed on the list."
             },
             "nameOnList": {
              "type": "string",
              "description": "As printed on the list."
             },
             "town": {
              "type": [
               "string",
               "null"
              ],
              "description": "Town on the list."
             },
             "county": {
              "type": [
               "string",
               "null"
              ],
              "description": "County on the list."
             }
            }
           }
          }
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/zip/{prefix}.json": {
   "get": {
    "operationId": "getZipShard",
    "summary": "ZIP codes that share their first two digits, each mapped to the nearest page that lists companies",
    "parameters": [
     {
      "name": "prefix",
      "in": "path",
      "required": true,
      "description": "First two digits of the ZIP code.",
      "schema": {
       "type": "string",
       "pattern": "^[0-9]{2}$"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Object keyed by 5-digit ZIP. Value: [page path, miles to it]. The page is the nearest town page within 60 miles. Where there is none, it is the page that shows the nearest mapped company. A ZIP is absent when the Census ZIP table lacks it and no listing uses it (a PO box ZIP, for example), or when no mapped listing sits within 60 miles.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "additionalProperties": {
          "type": "array",
          "prefixItems": [
           {
            "type": "string"
           },
           {
            "type": "number"
           }
          ]
         }
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/cities.json": {
   "get": {
    "operationId": "listTowns",
    "summary": "Every town page with coordinates",
    "responses": {
     "200": {
      "description": "Array of [name, state code, path, lat, lon, listings in town, state name].",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "type": "array"
         }
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "Listing": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "description": "Stable ID."
     },
     "name": {
      "type": "string",
      "description": "Company name."
     },
     "url": {
      "type": [
       "string",
       "null"
      ],
      "description": "Company page on this site. Null when the listing has no page of its own."
     },
     "city": {
      "type": [
       "string",
       "null"
      ],
      "description": "Town."
     },
     "county": {
      "type": [
       "string",
       "null"
      ],
      "description": "County, where known."
     },
     "state": {
      "type": "string",
      "description": "Two-letter state code."
     },
     "zip": {
      "type": [
       "string",
       "null"
      ],
      "description": "ZIP code."
     },
     "street": {
      "type": [
       "string",
       "null"
      ],
      "description": "Street address. Always null for a listing that comes only from a state record."
     },
     "phone": {
      "type": [
       "string",
       "null"
      ],
      "description": "Phone in +1 format."
     },
     "website": {
      "type": [
       "string",
       "null"
      ],
      "description": "The company's own website."
     },
     "lat": {
      "type": [
       "number",
       "null"
      ]
     },
     "lon": {
      "type": [
       "number",
       "null"
      ]
     },
     "source": {
      "type": "string",
      "description": "Where the listing comes from: Overture Maps, or a state license or registration record."
     },
     "licenses": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/License"
      },
      "description": "Empty when no state record was matched. Empty never means unlicensed or unregistered."
     }
    }
   },
   "License": {
    "type": "object",
    "description": "One record on a state license or registration list that we matched to this listing.",
    "properties": {
     "state": {
      "type": "string",
      "description": "Two-letter code of the state that issued it."
     },
     "kind": {
      "type": "string",
      "description": "What the state calls it: license or registration.",
      "enum": [
       "license",
       "registration"
      ]
     },
     "number": {
      "type": "string",
      "description": "License, registration or permit number as printed on the list."
     },
     "type": {
      "type": "string",
      "description": "Type as printed on the list."
     },
     "agency": {
      "type": "string",
      "description": "The agency that publishes the list."
     },
     "nameOnList": {
      "type": "string",
      "description": "Company name as printed on the list."
     },
     "issued": {
      "type": [
       "string",
       "null"
      ],
      "description": "Issue date as printed. Null when the list has none."
     },
     "expires": {
      "type": [
       "string",
       "null"
      ],
      "description": "Expiry date as printed. Null when the list has none."
     },
     "expiredOnList": {
      "type": "boolean",
      "description": "True when the printed expiry date had passed on the day we built the data."
     },
     "listAsOf": {
      "type": [
       "string",
       "null"
      ],
      "description": "The date printed on the list."
     },
     "listRetrievedLocalDate": {
      "type": "string",
      "description": "The day we downloaded the list, US Pacific, YYYY-MM-DD."
     },
     "listUrl": {
      "type": "string",
      "description": "Where the list is published."
     },
     "matchedBy": {
      "type": "string",
      "description": "How the record was tied to the listing: phone, name, or from the state record itself."
     }
    }
   }
  }
 }
}
