{
  "openapi": "3.0.3",
  "info": {
    "title": "ParentLink API",
    "version": "1.0.0",
    "description": "Read-only REST API over a nursery's own data (children, attendance, invoices, rota, waiting list). Authenticate with a scoped bearer token minted in Settings → API tokens. Responses are always scoped to the token's nursery. See https://www.parentlinkeducation.co.uk/developers for the full guide including webhooks.",
    "contact": { "name": "ParentLink", "url": "https://www.parentlinkeducation.co.uk/developers" }
  },
  "servers": [
    {
      "url": "https://{projectRef}.functions.supabase.co/api-v1",
      "description": "Per-nursery Supabase Edge Functions domain",
      "variables": {
        "projectRef": { "default": "your-project", "description": "Your Supabase project ref" }
      }
    }
  ],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "Children" },
    { "name": "Attendance" },
    { "name": "Invoices" },
    { "name": "Rota" },
    { "name": "Waiting list" }
  ],
  "paths": {
    "/children": {
      "get": {
        "tags": ["Children"],
        "summary": "List children",
        "description": "Active and archived children. Requires scope `children:read`.",
        "parameters": [
          { "$ref": "#/components/parameters/limit" },
          { "$ref": "#/components/parameters/offset" }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/List" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/attendance": {
      "get": {
        "tags": ["Attendance"],
        "summary": "List attendance sessions",
        "description": "Sign-in / sign-out sessions per child per day. Requires scope `attendance:read`.",
        "parameters": [
          { "$ref": "#/components/parameters/limit" },
          { "$ref": "#/components/parameters/offset" },
          { "$ref": "#/components/parameters/from" },
          { "$ref": "#/components/parameters/to" }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/List" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/invoices": {
      "get": {
        "tags": ["Invoices"],
        "summary": "List per-child billing roll-up",
        "description": "Total due, total paid, outstanding, weeks billed / paid per child. Requires scope `invoices:read`.",
        "parameters": [
          { "$ref": "#/components/parameters/limit" },
          { "$ref": "#/components/parameters/offset" }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/List" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/rota": {
      "get": {
        "tags": ["Rota"],
        "summary": "List staff rota",
        "description": "Staff rota rows per ISO week. Requires scope `rota:read`.",
        "parameters": [
          { "$ref": "#/components/parameters/limit" },
          { "$ref": "#/components/parameters/offset" },
          { "$ref": "#/components/parameters/from" },
          { "$ref": "#/components/parameters/to" }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/List" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/waiting-list": {
      "get": {
        "tags": ["Waiting list"],
        "summary": "List enquiries",
        "description": "Enquiry pipeline entries. Requires scope `waiting-list:read`.",
        "parameters": [
          { "$ref": "#/components/parameters/limit" },
          { "$ref": "#/components/parameters/offset" }
        ],
        "responses": {
          "200": { "$ref": "#/components/responses/List" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "pl_token",
        "description": "A token minted in Settings → API tokens, sent as `Authorization: Bearer pl_…`."
      }
    },
    "parameters": {
      "limit": {
        "name": "limit", "in": "query", "required": false,
        "description": "Page size (1–500, default 100).",
        "schema": { "type": "integer", "minimum": 1, "maximum": 500, "default": 100 }
      },
      "offset": {
        "name": "offset", "in": "query", "required": false,
        "description": "Rows to skip (default 0).",
        "schema": { "type": "integer", "minimum": 0, "default": 0 }
      },
      "from": {
        "name": "from", "in": "query", "required": false,
        "description": "Inclusive start date (ISO YYYY-MM-DD).",
        "schema": { "type": "string", "format": "date" }
      },
      "to": {
        "name": "to", "in": "query", "required": false,
        "description": "Inclusive end date (ISO YYYY-MM-DD).",
        "schema": { "type": "string", "format": "date" }
      }
    },
    "responses": {
      "List": {
        "description": "A page of rows with pagination metadata.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "data": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
                "total": { "type": "integer", "description": "Total rows matching the query (across all pages)." },
                "limit": { "type": "integer" },
                "offset": { "type": "integer" }
              },
              "required": ["data", "total", "limit", "offset"]
            }
          }
        }
      },
      "Error": {
        "description": "Error response (401 auth, 403 scope, 404 unknown resource, 429 rate limit).",
        "headers": {
          "Retry-After": {
            "description": "On 429, seconds to wait before retrying.",
            "schema": { "type": "integer" }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": { "error": { "type": "string" } },
              "required": ["error"]
            }
          }
        }
      }
    }
  }
}
