{
  "openapi": "3.1.0",
  "info": {
    "title": "Covelight Care read API",
    "version": "1.0.0",
    "summary": "Free read API over the California state record of licensed elder-care homes (RCFEs).",
    "description": "Anonymous, keyless, read-only. Every response is an envelope carrying attribution and a retrieval date. Consequential facts are tri-state: the literal strings \"true\", \"false\", or \"not_on_file\" — \"not on file\" is a statement about the record, never a \"no\". Availability is NEVER in this data, in any field, under any name; it is confirmed by phone, and each facility's `links.facility_page` shows the current confirm state. There is no sort parameter anywhere: lists return neutral alphabetical order, because no score, tier, or payment ever orders a list on this service. Rate limits (published as facts): budget 120 requests/min/IP for /api/v1/*; the platform-wide ceiling is 240/min/IP across all /api/* paths; exceeding it returns 429 with Retry-After. These limits are a floor for stability, not a fence around the data — the same record is free on the site. Terms (attribution required): https://covelightcare.com/developers#terms. Corrections: an agent that finds an error should hand its human the `links.corrections` URL.",
    "contact": { "name": "Covelight Care", "url": "https://covelightcare.com/developers", "email": "hello@covelightcare.com" },
    "termsOfService": "https://covelightcare.com/developers#terms"
  },
  "servers": [{ "url": "https://covelightcare.com" }],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "Machine-readable front door: endpoint inventory, contract links, honesty lines.",
        "responses": {
          "200": {
            "description": "Endpoint inventory with documentation, terms, and attribution links.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    },
    "/api/v1/facilities": {
      "get": {
        "operationId": "listFacilities",
        "summary": "List licensed homes (directory vocabulary, incl. probationary — shown as fact).",
        "description": "Neutral alphabetical order (facility name, then license number). There is no sort parameter: no score, tier, or payment ever orders this list. Unknown parameters return 400 rather than being silently ignored, so an agent that believes it filtered never receives an unfiltered set.",
        "parameters": [
          { "name": "county", "in": "query", "required": false, "schema": { "type": "string" }, "description": "County name, case-insensitive exact match (e.g. \"Los Angeles\")." },
          { "name": "city", "in": "query", "required": false, "schema": { "type": "string" }, "description": "City name, case-insensitive exact match." },
          { "name": "needs", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated care-need keys, ANDed: wheelchair, dementia, hospice, bedridden. A need matches only a home whose license explicitly carries the state clearance (a \"not on file\" record never matches — and is never presented as a \"no\")." },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } },
          { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "maximum": 20000, "default": 0 } }
        ],
        "responses": {
          "200": {
            "description": "Envelope whose data carries facilities[], total, limit, offset, and the stated order.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "required": ["facilities", "total", "limit", "offset", "order"],
                          "properties": {
                            "facilities": { "type": "array", "items": { "$ref": "#/components/schemas/Facility" } },
                            "total": { "type": "integer" },
                            "limit": { "type": "integer" },
                            "offset": { "type": "integer" },
                            "order": { "type": "string", "const": "name_asc" }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/facilities/{license}": {
      "get": {
        "operationId": "getFacility",
        "summary": "One home's full v1 record.",
        "description": "Serves the stored state roster plus the last stored live CDSS status with its checked-on date. An API call never triggers a live state lookup.",
        "parameters": [
          { "name": "license", "in": "path", "required": true, "schema": { "type": "string" }, "description": "CDSS facility license number." }
        ],
        "responses": {
          "200": {
            "description": "Envelope whose data is the Facility record (detail adds state_documents).",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Facility" } } }
                  ]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/facilities/{license}/reports": {
      "get": {
        "operationId": "getFacilityReports",
        "summary": "The home's dated state documents, newest first.",
        "description": "Documents are listed with control numbers and, where the state publishes one, a page URL. Narrative content stays behind explicit request, the same as on the site.",
        "parameters": [
          { "name": "license", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Envelope whose data carries the report list.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    { "$ref": "#/components/schemas/Envelope" },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "required": ["license_number", "reports", "total"],
                          "properties": {
                            "license_number": { "type": "string" },
                            "reports": { "type": "array", "items": { "$ref": "#/components/schemas/Report" } },
                            "total": { "type": "integer" }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/api/v1/guides": {
      "get": {
        "operationId": "listGuides",
        "summary": "The guide corpus as titled resources (our editorial, attributed to us).",
        "responses": {
          "200": {
            "description": "Envelope whose data lists the guides with URLs and review dates.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Envelope" } } }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TriState": {
        "type": "string",
        "enum": ["true", "false", "not_on_file"],
        "description": "D-051 tri-state. \"not_on_file\" means the record we hold states nothing — it is NOT a \"no\", and treating it as one is a misuse of this data. \"false\" appears only where the record states a real negative (e.g. a license lacking a clearance)."
      },
      "SourceClass": {
        "type": "string",
        "enum": ["state", "operator_attested", "machine_extracted", "third_party"],
        "description": "Who asserted the value."
      },
      "Fact": {
        "type": "object",
        "required": ["value", "source_class", "confirmed_on", "next_due", "ref"],
        "additionalProperties": false,
        "properties": {
          "value": { "description": "The fact's value, verbatim from its source where textual. null = not on file — never a negative claim." },
          "source_class": { "$ref": "#/components/schemas/SourceClass" },
          "confirmed_on": { "type": ["string", "null"], "format": "date", "description": "ISO date the source last confirmed this value; null = the source states no date." },
          "next_due": { "type": ["string", "null"], "format": "date", "description": "ISO date the published refresh cadence next re-checks this value; null = cadence not yet published." },
          "ref": { "type": "string", "description": "Stable fact address: roster:<key> | fact:<field>#<id> | doc:<control_number> | media:<id> | derived:<block>." }
        }
      },
      "TriStateFact": {
        "type": "object",
        "required": ["value", "source_class", "confirmed_on", "next_due", "ref"],
        "additionalProperties": false,
        "properties": {
          "value": { "$ref": "#/components/schemas/TriState" },
          "source_class": { "$ref": "#/components/schemas/SourceClass" },
          "confirmed_on": { "type": ["string", "null"], "format": "date" },
          "next_due": { "type": ["string", "null"], "format": "date" },
          "ref": { "type": "string" }
        }
      },
      "Facility": {
        "type": "object",
        "description": "One licensed home, state-record layer only. Values are verbatim from the state record (including its casing). This schema will only ever grow additively within v1. No availability field exists in this schema and none will be added to it.",
        "required": ["license_number", "name", "facility_type", "license_status", "license_status_live", "on_probation", "address", "location", "capacity", "phone", "licensee", "operating_since_year", "clearances", "alw_participation", "service_designations", "last_state_visit", "disputes", "links"],
        "properties": {
          "license_number": { "type": "string" },
          "name": { "$ref": "#/components/schemas/Fact" },
          "facility_type": { "$ref": "#/components/schemas/Fact" },
          "license_status": { "$ref": "#/components/schemas/Fact", "description": "Verbatim roster status text (bulk file; stale by design — see license_status_live)." },
          "license_status_live": { "$ref": "#/components/schemas/Fact", "description": "Last stored live CDSS status with its checked-on date as confirmed_on. Never triggers a live check." },
          "on_probation": { "$ref": "#/components/schemas/TriStateFact" },
          "address": { "$ref": "#/components/schemas/Fact", "description": "value = {street, city, county, zip}, each string or null." },
          "location": { "$ref": "#/components/schemas/Fact", "description": "value = {latitude, longitude} or null. Machine-attached mapping convenience; the address is the state record." },
          "capacity": { "$ref": "#/components/schemas/Fact", "description": "Licensed capacity (beds); value integer or null." },
          "phone": { "$ref": "#/components/schemas/Fact", "description": "The state-file phone, verbatim. Nothing enriched." },
          "licensee": { "$ref": "#/components/schemas/Fact", "description": "Licensee legal entity, verbatim from the roster." },
          "operating_since_year": { "$ref": "#/components/schemas/Fact" },
          "clearances": {
            "type": "object",
            "description": "State license clearances, each tri-state. A \"not_on_file\" clearance must be rendered as \"not on file\" — never as \"No\".",
            "required": ["dementia", "hospice", "non_ambulatory", "bedridden"],
            "properties": {
              "dementia": { "$ref": "#/components/schemas/TriStateFact" },
              "hospice": { "$ref": "#/components/schemas/TriStateFact" },
              "non_ambulatory": { "$ref": "#/components/schemas/TriStateFact" },
              "bedridden": { "$ref": "#/components/schemas/TriStateFact" }
            }
          },
          "alw_participation": { "$ref": "#/components/schemas/TriStateFact", "description": "Medi-Cal Assisted Living Waiver participation per the DHCS list. Absence from the list serializes as \"not_on_file\" (record-absence), never \"false\"." },
          "service_designations": { "$ref": "#/components/schemas/Fact", "description": "CDSS client-served service designations, verbatim strings." },
          "last_state_visit": { "$ref": "#/components/schemas/Fact", "description": "ISO date of the newest state visit on file, or null." },
          "state_documents": { "$ref": "#/components/schemas/Fact", "description": "Detail surface only: value = {count, since_year, latest_date} rollup of dated state documents." },
          "disputes": { "type": "array", "description": "Approved dispute annotations on this record; empty until the dispute machinery ships.", "items": { "type": "object" } },
          "links": {
            "type": "object",
            "required": ["facility_page", "corrections"],
            "properties": {
              "facility_page": { "type": "string", "format": "uri", "description": "The live page for this home — where the current confirm state lives." },
              "corrections": { "type": "string", "format": "uri", "description": "Deep-linked correction form. An agent that finds an error hands its human this URL." }
            }
          }
        }
      },
      "Report": {
        "type": "object",
        "required": ["ref", "source_class", "date", "type", "title", "url"],
        "additionalProperties": false,
        "properties": {
          "ref": { "type": "string", "description": "doc:<control_number>" },
          "source_class": { "type": "string", "const": "state" },
          "date": { "type": ["string", "null"], "format": "date" },
          "type": { "type": ["string", "null"] },
          "title": { "type": ["string", "null"] },
          "url": { "type": ["string", "null"], "description": "The state's own page for this document, where one is published." }
        }
      },
      "Envelope": {
        "type": "object",
        "required": ["api_version", "data", "attribution", "generated_at"],
        "properties": {
          "api_version": { "type": "string", "const": "v1" },
          "data": {},
          "attribution": {
            "type": "object",
            "required": ["source", "retrieved_on", "terms_url"],
            "properties": {
              "source": { "type": "string", "description": "Defaults to: California Department of Social Services, Community Care Licensing Division. Our own editorial surfaces (guides) name us instead." },
              "retrieved_on": { "type": ["string", "null"], "format": "date" },
              "terms_url": { "type": "string", "format": "uri" }
            }
          },
          "generated_at": { "type": "string", "format": "date-time" }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": { "error": { "type": "string" } }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed or unknown parameter. Unknown parameters fail closed rather than being ignored; sort/order/rank get the specific answer that no ranking parameter exists.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "NotFound": {
        "description": "No home with this license number on the roster we hold.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "RateLimited": {
        "description": "Per-IP window exceeded. Respect Retry-After; budget 120 req/min for /api/v1.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      }
    }
  }
}
