{
  "openapi": "3.1.0",
  "info": {
    "title": "eKTextAI School Records API",
    "version": "1.0.0",
    "summary": "Push a school's students, parents, attendance, marks, fees, homework and calendar to eKTextAI.",
    "description": "School software sends each school's records here, so eKTextAI can answer that school's parents and staff from them. Guide: https://ektextai.com/developers/school-api.html",
    "contact": {
      "name": "eKTextAI developer support",
      "email": "info@ektextai.com",
      "url": "https://ektextai.com/developers/school-api.html"
    }
  },
  "servers": [
    {
      "url": "https://ektextai.com/api/sis/v1",
      "description": "Production (sandbox schools use the same URL with their own key)"
    }
  ],
  "security": [
    {
      "SchoolKey": [],
      "PartnerId": []
    },
    {
      "SchoolBearer": [],
      "PartnerId": []
    }
  ],
  "tags": [
    {
      "name": "School and classes"
    },
    {
      "name": "Students, staff and parents"
    },
    {
      "name": "Attendance"
    },
    {
      "name": "Exams and marks"
    },
    {
      "name": "Fees"
    },
    {
      "name": "Homework and diary"
    },
    {
      "name": "Timetable and calendar"
    }
  ],
  "x-groups": [
    {
      "id": "school",
      "title": "School and classes",
      "paths": [
        "org_details",
        "classes"
      ]
    },
    {
      "id": "people",
      "title": "Students, staff and parents",
      "paths": [
        "user_details",
        "guardians",
        "user_subjects"
      ]
    },
    {
      "id": "attendance",
      "title": "Attendance",
      "paths": [
        "attendance",
        "attendance_summary"
      ]
    },
    {
      "id": "exams",
      "title": "Exams and marks",
      "paths": [
        "exams",
        "marks",
        "results"
      ]
    },
    {
      "id": "fees",
      "title": "Fees",
      "paths": [
        "fee_dues",
        "payments"
      ]
    },
    {
      "id": "homework",
      "title": "Homework and diary",
      "paths": [
        "assignments",
        "diary"
      ]
    },
    {
      "id": "calendar",
      "title": "Timetable and calendar",
      "paths": [
        "timetable",
        "holidays",
        "events"
      ]
    }
  ],
  "x-errors": [
    {
      "status": 401,
      "code": "AUTH_REQUIRED",
      "when": "No x-api-key header and no Bearer token"
    },
    {
      "status": 401,
      "code": "AUTHENTICATION_ERROR",
      "when": "The key is unknown or revoked, or the school's integration is switched off"
    },
    {
      "status": 401,
      "code": "PARTNER_REQUIRED",
      "when": "The key was created for a partner, but X-Partner-Id is missing"
    },
    {
      "status": 403,
      "code": "PARTNER_MISMATCH",
      "when": "X-Partner-Id is not the partner this school key was created for, or the key is not a partner key"
    },
    {
      "status": 403,
      "code": "PARTNER_NOT_APPROVED",
      "when": "Your partner account is not approved yet"
    },
    {
      "status": 403,
      "code": "PARTNER_SANDBOX_ONLY",
      "when": "You are not certified yet: push to your sandbox schools only"
    },
    {
      "status": 403,
      "code": "PARTNER_SUSPENDED",
      "when": "Your partner account is suspended"
    },
    {
      "status": 400,
      "code": "INVALID_BODY",
      "when": "The body is not a JSON array of records"
    },
    {
      "status": 404,
      "code": "UNKNOWN_COLLECTION",
      "when": "The path is not one of the record types"
    },
    {
      "status": 413,
      "code": "TOO_MANY_RECORDS",
      "when": "More than 1,000 records in one request: split it"
    },
    {
      "status": 429,
      "code": "RATE_LIMITED",
      "when": "Over 120 requests a minute for one school"
    },
    {
      "status": 429,
      "code": "PARTNER_RATE_LIMITED",
      "when": "Over your partner limit across all your schools (default 600 a minute)"
    },
    {
      "status": 500,
      "code": "INGEST_FAILED",
      "when": "Our side failed; retry later with the same records (pushes are idempotent)"
    }
  ],
  "x-record-errors": [
    {
      "code": "INVALID_RECORD",
      "when": "The item is not a JSON object"
    },
    {
      "code": "MISSING_KEY",
      "when": "The record has no value for its key field"
    },
    {
      "code": "MISSING_STUDENT",
      "when": "A student-level record has no student id"
    },
    {
      "code": "ORG_MISMATCH",
      "when": "org_id is not this school's"
    },
    {
      "code": "TEST_MODE_LIMIT",
      "when": "The school is in test mode and already has 50 active students; it needs a paid plan for more"
    },
    {
      "code": "NO_OPEN_RUN",
      "when": "A complete marker without a matching droptable run: nothing was removed"
    },
    {
      "code": "WRITE_FAILED",
      "when": "The record could not be stored; send it again"
    }
  ],
  "x-dropped-fields": [
    "aadhaar",
    "aadhaar_number",
    "aadhar",
    "aadhar_no",
    "address",
    "blood_group",
    "caste",
    "caste_category",
    "city",
    "class_average",
    "class_average_grade",
    "class_rank",
    "class_size",
    "class_topper",
    "classaverage",
    "classaveragegrade",
    "classrank",
    "classsize",
    "date_of_birth",
    "dateofbirth",
    "dob",
    "esic",
    "org_photo",
    "percentile",
    "percentile_score",
    "percentiledesc",
    "percentilegrade",
    "percentilescore",
    "pf",
    "photo",
    "present_salary",
    "rank",
    "religion",
    "salary",
    "state",
    "topper"
  ],
  "x-limits": {
    "recordsPerRequest": 1000,
    "requestsPerMinutePerSchool": 120,
    "requestsPerMinutePerPartner": 600,
    "testModeStudents": 50,
    "testModeEnquiringParents": 200
  },
  "x-changelog": [
    {
      "version": "1.0.0",
      "date": "2026-11-13",
      "change": "First public version: 17 record types, partner keys (X-Partner-Id), test mode, sandbox schools."
    }
  ],
  "paths": {
    "/schema": {
      "get": {
        "tags": [
          "School and classes"
        ],
        "summary": "List the record types",
        "operationId": "getSchema",
        "description": "The record types, their level and the fields a full replace may be scoped by.",
        "responses": {
          "200": {
            "description": "Record types"
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/state": {
      "get": {
        "tags": [
          "School and classes"
        ],
        "summary": "Sync state for this school",
        "operationId": "getState",
        "description": "Last successful push, counts and the last error per record type, plus the plan and partner. Show this in your own software so the school can see the sync is healthy.",
        "responses": {
          "200": {
            "description": "State",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/State"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/org_details": {
      "post": {
        "tags": [
          "School and classes"
        ],
        "summary": "Push school details",
        "operationId": "push_org_details",
        "description": "The school itself. Send one record.\n\nLevel: school. Key: `org_id`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/OrgDetailsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-org_details-1731400000000"
                },
                {
                  "org_id": "GVPS01",
                  "org_name": "Green Valley Public School",
                  "org_phone": "080 2345 6789",
                  "org_email": "office@greenvalley.example",
                  "academic_year": "2026-27",
                  "push_run": "GVPS01-org_details-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-org_details-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/classes": {
      "post": {
        "tags": [
          "School and classes"
        ],
        "summary": "Push classes",
        "operationId": "push_classes",
        "description": "Classes and sections offered this year.\n\nLevel: class. Key: `main_group + sub_group + academic_year`. A full replace may be scoped by: main_group.\n\nStored now; not used in answers yet.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ClassesRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-classes-1731400000000"
                },
                {
                  "main_group": "5",
                  "sub_group": "A",
                  "academic_year": "2026-27",
                  "class_teacher": "Mrs Rao",
                  "push_run": "GVPS01-classes-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-classes-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/user_details": {
      "post": {
        "tags": [
          "Students, staff and parents"
        ],
        "summary": "Push students and staff",
        "operationId": "push_user_details",
        "description": "One record per student, and per staff member with kind \"staff\". Students count toward the plan's student limit.\n\nLevel: student (staff: school). Key: `uid`. A full replace may be scoped by: main_group, kind (\"staff\" to replace staff only).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/UserDetailsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-user_details-1731400000000"
                },
                {
                  "uid": "S1042",
                  "usn": "GV/2021/1042",
                  "official_name": "Ananya Sharma",
                  "first_name": "Ananya",
                  "last_name": "Sharma",
                  "main_group": "5",
                  "sub_group": "A",
                  "gender": "F",
                  "status": "active",
                  "academic_year": "2026-27",
                  "push_run": "GVPS01-user_details-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-user_details-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/guardians": {
      "post": {
        "tags": [
          "Students, staff and parents"
        ],
        "summary": "Push parents and guardians",
        "operationId": "push_guardians",
        "description": "Who may ask about a student. A parent is recognised by this mobile number or email.\n\nLevel: student. Key: `uid + relation`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/GuardiansRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-guardians-1731400000000"
                },
                {
                  "uid": "S1042",
                  "relation": "mother",
                  "name": "Priya Sharma",
                  "mobile_number": "+91 98450 12345",
                  "email_address": "priya@example.com",
                  "push_run": "GVPS01-guardians-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-guardians-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/user_subjects": {
      "post": {
        "tags": [
          "Students, staff and parents"
        ],
        "summary": "Push student subjects",
        "operationId": "push_user_subjects",
        "description": "Subjects each student takes.\n\nLevel: student. Key: `uid + subject_name`.\n\nStored now; not used in answers yet.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/UserSubjectsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-user_subjects-1731400000000"
                },
                {
                  "uid": "S1042",
                  "subject_name": "Mathematics",
                  "subject_type": "core",
                  "push_run": "GVPS01-user_subjects-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-user_subjects-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/attendance": {
      "post": {
        "tags": [
          "Attendance"
        ],
        "summary": "Push daily attendance",
        "operationId": "push_attendance",
        "description": "One record per student per day.\n\nLevel: student. Key: `DESKTOPATTENDANCEID`. A full replace may be scoped by: main_group, sub_group, from, to.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AttendanceRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-attendance-1731400000000"
                },
                {
                  "DESKTOPATTENDANCEID": "A-2026-11-12-S1042",
                  "STUDENTID": "S1042",
                  "ATTENDANCEDATE": "2026-11-12",
                  "MORNING": true,
                  "AFTERNOON": true,
                  "main_group": "5",
                  "sub_group": "A",
                  "push_run": "GVPS01-attendance-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-attendance-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/attendance_summary": {
      "post": {
        "tags": [
          "Attendance"
        ],
        "summary": "Push attendance summary",
        "operationId": "push_attendance_summary",
        "description": "Totals per student per period, when you keep them instead of daily rows.\n\nLevel: student. Key: `uid + period`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AttendanceSummaryRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-attendance_summary-1731400000000"
                },
                {
                  "uid": "S1042",
                  "period": "2026-11",
                  "working_days": 20,
                  "present_days": 19,
                  "push_run": "GVPS01-attendance_summary-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-attendance_summary-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/exams": {
      "post": {
        "tags": [
          "Exams and marks"
        ],
        "summary": "Push exams (publishing)",
        "operationId": "push_exams",
        "description": "Which exams parents may see, and from when. Marks of an exam reach parents only once its exam record has a published_at date on or before today.\n\nLevel: class. Key: `desktop_exam_id`. A full replace may be scoped by: main_group.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ExamsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-exams-1731400000000"
                },
                {
                  "desktop_exam_id": "5|1|2",
                  "main_group": "5",
                  "term": "1",
                  "EXAM": "2",
                  "exam_kind": "unit test",
                  "exam_name": "Unit Test 2",
                  "published_at": "2026-11-15",
                  "note": "Revision class on Saturday",
                  "push_run": "GVPS01-exams-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-exams-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/marks": {
      "post": {
        "tags": [
          "Exams and marks"
        ],
        "summary": "Push marks",
        "operationId": "push_marks",
        "description": "One record per student, exam and subject.\n\nLevel: student. Key: `DESKTOPTESTID`. A full replace may be scoped by: main_group, term, EXAM.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/MarksRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-marks-1731400000000"
                },
                {
                  "DESKTOPTESTID": "M-5-1-2-S1042-MATH",
                  "STUDENTID": "S1042",
                  "term": "1",
                  "EXAM": "2",
                  "exam_name": "Unit Test 2",
                  "SUBJECTNAME": "Mathematics",
                  "SCORE": 46,
                  "MAXMARKS": 50,
                  "MINMARKS": 18,
                  "GRADES": "A1",
                  "main_group": "5",
                  "sub_group": "A",
                  "push_run": "GVPS01-marks-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-marks-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/results": {
      "post": {
        "tags": [
          "Exams and marks"
        ],
        "summary": "Push results",
        "operationId": "push_results",
        "description": "Overall result per student and exam (total, grade, pass or fail).\n\nLevel: student. Key: `desktop_result_id`.\n\nStored now; not used in answers yet.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ResultsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-results-1731400000000"
                },
                {
                  "desktop_result_id": "R-5-1-2-S1042",
                  "uid": "S1042",
                  "term": "1",
                  "EXAM": "2",
                  "total": 231,
                  "max_total": 250,
                  "grade": "A1",
                  "result": "Pass",
                  "push_run": "GVPS01-results-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-results-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/fee_dues": {
      "post": {
        "tags": [
          "Fees"
        ],
        "summary": "Push fee dues",
        "operationId": "push_fee_dues",
        "description": "What each student owes. Parents can ask what is due; eKTextAI never sends fee reminders on its own.\n\nLevel: student. Key: `desktop_due_id`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/FeeDuesRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-fee_dues-1731400000000"
                },
                {
                  "desktop_due_id": "D-S1042-T2",
                  "uid": "S1042",
                  "main_group": "5",
                  "sub_group": "A",
                  "fee_type": "Tuition, term 2",
                  "total_amount": 18500,
                  "amount_paid": 10000,
                  "due_date": "2026-11-30",
                  "push_run": "GVPS01-fee_dues-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-fee_dues-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/payments": {
      "post": {
        "tags": [
          "Fees"
        ],
        "summary": "Push fee payments",
        "operationId": "push_payments",
        "description": "Payments received.\n\nLevel: student. Key: `DESKTOPPAYMENTID`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PaymentsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-payments-1731400000000"
                },
                {
                  "DESKTOPPAYMENTID": "P-88213",
                  "uid": "S1042",
                  "receipt_id": "RC/2026/88213",
                  "amount_paid": 10000,
                  "total_amount": 18500,
                  "trans_date": "2026-10-04",
                  "push_run": "GVPS01-payments-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-payments-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/assignments": {
      "post": {
        "tags": [
          "Homework and diary"
        ],
        "summary": "Push homework (class)",
        "operationId": "push_assignments",
        "description": "Homework set for a class or section.\n\nLevel: class. Key: `desktop_assignment_id`. A full replace may be scoped by: main_group, sub_group, from, to.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AssignmentsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-assignments-1731400000000"
                },
                {
                  "desktop_assignment_id": "H-5A-2026-11-12-MATH",
                  "main_group": "5",
                  "sub_group": "A",
                  "subject": "Mathematics",
                  "title": "Fractions",
                  "description": "Exercise 4.2, questions 1-10",
                  "date": "2026-11-12",
                  "submit_date": "2026-11-14",
                  "teacher_name": "Mr Iyer",
                  "push_run": "GVPS01-assignments-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-assignments-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/diary": {
      "post": {
        "tags": [
          "Homework and diary"
        ],
        "summary": "Push diary (per student)",
        "operationId": "push_diary",
        "description": "A teacher's note about one student.\n\nLevel: student. Key: `DESKTOPDAIRYID`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/DiaryRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-diary-1731400000000"
                },
                {
                  "DESKTOPDAIRYID": "N-77120",
                  "STUDENTID": "S1042",
                  "DATE": "2026-11-12",
                  "DAIRYREPORT": "Please send the signed permission slip.",
                  "teacher_name": "Mrs Rao",
                  "push_run": "GVPS01-diary-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-diary-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/timetable": {
      "post": {
        "tags": [
          "Timetable and calendar"
        ],
        "summary": "Push timetable",
        "operationId": "push_timetable",
        "description": "Periods per class or section.\n\nLevel: class. Key: `desktop_timetable_id`. A full replace may be scoped by: main_group, sub_group.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/TimetableRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-timetable-1731400000000"
                },
                {
                  "desktop_timetable_id": "T-5A-MON-1",
                  "main_group": "5",
                  "sub_group": "A",
                  "day": "Monday",
                  "period": 1,
                  "start_time": "08:30",
                  "end_time": "09:15",
                  "subject": "English",
                  "teacher_name": "Mrs Rao",
                  "push_run": "GVPS01-timetable-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-timetable-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/holidays": {
      "post": {
        "tags": [
          "Timetable and calendar"
        ],
        "summary": "Push holidays",
        "operationId": "push_holidays",
        "description": "School holidays.\n\nLevel: school. Key: `desktop_holiday_id`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/HolidaysRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-holidays-1731400000000"
                },
                {
                  "desktop_holiday_id": "HOL-2026-11-01",
                  "date": "2026-11-01",
                  "title": "Kannada Rajyotsava",
                  "push_run": "GVPS01-holidays-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-holidays-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/events": {
      "post": {
        "tags": [
          "Timetable and calendar"
        ],
        "summary": "Push events",
        "operationId": "push_events",
        "description": "School events (sports day, PTM, exams week).\n\nLevel: school. Key: `desktop_event_id`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 1002,
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/EventsRecord"
                    },
                    {
                      "$ref": "#/components/schemas/Reset"
                    },
                    {
                      "$ref": "#/components/schemas/Complete"
                    }
                  ]
                }
              },
              "example": [
                {
                  "droptable": true,
                  "push_run": "GVPS01-events-1731400000000"
                },
                {
                  "desktop_event_id": "EV-PTM-2026-11-22",
                  "date": "2026-11-22",
                  "title": "Parent-teacher meeting",
                  "type": "ptm",
                  "push_run": "GVPS01-events-1731400000000"
                },
                {
                  "complete": true,
                  "push_run": "GVPS01-events-1731400000000"
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored (info \"partial\" when some records failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushResult"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: The body is not a JSON array of records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "`AUTH_REQUIRED`: No x-api-key header and no Bearer token; `AUTHENTICATION_ERROR`: The key is unknown or revoked, or the school's integration is switched off; `PARTNER_REQUIRED`: The key was created for a partner, but X-Partner-Id is missing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`PARTNER_MISMATCH`: X-Partner-Id is not the partner this school key was created for, or the key is not a partner key; `PARTNER_NOT_APPROVED`: Your partner account is not approved yet; `PARTNER_SANDBOX_ONLY`: You are not certified yet: push to your sandbox schools only; `PARTNER_SUSPENDED`: Your partner account is suspended",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`UNKNOWN_COLLECTION`: The path is not one of the record types",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`TOO_MANY_RECORDS`: More than 1,000 records in one request: split it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "`RATE_LIMITED`: Over 120 requests a minute for one school; `PARTNER_RATE_LIMITED`: Over your partner limit across all your schools (default 600 a minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INGEST_FAILED`: Our side failed; retry later with the same records (pushes are idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "SchoolKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "The school's key, created by the school in eKTextAI Settings > API Access > Connect school software"
      },
      "SchoolBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "The same school key as a Bearer token"
      },
      "PartnerId": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Partner-Id",
        "description": "Your Partner ID (ptr_…), from MarvelSoft when your partner account is approved. Public, not a secret."
      }
    },
    "schemas": {
      "Reset": {
        "type": "object",
        "title": "Start of a full replace",
        "description": "First item of the first request of a full replace. Rows of this type (or of scope) that the run does not send are removed when the complete marker arrives, never before.",
        "required": [
          "droptable",
          "push_run"
        ],
        "properties": {
          "droptable": {
            "const": true
          },
          "push_run": {
            "type": "string",
            "description": "Your id for this run; the same on every request and on the complete marker"
          },
          "scope": {
            "type": "object",
            "description": "Replace only part of the type, for example { \"main_group\": \"5\" } or { \"from\": \"2026-11-01\", \"to\": \"2026-11-30\" }",
            "additionalProperties": true
          }
        }
      },
      "Complete": {
        "type": "object",
        "title": "End of a full replace",
        "description": "Last item of the last request of a full replace.",
        "required": [
          "complete",
          "push_run"
        ],
        "properties": {
          "complete": {
            "const": true
          },
          "push_run": {
            "type": "string"
          }
        }
      },
      "PushResult": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "info": {
            "type": "string",
            "description": "\"ok\", or \"partial\" when some records failed"
          },
          "data": {
            "type": "object",
            "properties": {
              "received": {
                "type": "integer"
              },
              "upserted": {
                "type": "integer"
              },
              "updated": {
                "type": "integer"
              },
              "unchanged": {
                "type": "integer"
              },
              "deleted": {
                "type": "integer"
              },
              "failed": {
                "type": "integer"
              },
              "errors": {
                "type": "array",
                "description": "At most 50",
                "items": {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer",
                      "description": "Position in the request body"
                    },
                    "key": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "INVALID_RECORD",
                        "MISSING_KEY",
                        "MISSING_STUDENT",
                        "ORG_MISMATCH",
                        "TEST_MODE_LIMIT",
                        "NO_OPEN_RUN",
                        "WRITE_FAILED"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              },
              "plan": {
                "type": "string",
                "description": "\"test\" (test mode) or \"paid\""
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "result": {
            "const": false
          },
          "info": {
            "type": "string",
            "enum": [
              "AUTH_REQUIRED",
              "AUTHENTICATION_ERROR",
              "PARTNER_REQUIRED",
              "PARTNER_MISMATCH",
              "PARTNER_NOT_APPROVED",
              "PARTNER_SANDBOX_ONLY",
              "PARTNER_SUSPENDED",
              "INVALID_BODY",
              "UNKNOWN_COLLECTION",
              "TOO_MANY_RECORDS",
              "RATE_LIMITED",
              "PARTNER_RATE_LIMITED",
              "INGEST_FAILED"
            ]
          },
          "message": {
            "type": "string"
          }
        }
      },
      "State": {
        "type": "object",
        "properties": {
          "result": {
            "type": "boolean"
          },
          "info": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "properties": {
              "collections": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "collection": {
                      "type": "string"
                    },
                    "lastSuccessAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "lastRun": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastResetAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "openRun": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "A full replace that has not completed"
                    },
                    "counts": {
                      "type": "object"
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              },
              "license": {
                "type": "object",
                "properties": {
                  "plan": {
                    "type": "string"
                  },
                  "maxStudents": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "string"
                  }
                }
              },
              "partner": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "partnerId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "sandbox": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      },
      "OrgDetailsRecord": {
        "type": "object",
        "title": "School details",
        "description": "The school itself. Send one record. Key: org_id.",
        "required": [
          "org_id"
        ],
        "properties": {
          "org_id": {
            "type": "string",
            "description": "Your id for the school; also sent on every other record"
          },
          "org_name": {
            "type": "string",
            "description": "School name"
          },
          "org_phone": {
            "type": "string",
            "description": "Office phone"
          },
          "org_mobile": {
            "type": "string",
            "description": "Office mobile"
          },
          "org_email": {
            "type": "string",
            "description": "Office email"
          },
          "academic_year": {
            "type": "string",
            "description": "Current academic year, for example \"2026-27\""
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "org_id": "GVPS01",
          "org_name": "Green Valley Public School",
          "org_phone": "080 2345 6789",
          "org_email": "office@greenvalley.example",
          "academic_year": "2026-27"
        }
      },
      "ClassesRecord": {
        "type": "object",
        "title": "Classes",
        "description": "Classes and sections offered this year. Key: main_group + sub_group + academic_year. Stored now; not used in answers yet.",
        "required": [
          "main_group"
        ],
        "properties": {
          "main_group": {
            "type": "string",
            "description": "Class (grade)"
          },
          "sub_group": {
            "type": "string",
            "description": "Section"
          },
          "academic_year": {
            "type": "string",
            "description": "Academic year"
          },
          "class_teacher": {
            "type": "string",
            "description": "Class teacher's name"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "main_group": "5",
          "sub_group": "A",
          "academic_year": "2026-27",
          "class_teacher": "Mrs Rao"
        }
      },
      "UserDetailsRecord": {
        "type": "object",
        "title": "Students and staff",
        "description": "One record per student, and per staff member with kind \"staff\". Students count toward the plan's student limit. Key: uid.",
        "required": [
          "uid"
        ],
        "properties": {
          "uid": {
            "type": "string",
            "description": "Your permanent id for the student or staff member"
          },
          "kind": {
            "type": "string",
            "description": "\"student\" (default) or \"staff\""
          },
          "usn": {
            "type": "string",
            "description": "Admission number"
          },
          "official_name": {
            "type": "string",
            "description": "Full name as on school records"
          },
          "first_name": {
            "type": "string",
            "description": "First name"
          },
          "last_name": {
            "type": "string",
            "description": "Last name"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "gender": {
            "type": "string",
            "description": "Gender"
          },
          "status": {
            "type": "string",
            "description": "\"active\" (default) or \"left\"; only active students count and are answered for"
          },
          "academic_year": {
            "type": "string",
            "description": "Academic year"
          },
          "mobile_number": {
            "type": "string",
            "description": "Staff: mobile number (used to recognise teachers on WhatsApp)"
          },
          "email_address": {
            "type": "string",
            "description": "Staff: email address"
          },
          "classes": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Staff: classes they teach, as [{ main_group, sub_group, subject }]"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "uid": "S1042",
          "usn": "GV/2021/1042",
          "official_name": "Ananya Sharma",
          "first_name": "Ananya",
          "last_name": "Sharma",
          "main_group": "5",
          "sub_group": "A",
          "gender": "F",
          "status": "active",
          "academic_year": "2026-27"
        }
      },
      "GuardiansRecord": {
        "type": "object",
        "title": "Parents and guardians",
        "description": "Who may ask about a student. A parent is recognised by this mobile number or email. Key: uid + relation.",
        "required": [
          "uid"
        ],
        "properties": {
          "uid": {
            "type": "string",
            "description": "The student's uid"
          },
          "relation": {
            "type": "string",
            "description": "\"father\", \"mother\" or \"guardian\" (default)"
          },
          "name": {
            "type": "string",
            "description": "Parent's name"
          },
          "mobile_number": {
            "type": "string",
            "description": "Mobile number; the last 10 digits are matched"
          },
          "email_address": {
            "type": "string",
            "description": "Email address"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "uid": "S1042",
          "relation": "mother",
          "name": "Priya Sharma",
          "mobile_number": "+91 98450 12345",
          "email_address": "priya@example.com"
        }
      },
      "UserSubjectsRecord": {
        "type": "object",
        "title": "Student subjects",
        "description": "Subjects each student takes. Key: uid + subject_name. Stored now; not used in answers yet.",
        "required": [
          "uid",
          "subject_name"
        ],
        "properties": {
          "uid": {
            "type": "string",
            "description": "The student's uid"
          },
          "subject_name": {
            "type": "string",
            "description": "Subject"
          },
          "subject_type": {
            "type": "string",
            "description": "For example \"core\" or \"elective\""
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "uid": "S1042",
          "subject_name": "Mathematics",
          "subject_type": "core"
        }
      },
      "AttendanceRecord": {
        "type": "object",
        "title": "Daily attendance",
        "description": "One record per student per day. Key: DESKTOPATTENDANCEID.",
        "required": [
          "DESKTOPATTENDANCEID",
          "STUDENTID",
          "ATTENDANCEDATE"
        ],
        "properties": {
          "DESKTOPATTENDANCEID": {
            "type": "string",
            "description": "Your id for this attendance row"
          },
          "STUDENTID": {
            "type": "string",
            "description": "The student's uid"
          },
          "ATTENDANCEDATE": {
            "type": "string",
            "format": "date",
            "description": "Day, YYYY-MM-DD"
          },
          "MORNING": {
            "type": "boolean",
            "description": "Present in the morning session"
          },
          "AFTERNOON": {
            "type": "boolean",
            "description": "Present in the afternoon session"
          },
          "status": {
            "type": "string",
            "description": "\"present\", \"absent\" or \"half_day\"; worked out from MORNING / AFTERNOON when left out"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "DESKTOPATTENDANCEID": "A-2026-11-12-S1042",
          "STUDENTID": "S1042",
          "ATTENDANCEDATE": "2026-11-12",
          "MORNING": true,
          "AFTERNOON": true,
          "main_group": "5",
          "sub_group": "A"
        }
      },
      "AttendanceSummaryRecord": {
        "type": "object",
        "title": "Attendance summary",
        "description": "Totals per student per period, when you keep them instead of daily rows. Key: uid + period.",
        "required": [
          "uid",
          "period"
        ],
        "properties": {
          "uid": {
            "type": "string",
            "description": "The student's uid"
          },
          "period": {
            "type": "string",
            "description": "For example \"2026-11\" or \"Term 1\""
          },
          "working_days": {
            "type": "number",
            "description": "School days in the period"
          },
          "present_days": {
            "type": "number",
            "description": "Days present"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "uid": "S1042",
          "period": "2026-11",
          "working_days": 20,
          "present_days": 19
        }
      },
      "ExamsRecord": {
        "type": "object",
        "title": "Exams (publishing)",
        "description": "Which exams parents may see, and from when. Marks of an exam reach parents only once its exam record has a published_at date on or before today. Key: desktop_exam_id.",
        "required": [
          "desktop_exam_id"
        ],
        "properties": {
          "desktop_exam_id": {
            "type": "string",
            "description": "Your id; \"class|term|test\", or \"class|term|test|section\" for one section"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "term": {
            "type": "string",
            "description": "Term"
          },
          "EXAM": {
            "type": "string",
            "description": "Test within the term"
          },
          "exam_kind": {
            "type": "string",
            "description": "For example \"unit test\" or \"term exam\""
          },
          "exam_name": {
            "type": "string",
            "description": "Name parents see"
          },
          "published_at": {
            "type": "string",
            "format": "date",
            "description": "Shown to parents from this day (YYYY-MM-DD); leave out to keep it hidden"
          },
          "note": {
            "type": "string",
            "description": "A note parents see with the marks"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_exam_id": "5|1|2",
          "main_group": "5",
          "term": "1",
          "EXAM": "2",
          "exam_kind": "unit test",
          "exam_name": "Unit Test 2",
          "published_at": "2026-11-15",
          "note": "Revision class on Saturday"
        }
      },
      "MarksRecord": {
        "type": "object",
        "title": "Marks",
        "description": "One record per student, exam and subject. Key: DESKTOPTESTID.",
        "required": [
          "DESKTOPTESTID",
          "STUDENTID"
        ],
        "properties": {
          "DESKTOPTESTID": {
            "type": "string",
            "description": "Your id for this mark"
          },
          "STUDENTID": {
            "type": "string",
            "description": "The student's uid"
          },
          "term": {
            "type": "string",
            "description": "Term"
          },
          "EXAM": {
            "type": "string",
            "description": "Test within the term"
          },
          "exam_kind": {
            "type": "string",
            "description": "Exam kind"
          },
          "exam_name": {
            "type": "string",
            "description": "Exam name"
          },
          "SUBJECTNAME": {
            "type": "string",
            "description": "Subject"
          },
          "SUBJECTTYPE": {
            "type": "string",
            "description": "Subject type"
          },
          "subject_order": {
            "type": "number",
            "description": "Order on the report card"
          },
          "absent": {
            "type": "boolean",
            "description": "Absent for this paper"
          },
          "SCORE": {
            "type": "number",
            "description": "Marks scored"
          },
          "MAXMARKS": {
            "type": "number",
            "description": "Maximum marks"
          },
          "MINMARKS": {
            "type": "number",
            "description": "Pass marks"
          },
          "GRADES": {
            "type": "string",
            "description": "Grade"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "DESKTOPTESTID": "M-5-1-2-S1042-MATH",
          "STUDENTID": "S1042",
          "term": "1",
          "EXAM": "2",
          "exam_name": "Unit Test 2",
          "SUBJECTNAME": "Mathematics",
          "SCORE": 46,
          "MAXMARKS": 50,
          "MINMARKS": 18,
          "GRADES": "A1",
          "main_group": "5",
          "sub_group": "A"
        }
      },
      "ResultsRecord": {
        "type": "object",
        "title": "Results",
        "description": "Overall result per student and exam (total, grade, pass or fail). Key: desktop_result_id. Stored now; not used in answers yet.",
        "required": [
          "desktop_result_id",
          "uid"
        ],
        "properties": {
          "desktop_result_id": {
            "type": "string",
            "description": "Your id for this result"
          },
          "uid": {
            "type": "string",
            "description": "The student's uid"
          },
          "term": {
            "type": "string",
            "description": "Term"
          },
          "EXAM": {
            "type": "string",
            "description": "Test within the term"
          },
          "total": {
            "type": "number",
            "description": "Total marks"
          },
          "max_total": {
            "type": "number",
            "description": "Maximum total"
          },
          "grade": {
            "type": "string",
            "description": "Overall grade"
          },
          "result": {
            "type": "string",
            "description": "For example \"Pass\""
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_result_id": "R-5-1-2-S1042",
          "uid": "S1042",
          "term": "1",
          "EXAM": "2",
          "total": 231,
          "max_total": 250,
          "grade": "A1",
          "result": "Pass"
        }
      },
      "FeeDuesRecord": {
        "type": "object",
        "title": "Fee dues",
        "description": "What each student owes. Parents can ask what is due; eKTextAI never sends fee reminders on its own. Key: desktop_due_id.",
        "required": [
          "desktop_due_id",
          "uid"
        ],
        "properties": {
          "desktop_due_id": {
            "type": "string",
            "description": "Your id for this due"
          },
          "uid": {
            "type": "string",
            "description": "The student's uid"
          },
          "usn": {
            "type": "string",
            "description": "Admission number"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "group_name": {
            "type": "string",
            "description": "Fee group"
          },
          "fee_type": {
            "type": "string",
            "description": "For example \"Tuition, term 2\""
          },
          "total_amount": {
            "type": "number",
            "description": "Amount due"
          },
          "amount_paid": {
            "type": "number",
            "description": "Paid so far"
          },
          "balance": {
            "type": "number",
            "description": "Still to pay; worked out when left out"
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "description": "Due date, YYYY-MM-DD"
          },
          "status": {
            "type": "string",
            "description": "\"open\" or \"paid\"; worked out from balance when left out"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_due_id": "D-S1042-T2",
          "uid": "S1042",
          "main_group": "5",
          "sub_group": "A",
          "fee_type": "Tuition, term 2",
          "total_amount": 18500,
          "amount_paid": 10000,
          "due_date": "2026-11-30"
        }
      },
      "PaymentsRecord": {
        "type": "object",
        "title": "Fee payments",
        "description": "Payments received. Key: DESKTOPPAYMENTID.",
        "required": [
          "DESKTOPPAYMENTID",
          "uid"
        ],
        "properties": {
          "DESKTOPPAYMENTID": {
            "type": "string",
            "description": "Your id for this payment"
          },
          "uid": {
            "type": "string",
            "description": "The student's uid (or student_id)"
          },
          "usn": {
            "type": "string",
            "description": "Admission number"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "group_name": {
            "type": "string",
            "description": "Fee group"
          },
          "receipt_id": {
            "type": "string",
            "description": "Receipt number"
          },
          "amount_paid": {
            "type": "number",
            "description": "Amount of this payment"
          },
          "total_amount": {
            "type": "number",
            "description": "Total fee it was paid against"
          },
          "trans_date": {
            "type": "string",
            "format": "date",
            "description": "Payment date, YYYY-MM-DD"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "DESKTOPPAYMENTID": "P-88213",
          "uid": "S1042",
          "receipt_id": "RC/2026/88213",
          "amount_paid": 10000,
          "total_amount": 18500,
          "trans_date": "2026-10-04"
        }
      },
      "AssignmentsRecord": {
        "type": "object",
        "title": "Homework (class)",
        "description": "Homework set for a class or section. Key: desktop_assignment_id.",
        "required": [
          "desktop_assignment_id"
        ],
        "properties": {
          "desktop_assignment_id": {
            "type": "string",
            "description": "Your id for this homework"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "subject": {
            "type": "string",
            "description": "Subject"
          },
          "title": {
            "type": "string",
            "description": "Title"
          },
          "description": {
            "type": "string",
            "description": "What to do"
          },
          "url": {
            "type": "string",
            "description": "Link to a worksheet or file"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "Day it was set, YYYY-MM-DD"
          },
          "submit_date": {
            "type": "string",
            "format": "date",
            "description": "Due date, YYYY-MM-DD"
          },
          "teacher_name": {
            "type": "string",
            "description": "Teacher"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_assignment_id": "H-5A-2026-11-12-MATH",
          "main_group": "5",
          "sub_group": "A",
          "subject": "Mathematics",
          "title": "Fractions",
          "description": "Exercise 4.2, questions 1-10",
          "date": "2026-11-12",
          "submit_date": "2026-11-14",
          "teacher_name": "Mr Iyer"
        }
      },
      "DiaryRecord": {
        "type": "object",
        "title": "Diary (per student)",
        "description": "A teacher's note about one student. Key: DESKTOPDAIRYID.",
        "required": [
          "DESKTOPDAIRYID",
          "STUDENTID"
        ],
        "properties": {
          "DESKTOPDAIRYID": {
            "type": "string",
            "description": "Your id for this note"
          },
          "STUDENTID": {
            "type": "string",
            "description": "The student's uid"
          },
          "DATE": {
            "type": "string",
            "format": "date",
            "description": "Day, YYYY-MM-DD"
          },
          "DAIRYREPORT": {
            "type": "string",
            "description": "The note"
          },
          "teacher_name": {
            "type": "string",
            "description": "Teacher"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "DESKTOPDAIRYID": "N-77120",
          "STUDENTID": "S1042",
          "DATE": "2026-11-12",
          "DAIRYREPORT": "Please send the signed permission slip.",
          "teacher_name": "Mrs Rao"
        }
      },
      "TimetableRecord": {
        "type": "object",
        "title": "Timetable",
        "description": "Periods per class or section. Key: desktop_timetable_id.",
        "required": [
          "desktop_timetable_id"
        ],
        "properties": {
          "desktop_timetable_id": {
            "type": "string",
            "description": "Your id for this period"
          },
          "main_group": {
            "type": "string",
            "description": "Class (grade), for example \"5\" or \"LKG\""
          },
          "sub_group": {
            "type": "string",
            "description": "Section, for example \"A\"; empty for the whole class"
          },
          "day": {
            "type": "string",
            "description": "Day of the week, for example \"Monday\""
          },
          "period": {
            "type": "number",
            "description": "Period number"
          },
          "start_time": {
            "type": "string",
            "description": "HH:MM"
          },
          "end_time": {
            "type": "string",
            "description": "HH:MM"
          },
          "subject": {
            "type": "string",
            "description": "Subject"
          },
          "teacher_name": {
            "type": "string",
            "description": "Teacher"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_timetable_id": "T-5A-MON-1",
          "main_group": "5",
          "sub_group": "A",
          "day": "Monday",
          "period": 1,
          "start_time": "08:30",
          "end_time": "09:15",
          "subject": "English",
          "teacher_name": "Mrs Rao"
        }
      },
      "HolidaysRecord": {
        "type": "object",
        "title": "Holidays",
        "description": "School holidays. Key: desktop_holiday_id.",
        "required": [
          "desktop_holiday_id",
          "date"
        ],
        "properties": {
          "desktop_holiday_id": {
            "type": "string",
            "description": "Your id for this holiday"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "Day, YYYY-MM-DD"
          },
          "title": {
            "type": "string",
            "description": "For example \"Diwali\""
          },
          "description": {
            "type": "string",
            "description": "Details"
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_holiday_id": "HOL-2026-11-01",
          "date": "2026-11-01",
          "title": "Kannada Rajyotsava"
        }
      },
      "EventsRecord": {
        "type": "object",
        "title": "Events",
        "description": "School events (sports day, PTM, exams week). Key: desktop_event_id.",
        "required": [
          "desktop_event_id",
          "date"
        ],
        "properties": {
          "desktop_event_id": {
            "type": "string",
            "description": "Your id for this event"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "Day, YYYY-MM-DD"
          },
          "title": {
            "type": "string",
            "description": "Title"
          },
          "description": {
            "type": "string",
            "description": "Details"
          },
          "type": {
            "type": "string",
            "description": "For example \"ptm\" or \"sports\"; default \"event\""
          },
          "org_id": {
            "type": "string",
            "description": "Your id for the school (optional on records other than school details)"
          },
          "deleted": {
            "type": "boolean",
            "description": "true removes this record (send its key)"
          }
        },
        "additionalProperties": true,
        "example": {
          "desktop_event_id": "EV-PTM-2026-11-22",
          "date": "2026-11-22",
          "title": "Parent-teacher meeting",
          "type": "ptm"
        }
      }
    }
  }
}
