{
 "openapi": "3.0.3",
 "info": {
  "title": "KSA Land Data \u2014 Saudi Real Estate Transactions API",
  "version": "1.0.0",
  "description": "Registered Saudi property sales (Ministry of Justice deeds, 2020-present): quarterly aggregates by region/city/district and transaction-level records. Contains information from Ministry of Justice real-estate transactions (https://open.data.gov.sa), published on the Saudi Open Data Portal and in the Ministry's real-estate transactions report (moj.gov.sa), which is made available under the Saudi Open Data License (ODC Attribution License) (https://open.data.gov.sa/odp-public/static/ar/assets/Open_Data_License_Ar.pdf). Get a free key at https://ksalanddata.com/docs",
  "contact": {
   "url": "https://ksalanddata.com/contact"
  }
 },
 "servers": [
  {
   "url": "https://ksalanddata.com/v1"
  }
 ],
 "components": {
  "securitySchemes": {
   "ApiKey": {
    "type": "apiKey",
    "in": "header",
    "name": "x-api-key"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "string"
     },
     "see": {
      "type": "string"
     },
     "tier": {
      "type": "string"
     },
     "cap": {
      "type": "integer"
     }
    }
   },
   "Meta": {
    "type": "object",
    "required": [
     "dataset",
     "records",
     "quarters",
     "regions",
     "cities",
     "source",
     "license",
     "attribution",
     "built"
    ],
    "properties": {
     "dataset": {
      "type": "string"
     },
     "records": {
      "type": "integer",
      "minimum": 0
     },
     "quarters": {
      "type": "array",
      "items": {
       "type": "string",
       "pattern": "^[0-9]{4}Q[1-4]$"
      }
     },
     "regions": {
      "type": "integer",
      "minimum": 0
     },
     "cities": {
      "type": "integer",
      "minimum": 0
     },
     "source": {
      "type": "string"
     },
     "license": {
      "type": "string"
     },
     "attribution": {
      "type": "string"
     },
     "built": {
      "type": "string",
      "description": "Day the data was built (UTC), YYYY-MM-DD."
     }
    }
   },
   "StatBucket": {
    "type": "object",
    "required": [
     "n",
     "total_sar",
     "median_price",
     "median_psm",
     "median_area"
    ],
    "properties": {
     "n": {
      "type": "integer",
      "description": "Number of transactions."
     },
     "total_sar": {
      "type": "integer",
      "description": "Total price of those transactions, SAR."
     },
     "median_price": {
      "type": "number",
      "description": "SAR."
     },
     "median_psm": {
      "type": "number",
      "nullable": true,
      "description": "Median price per square metre, SAR; null when no row has an area."
     },
     "median_area": {
      "type": "number",
      "nullable": true,
      "description": "Median area in square metres; null for district aggregates."
     }
    }
   },
   "RegionStat": {
    "allOf": [
     {
      "$ref": "#/components/schemas/StatBucket"
     },
     {
      "type": "object",
      "required": [
       "name_en",
       "name_ar"
      ],
      "properties": {
       "name_en": {
        "type": "string"
       },
       "name_ar": {
        "type": "string"
       }
      }
     }
    ]
   },
   "CityStat": {
    "allOf": [
     {
      "$ref": "#/components/schemas/StatBucket"
     },
     {
      "type": "object",
      "required": [
       "name_en",
       "name_ar",
       "region"
      ],
      "properties": {
       "name_en": {
        "type": "string"
       },
       "name_ar": {
        "type": "string"
       },
       "region": {
        "type": "string",
        "description": "Region slug."
       }
      }
     }
    ]
   },
   "RegionStatsResponse": {
    "type": "object",
    "required": [
     "quarter",
     "classification",
     "regions"
    ],
    "properties": {
     "quarter": {
      "type": "string"
     },
     "classification": {
      "type": "string",
      "enum": [
       "all",
       "residential",
       "commercial",
       "agricultural",
       "mixed"
      ]
     },
     "regions": {
      "type": "object",
      "description": "Keyed by region slug. A region with no data for the quarter and classification is left out.",
      "additionalProperties": {
       "$ref": "#/components/schemas/RegionStat"
      }
     }
    }
   },
   "CityStatsResponse": {
    "type": "object",
    "required": [
     "quarter",
     "classification",
     "cities"
    ],
    "properties": {
     "quarter": {
      "type": "string"
     },
     "classification": {
      "type": "string",
      "enum": [
       "all",
       "residential",
       "commercial",
       "agricultural",
       "mixed"
      ]
     },
     "cities": {
      "type": "object",
      "description": "Keyed by city slug. A city with no data for the quarter and classification is left out.",
      "additionalProperties": {
       "$ref": "#/components/schemas/CityStat"
      }
     }
    }
   },
   "DistrictStatsResponse": {
    "type": "object",
    "required": [
     "city",
     "quarter",
     "classification",
     "districts"
    ],
    "properties": {
     "city": {
      "type": "string",
      "description": "City slug."
     },
     "quarter": {
      "type": "string"
     },
     "classification": {
      "type": "string",
      "enum": [
       "all",
       "residential",
       "commercial",
       "agricultural",
       "mixed"
      ]
     },
     "districts": {
      "type": "object",
      "description": "Keyed by Arabic district name.",
      "additionalProperties": {
       "$ref": "#/components/schemas/StatBucket"
      }
     }
    }
   },
   "Transaction": {
    "type": "object",
    "required": [
     "date",
     "region",
     "city",
     "district_ar",
     "classification",
     "price_sar",
     "ref_no"
    ],
    "properties": {
     "date": {
      "type": "string",
      "description": "Deed date, YYYY-MM-DD."
     },
     "region": {
      "type": "string",
      "description": "Region slug."
     },
     "city": {
      "type": "string",
      "description": "City slug."
     },
     "district_ar": {
      "type": "string"
     },
     "classification": {
      "type": "string",
      "enum": [
       "residential",
       "commercial",
       "agricultural",
       "mixed",
       "industrial"
      ]
     },
     "property_type": {
      "type": "string",
      "nullable": true
     },
     "properties_count": {
      "type": "integer"
     },
     "price_sar": {
      "type": "number"
     },
     "area_sqm": {
      "type": "number",
      "nullable": true
     },
     "price_per_sqm": {
      "type": "number",
      "nullable": true
     },
     "ref_no": {
      "type": "string"
     }
    }
   },
   "TransactionsResponse": {
    "type": "object",
    "required": [
     "city",
     "quarter",
     "count",
     "offset",
     "transactions"
    ],
    "properties": {
     "city": {
      "type": "string"
     },
     "quarter": {
      "type": "string"
     },
     "count": {
      "type": "integer"
     },
     "offset": {
      "type": "integer"
     },
     "transactions": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Transaction"
      }
     }
    }
   },
   "KeyIssued": {
    "type": "object",
    "required": [
     "key",
     "recovery_code",
     "tier",
     "monthly_quota",
     "note"
    ],
    "properties": {
     "key": {
      "type": "string"
     },
     "recovery_code": {
      "type": "string"
     },
     "tier": {
      "type": "string"
     },
     "monthly_quota": {
      "type": "integer"
     },
     "note": {
      "type": "string"
     }
    }
   },
   "Usage": {
    "type": "object",
    "required": [
     "tier",
     "month",
     "monthly_quota",
     "used",
     "remaining",
     "days",
     "used_estimate",
     "remaining_estimate",
     "note"
    ],
    "properties": {
     "tier": {
      "type": "string"
     },
     "month": {
      "type": "string",
      "description": "YYYYMM (UTC)."
     },
     "monthly_quota": {
      "type": "integer"
     },
     "used": {
      "type": "integer",
      "nullable": true
     },
     "remaining": {
      "type": "integer",
      "nullable": true
     },
     "days": {
      "type": "array",
      "items": {
       "type": "object",
       "required": [
        "day",
        "requests"
       ],
       "properties": {
        "day": {
         "type": "string"
        },
        "requests": {
         "type": "integer"
        }
       }
      }
     },
     "used_estimate": {
      "type": "integer"
     },
     "remaining_estimate": {
      "type": "integer"
     },
     "keys": {
      "type": "object",
      "description": "Team accounts only.",
      "properties": {
       "allowed": {
        "type": "integer"
       },
       "in_use": {
        "type": "integer"
       }
      }
     },
     "note": {
      "type": "string"
     }
    }
   },
   "LogsResponse": {
    "type": "object",
    "required": [
     "count",
     "retention_days",
     "next_cursor",
     "logs"
    ],
    "properties": {
     "count": {
      "type": "integer"
     },
     "retention_days": {
      "type": "integer"
     },
     "next_cursor": {
      "type": "integer",
      "nullable": true
     },
     "logs": {
      "type": "array",
      "items": {
       "type": "object",
       "required": [
        "time",
        "method",
        "endpoint",
        "query",
        "status",
        "ms"
       ],
       "properties": {
        "time": {
         "type": "string",
         "format": "date-time"
        },
        "method": {
         "type": "string"
        },
        "endpoint": {
         "type": "string"
        },
        "query": {
         "type": "string"
        },
        "status": {
         "type": "integer"
        },
        "ms": {
         "type": "integer"
        }
       }
      }
     }
    }
   },
   "FilesResponse": {
    "type": "object",
    "required": [
     "release",
     "built",
     "first_quarter",
     "latest_quarter",
     "records",
     "dictionary",
     "files",
     "note"
    ],
    "properties": {
     "release": {
      "type": "string"
     },
     "built": {
      "type": "string"
     },
     "first_quarter": {
      "type": "string"
     },
     "latest_quarter": {
      "type": "string"
     },
     "records": {
      "type": "integer"
     },
     "dictionary": {
      "type": "string"
     },
     "files": {
      "type": "array",
      "items": {
       "type": "object",
       "required": [
        "path",
        "url",
        "bytes",
        "sha256",
        "rows"
       ],
       "properties": {
        "path": {
         "type": "string"
        },
        "url": {
         "type": "string"
        },
        "bytes": {
         "type": "integer"
        },
        "sha256": {
         "type": "string"
        },
        "rows": {
         "type": "integer",
         "nullable": true
        }
       }
      }
     },
     "note": {
      "type": "string"
     }
    }
   },
   "MemberKeyList": {
    "type": "object",
    "required": [
     "allowed",
     "in_use",
     "members",
     "note"
    ],
    "properties": {
     "allowed": {
      "type": "integer"
     },
     "in_use": {
      "type": "integer"
     },
     "note": {
      "type": "string"
     },
     "members": {
      "type": "array",
      "items": {
       "type": "object",
       "required": [
        "id",
        "label",
        "key_start",
        "created"
       ],
       "properties": {
        "id": {
         "type": "string"
        },
        "label": {
         "type": "string",
         "nullable": true
        },
        "key_start": {
         "type": "string",
         "nullable": true
        },
        "created": {
         "type": "string",
         "nullable": true
        }
       }
      }
     }
    }
   },
   "MemberKeyCreated": {
    "type": "object",
    "required": [
     "key",
     "id",
     "label",
     "tier",
     "keys",
     "note"
    ],
    "properties": {
     "key": {
      "type": "string"
     },
     "id": {
      "type": "string"
     },
     "label": {
      "type": "string"
     },
     "tier": {
      "type": "string"
     },
     "keys": {
      "type": "object",
      "properties": {
       "allowed": {
        "type": "integer"
       },
       "in_use": {
        "type": "integer"
       }
      }
     },
     "note": {
      "type": "string"
     }
    }
   },
   "MemberKeyRotated": {
    "type": "object",
    "required": [
     "key",
     "id",
     "label",
     "note"
    ],
    "properties": {
     "key": {
      "type": "string"
     },
     "id": {
      "type": "string"
     },
     "label": {
      "type": "string"
     },
     "note": {
      "type": "string"
     }
    }
   },
   "MemberKeyRemoved": {
    "type": "object",
    "required": [
     "ok",
     "removed"
    ],
    "properties": {
     "ok": {
      "type": "boolean"
     },
     "removed": {
      "type": "string"
     }
    }
   }
  },
  "responses": {
   "Unauthorized": {
    "description": "Missing or invalid API key",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      },
      "example": {
       "error": "missing x-api-key"
      }
     }
    }
   },
   "QuotaExceeded": {
    "description": "Monthly quota exceeded",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      },
      "example": {
       "error": "monthly quota exceeded",
       "cap": 500,
       "tier": "free"
      }
     }
    }
   }
  }
 },
 "security": [
  {
   "ApiKey": []
  }
 ],
 "paths": {
  "/meta": {
   "get": {
    "operationId": "getMeta",
    "summary": "Coverage: quarters, counts",
    "security": [],
    "responses": {
     "200": {
      "description": "Dataset coverage and build metadata",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Meta"
        },
        "example": {
         "dataset": "moj-sales",
         "records": 1474665,
         "quarters": [
          "2020Q1",
          "2020Q2",
          "2020Q3",
          "2020Q4",
          "2021Q1",
          "2021Q2",
          "2021Q3",
          "2021Q4",
          "2022Q1",
          "2022Q2",
          "2022Q3",
          "2022Q4",
          "2023Q1",
          "2023Q2",
          "2023Q3",
          "2023Q4",
          "2024Q1",
          "2024Q2",
          "2024Q3",
          "2024Q4",
          "2025Q1",
          "2025Q2",
          "2025Q3",
          "2025Q4",
          "2026Q1",
          "2026Q2"
         ],
         "regions": 13,
         "cities": 175,
         "source": "Saudi Ministry of Justice via the Saudi Open Data Portal (open.data.gov.sa)",
         "license": "Saudi Open Data License (ODC Attribution License): https://open.data.gov.sa/odp-public/static/ar/assets/Open_Data_License_Ar.pdf",
         "attribution": "Contains information from Ministry of Justice real-estate transactions (https://open.data.gov.sa), published on the Saudi Open Data Portal and in the Ministry's real-estate transactions report (moj.gov.sa), which is made available under the Saudi Open Data License (ODC Attribution License) (https://open.data.gov.sa/odp-public/static/ar/assets/Open_Data_License_Ar.pdf).",
         "built": "2026-10-13"
        }
       }
      }
     }
    }
   }
  },
  "/keys": {
   "post": {
    "operationId": "createKey",
    "summary": "Create a free API key",
    "security": [],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "email": {
          "type": "string"
         }
        },
        "required": [
         "email"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Key issued. Both the key and the recovery code are shown once.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/KeyIssued"
        }
       }
      }
     },
     "400": {
      "description": "Invalid JSON or no valid email",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Daily key-issuance limit reached",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/stats/regions": {
   "get": {
    "operationId": "getRegionStats",
    "summary": "Quarterly aggregates for the 13 regions",
    "parameters": [
     {
      "name": "quarter",
      "in": "query",
      "schema": {
       "type": "string",
       "example": "2025Q4"
      }
     },
     {
      "name": "classification",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "all",
        "residential",
        "commercial",
        "agricultural",
        "mixed"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "n, total_sar, median_price, median_psm, median_area per region",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/RegionStatsResponse"
        }
       }
      }
     },
     "400": {
      "description": "Bad classification or quarter format",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     }
    }
   }
  },
  "/stats/cities": {
   "get": {
    "operationId": "getCityStats",
    "summary": "Quarterly aggregates per city",
    "parameters": [
     {
      "name": "region",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "city",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "quarter",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "classification",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "all",
        "residential",
        "commercial",
        "agricultural",
        "mixed"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "n, total_sar, median_price, median_psm, median_area per city",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CityStatsResponse"
        }
       }
      }
     },
     "400": {
      "description": "Bad classification or quarter format",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     }
    }
   }
  },
  "/stats/districts": {
   "get": {
    "operationId": "getDistrictStats",
    "summary": "District aggregates inside a city",
    "parameters": [
     {
      "name": "city",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "quarter",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "classification",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "all",
        "residential",
        "commercial",
        "agricultural",
        "mixed"
       ]
      }
     }
    ],
    "responses": {
     "200": {
      "description": "n, total_sar, median_price, median_psm per district (median_area is null)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/DistrictStatsResponse"
        }
       }
      }
     },
     "400": {
      "description": "Bad classification or quarter format; city missing",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "404": {
      "description": "No district data for this city",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     }
    }
   }
  },
  "/usage": {
   "get": {
    "operationId": "getUsage",
    "summary": "Your plan, monthly quota and exact usage this month (UTC), with a per-day breakdown",
    "responses": {
     "200": {
      "description": "Plan, quota and exact usage this month. used_estimate is the sampled counter the quota is enforced on; it can differ from used by a few requests. A call is counted from the next one.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Usage"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     }
    }
   }
  },
  "/logs": {
   "get": {
    "operationId": "getLogs",
    "summary": "Your request log for the last 30 days, newest first (never your key or IP address)",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "description": "1-500, default 100",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "since",
      "in": "query",
      "description": "ISO date or time (UTC), e.g. 2026-09-01",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "description": "next_cursor from the previous page",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Request log, newest first; next_cursor is null when there is no more",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/LogsResponse"
        }
       }
      }
     },
     "400": {
      "description": "Bad since",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     },
     "503": {
      "description": "Logs temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/export": {
   "get": {
    "operationId": "exportDataset",
    "summary": "Pro plan: the full dataset as one gzip-compressed CSV. Columns: https://ksalanddata.com/download/dictionary",
    "responses": {
     "200": {
      "description": "The full dataset as one gzip-compressed CSV",
      "headers": {
       "Content-Disposition": {
        "schema": {
         "type": "string"
        },
        "description": "Attachment filename"
       }
      },
      "content": {
       "application/gzip": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Pro plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Pack unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     }
    }
   }
  },
  "/transactions": {
   "get": {
    "operationId": "getTransactions",
    "summary": "Transaction-level records",
    "parameters": [
     {
      "name": "city",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "quarter",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "classification",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "residential",
        "commercial",
        "agricultural",
        "mixed",
        "industrial"
       ]
      },
      "description": "Exact match on the row's classification."
     },
     {
      "name": "district",
      "in": "query",
      "description": "Arabic district name as returned by /stats/districts. A leading \"\u062d\u064a\" and alef, ya and ta-marbuta spelling variants are ignored.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "min_price",
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "max_price",
      "in": "query",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "maximum": 1000
      }
     },
     {
      "name": "offset",
      "in": "query",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Transaction-level records",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TransactionsResponse"
        }
       }
      }
     },
     "400": {
      "description": "City or quarter missing, or bad quarter format",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Above tier: the free plan serves the latest quarter only",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "No data for this city and quarter",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/QuotaExceeded"
     }
    }
   }
  },
  "/files": {
   "get": {
    "operationId": "listFiles",
    "summary": "Team: list downloadable files",
    "description": "Requires a Team API key.",
    "responses": {
     "200": {
      "description": "Release metadata and files with path, url, bytes, sha256 and rows",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/FilesResponse"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Team plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/files/{path}": {
   "get": {
    "operationId": "downloadFile",
    "summary": "Team: download a manifest file",
    "description": "Requires a Team API key.",
    "responses": {
     "200": {
      "description": "Complete file",
      "headers": {
       "Accept-Ranges": {
        "schema": {
         "type": "string"
        },
        "description": "bytes"
       },
       "ETag": {
        "schema": {
         "type": "string"
        },
        "description": "File entity tag"
       },
       "Content-Length": {
        "schema": {
         "type": "string"
        },
        "description": "Response length in bytes"
       },
       "Content-Disposition": {
        "schema": {
         "type": "string"
        },
        "description": "Attachment filename"
       }
      },
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Team plan",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "206": {
      "description": "Requested byte range",
      "headers": {
       "Accept-Ranges": {
        "schema": {
         "type": "string"
        },
        "description": "bytes"
       },
       "ETag": {
        "schema": {
         "type": "string"
        },
        "description": "File entity tag"
       },
       "Content-Length": {
        "schema": {
         "type": "string"
        },
        "description": "Response length in bytes"
       },
       "Content-Disposition": {
        "schema": {
         "type": "string"
        },
        "description": "Attachment filename"
       },
       "Content-Range": {
        "schema": {
         "type": "string"
        },
        "description": "bytes START-END/SIZE"
       }
      },
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "404": {
      "description": "Path is absent from the manifest",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "416": {
      "description": "Range is not satisfiable",
      "headers": {
       "Content-Range": {
        "schema": {
         "type": "string"
        },
        "description": "bytes */SIZE"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "path",
      "in": "path",
      "required": true,
      "description": "Exact path from GET /files, including any slash-separated directories.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Range",
      "in": "header",
      "description": "Single byte range, including open-ended or suffix ranges. Malformed or multiple ranges return the complete file.",
      "schema": {
       "type": "string",
       "example": "bytes=0-1023"
      }
     },
     {
      "name": "If-Range",
      "in": "header",
      "description": "ETag of the expected file. A mismatch returns the complete file.",
      "schema": {
       "type": "string"
      }
     }
    ]
   },
   "head": {
    "operationId": "headFile",
    "summary": "Team: inspect a manifest file",
    "description": "Requires a Team API key. Same status and headers as GET, with no response body.",
    "responses": {
     "200": {
      "description": "Complete file",
      "headers": {
       "Accept-Ranges": {
        "schema": {
         "type": "string"
        },
        "description": "bytes"
       },
       "ETag": {
        "schema": {
         "type": "string"
        },
        "description": "File entity tag"
       },
       "Content-Length": {
        "schema": {
         "type": "string"
        },
        "description": "Response length in bytes"
       },
       "Content-Disposition": {
        "schema": {
         "type": "string"
        },
        "description": "Attachment filename"
       }
      }
     },
     "401": {
      "description": "Missing or invalid API key"
     },
     "403": {
      "description": "Requires the Team plan"
     },
     "503": {
      "description": "Temporarily unavailable"
     },
     "206": {
      "description": "Requested byte range",
      "headers": {
       "Accept-Ranges": {
        "schema": {
         "type": "string"
        },
        "description": "bytes"
       },
       "ETag": {
        "schema": {
         "type": "string"
        },
        "description": "File entity tag"
       },
       "Content-Length": {
        "schema": {
         "type": "string"
        },
        "description": "Response length in bytes"
       },
       "Content-Disposition": {
        "schema": {
         "type": "string"
        },
        "description": "Attachment filename"
       },
       "Content-Range": {
        "schema": {
         "type": "string"
        },
        "description": "bytes START-END/SIZE"
       }
      }
     },
     "404": {
      "description": "Path is absent from the manifest"
     },
     "416": {
      "description": "Range is not satisfiable",
      "headers": {
       "Content-Range": {
        "schema": {
         "type": "string"
        },
        "description": "bytes */SIZE"
       }
      }
     }
    },
    "parameters": [
     {
      "name": "path",
      "in": "path",
      "required": true,
      "description": "Exact path from GET /files, including any slash-separated directories.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "Range",
      "in": "header",
      "description": "Single byte range, including open-ended or suffix ranges. Malformed or multiple ranges return the complete file.",
      "schema": {
       "type": "string",
       "example": "bytes=0-1023"
      }
     },
     {
      "name": "If-Range",
      "in": "header",
      "description": "ETag of the expected file. A mismatch returns the complete file.",
      "schema": {
       "type": "string"
      }
     }
    ]
   }
  },
  "/account/keys": {
   "get": {
    "operationId": "listMemberKeys",
    "summary": "Team owner: list member keys",
    "description": "Requires the Team account owner key; member keys cannot manage keys.",
    "responses": {
     "200": {
      "description": "allowed, in_use and members (id, label, key_start, created); full keys are not returned",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/MemberKeyList"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Team account owner key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   },
   "post": {
    "operationId": "createMemberKey",
    "summary": "Team owner: add a member key",
    "description": "Requires the Team account owner key; member keys cannot manage keys.",
    "responses": {
     "200": {
      "description": "New key (shown once), id, label, tier and key counts; quota is shared with the account",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/MemberKeyCreated"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Team account owner key; or all five account seats are in use",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Daily member key change limit reached (10 adds/rotations)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "label": {
          "type": "string",
          "description": "Optional; trimmed to 60 characters, defaults to member."
         }
        }
       }
      }
     }
    }
   }
  },
  "/account/keys/{id}/rotate": {
   "post": {
    "operationId": "rotateMemberKey",
    "summary": "Team owner: replace a member key",
    "description": "Requires the Team account owner key; member keys cannot manage keys.",
    "responses": {
     "200": {
      "description": "New key (shown once), id and label; the old key stops working",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/MemberKeyRotated"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Team account owner key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Unknown member key id",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Daily member key change limit reached (10 adds/rotations)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Member id returned by GET /account/keys.",
      "schema": {
       "type": "string",
       "pattern": "^[0-9a-f]{8}$"
      }
     }
    ]
   }
  },
  "/account/keys/{id}": {
   "delete": {
    "operationId": "deleteMemberKey",
    "summary": "Team owner: remove a member key",
    "description": "Requires the Team account owner key; member keys cannot manage keys.",
    "responses": {
     "200": {
      "description": "ok and removed member id; the seat is freed",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/MemberKeyRemoved"
        }
       }
      }
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "description": "Requires the Team account owner key",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Temporarily unavailable",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Unknown member key id",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Member id returned by GET /account/keys.",
      "schema": {
       "type": "string",
       "pattern": "^[0-9a-f]{8}$"
      }
     }
    ]
   }
  }
 }
}
