{"info":{"_postman_id":"00000000-0000-0000-0000-000000000001","name":"Forge SIS District API","description":"Comprehensive API for Forge SIS district operations. See the Forge SIS Technical Specification v1.0 §9 and §25.\n\nAuthentication: set the `FORGE_API_KEY` collection variable to a key generated at /admin/api-keys, or `FORGE_SESSION_COOKIE` if you prefer cookie auth.","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json"},"variable":[{"key":"baseUrl","value":"https://api.forgesis.com/v1","type":"string"},{"key":"FORGE_API_KEY","value":"","type":"string"}],"auth":{"type":"bearer","bearer":[{"key":"token","value":"{{FORGE_API_KEY}}","type":"string"}]},"item":[{"name":"General","item":[{"name":"GET /postman.json","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/postman.json","host":["{{baseUrl}}"],"path":["postman.json"]},"description":""}},{"name":"POST /api/platform/v1/webhooks/stripe/billing","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/webhooks/stripe/billing","host":["{{baseUrl}}"],"path":["api","platform","v1","webhooks","stripe","billing"]},"description":""}}]},{"name":"Meta","item":[{"name":"GET /healthz — Liveness probe","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/healthz","host":["{{baseUrl}}"],"path":["healthz"]},"description":"Returns service identity and uptime. Does not hit external dependencies — use /readyz for that."}},{"name":"GET /readyz — Readiness probe","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/readyz","host":["{{baseUrl}}"],"path":["readyz"]},"description":"Actually probes DB and Redis with a per-check 2s timeout. Returns 503 if any hard dependency fails."}},{"name":"GET /version — Build metadata","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/version","host":["{{baseUrl}}"],"path":["version"]},"description":"Returns the git sha, build time, and Node version baked in at container-build time. Used for in-field diagnosis."}}]},{"name":"Auth","item":[{"name":"POST /api/auth/login — Log in with email + password","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/auth/login","host":["{{baseUrl}}"],"path":["api","auth","login"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Returns a session cookie on success. Subject to rate limits and account lockout after repeated failures."}},{"name":"POST /api/auth/login/mfa-verify — Complete MFA login with a TOTP code","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/auth/login/mfa-verify","host":["{{baseUrl}}"],"path":["api","auth","login","mfa-verify"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Second step of the MFA login flow. Consumes the pendingMfaToken returned by /auth/login and validates the TOTP code. Returns the session cookie on success."}},{"name":"POST /api/auth/logout — Log out (revoke the current session)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/api/auth/logout","host":["{{baseUrl}}"],"path":["api","auth","logout"]},"description":"Log out (revoke the current session)"}},{"name":"GET /api/auth/session — Return the current authenticated session, if any","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/auth/session","host":["{{baseUrl}}"],"path":["api","auth","session"]},"description":"Return the current authenticated session, if any"}},{"name":"POST /api/auth/request-password-reset — Request a password reset email","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/auth/request-password-reset","host":["{{baseUrl}}"],"path":["api","auth","request-password-reset"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Always returns 200 — the response does not reveal whether the email exists."}},{"name":"POST /api/auth/complete-password-reset — Complete a password reset using an emailed token","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/auth/complete-password-reset","host":["{{baseUrl}}"],"path":["api","auth","complete-password-reset"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Complete a password reset using an emailed token"}},{"name":"POST /api/auth/complete-invite — Complete a user invite (set initial password)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/auth/complete-invite","host":["{{baseUrl}}"],"path":["api","auth","complete-invite"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Complete a user invite (set initial password)"}},{"name":"POST /me/push-token — Register an Expo push token for the signed-in user","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/me/push-token","host":["{{baseUrl}}"],"path":["me","push-token"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stores the Expo push token so the backend can send push notifications to this device. Call this once after login. The token is scoped to the district."}},{"name":"DELETE /me/push-token — Remove the push token for the signed-in user","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/me/push-token","host":["{{baseUrl}}"],"path":["me","push-token"]},"description":"Call on logout so the device no longer receives push notifications."}}]},{"name":"Auth · SSO","item":[{"name":"GET /auth/saml/metadata — SAML 2.0 SP metadata","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/auth/saml/metadata","host":["{{baseUrl}}"],"path":["auth","saml","metadata"]},"description":"Returns SP EntityDescriptor XML for IdP configuration."}},{"name":"GET /auth/saml/initiate — Initiate SAML 2.0 SSO for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/auth/saml/initiate","host":["{{baseUrl}}"],"path":["auth","saml","initiate"]},"description":"Redirects browser to the district IdP with an encoded AuthnRequest."}},{"name":"POST /auth/saml/callback — SAML 2.0 Assertion Consumer Service (ACS)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/auth/saml/callback","host":["{{baseUrl}}"],"path":["auth","saml","callback"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Receives SAMLResponse from IdP and establishes a Forge session."}},{"name":"GET /auth/oidc/authorize — Initiate OIDC SSO for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/auth/oidc/authorize","host":["{{baseUrl}}"],"path":["auth","oidc","authorize"]},"description":"Redirects browser to the district OIDC IdP with PKCE parameters."}},{"name":"GET /auth/oidc/callback — OIDC authorization code callback","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/auth/oidc/callback","host":["{{baseUrl}}"],"path":["auth","oidc","callback"]},"description":"Receives authorization code from IdP, exchanges for tokens, creates session."}},{"name":"GET /auth/classlink/authorize — Initiate ClassLink SSO for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/auth/classlink/authorize","host":["{{baseUrl}}"],"path":["auth","classlink","authorize"]},"description":"Redirects browser to ClassLink IdP for the district tenant."}},{"name":"GET /auth/classlink/callback — ClassLink authorization code callback","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/auth/classlink/callback","host":["{{baseUrl}}"],"path":["auth","classlink","callback"]},"description":"Receives code from ClassLink, exchanges for tokens, creates Forge session."}}]},{"name":"District · SSO","item":[{"name":"GET /district/sso — Get SSO provider configurations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/district/sso","host":["{{baseUrl}}"],"path":["district","sso"]},"description":"Get SSO provider configurations"}},{"name":"POST /district/sso/saml — Save SAML 2.0 configuration","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/district/sso/saml","host":["{{baseUrl}}"],"path":["district","sso","saml"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stores SAML IdP settings in District.settings.sso.saml. No migration required."}},{"name":"POST /district/sso/oidc — Save OIDC configuration","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/district/sso/oidc","host":["{{baseUrl}}"],"path":["district","sso","oidc"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stores OIDC client settings in District.settings.sso.oidc."}},{"name":"POST /district/sso/classlink — Save ClassLink SSO configuration","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/district/sso/classlink","host":["{{baseUrl}}"],"path":["district","sso","classlink"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stores ClassLink tenant settings in District.settings.sso.classlink."}}]},{"name":"Marketing","item":[{"name":"GET /marketing/plans — List active pricing tiers for the public /pricing page","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/marketing/plans","host":["{{baseUrl}}"],"path":["marketing","plans"]},"description":"List active pricing tiers for the public /pricing page"}},{"name":"POST /marketing/checkout — Create a Stripe Checkout Session for a plan","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/marketing/checkout","host":["{{baseUrl}}"],"path":["marketing","checkout"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Anonymous endpoint that opens a hosted Stripe Checkout flow for a prospect. The webhook handler at /api/platform/v1/webhooks/stripe/billing records the completed checkout for manual district provisioning. Requires STRIPE_PRICE_<UPPERCASE_CODE> env var per plan."}},{"name":"GET /marketing/event-catalog — Event-type catalog with example payloads","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/marketing/event-catalog","host":["{{baseUrl}}"],"path":["marketing","event-catalog"]},"description":"Public reference for integrators. Walks the platform event registry and emits one example payload per type so developers can prototype receivers without reading TypeScript schemas."}},{"name":"GET /marketing/content — Bulk-fetch active marketing copy blocks (optionally by slug list)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/marketing/content","host":["{{baseUrl}}"],"path":["marketing","content"]},"description":"Bulk-fetch active marketing copy blocks (optionally by slug list)"}}]},{"name":"API Keys","item":[{"name":"GET /api-keys/usage-summary — District-wide API usage rollup for the last 7 days","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api-keys/usage-summary","host":["{{baseUrl}}"],"path":["api-keys","usage-summary"]},"description":"Per-day totals across every active key in the district + per-key totals. Daily totals are summed from the same Redis counters the per-key sparkline uses; per-key totals are the sum of that key's 7-day series."}},{"name":"GET /api-keys — List API keys for the current district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api-keys","host":["{{baseUrl}}"],"path":["api-keys"]},"description":"List API keys for the current district"}},{"name":"POST /api-keys — Create a new API key for the current district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api-keys","host":["{{baseUrl}}"],"path":["api-keys"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Generates a cryptographically random key. The plaintext is returned ONCE in the `key` field and cannot be retrieved again."}},{"name":"DELETE /api-keys/{id} — Revoke an API key (soft-delete via revokedAt)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/api-keys/{id}","host":["{{baseUrl}}"],"path":["api-keys","{id}"]},"description":"Revoke an API key (soft-delete via revokedAt)"}}]},{"name":"Webhooks","item":[{"name":"GET /webhooks — List webhooks for the current district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"description":"List webhooks for the current district"}},{"name":"POST /webhooks — Create a webhook subscription","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/webhooks","host":["{{baseUrl}}"],"path":["webhooks"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Generates a signing secret. The plaintext is returned once in the `signingSecret` field and is never returned again. Use it to verify the `X-Forge-Signature` header on each delivery."}},{"name":"DELETE /webhooks/{id} — Delete (soft) a webhook","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/webhooks/{id}","host":["{{baseUrl}}"],"path":["webhooks","{id}"]},"description":"Delete (soft) a webhook"}},{"name":"GET /webhooks/{id}/deliveries — List recent deliveries for a webhook","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/webhooks/{id}/deliveries","host":["{{baseUrl}}"],"path":["webhooks","{id}","deliveries"]},"description":"List recent deliveries for a webhook"}},{"name":"POST /webhooks/{id}/deliveries/{deliveryId}/resend — Re-enqueue a past delivery (typically a failed one)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/webhooks/{id}/deliveries/{deliveryId}/resend","host":["{{baseUrl}}"],"path":["webhooks","{id}","deliveries","{deliveryId}","resend"]},"description":"Looks up the original event by id and queues a fresh delivery to this webhook. The receiver will see the same payload + eventType as the first attempt; the new attempt gets a new WebhookDelivery row with attempt=N+1."}},{"name":"POST /webhooks/{id}/test — Fire a synthetic delivery so the operator can verify their receiver","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/webhooks/{id}/test","host":["{{baseUrl}}"],"path":["webhooks","{id}","test"]},"description":"Enqueues a `WebhookTest` event addressed only to this webhook. The receiver gets a normal, signed delivery with eventType=WebhookTest. Useful as a \"ping\" during integration setup."}},{"name":"GET /webhooks/event-types — Event types that webhooks can subscribe to","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/webhooks/event-types","host":["{{baseUrl}}"],"path":["webhooks","event-types"]},"description":"Event types that webhooks can subscribe to"}},{"name":"POST /webhooks/sendgrid/{districtId}","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/webhooks/sendgrid/{districtId}","host":["{{baseUrl}}"],"path":["webhooks","sendgrid","{districtId}"]},"description":"SendGrid delivery webhook (token-authed via ?tok=)."}},{"name":"POST /webhooks/twilio/{districtId}","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/webhooks/twilio/{districtId}","host":["{{baseUrl}}"],"path":["webhooks","twilio","{districtId}"]},"description":"Twilio status webhook (HMAC-SHA1 authed)."}},{"name":"POST /payments/webhook/stripe","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/payments/webhook/stripe","host":["{{baseUrl}}"],"path":["payments","webhook","stripe"]},"description":"Stripe payment-event webhook (HMAC-SHA256 via Stripe-Signature header)."}}]},{"name":"Students","item":[{"name":"GET /students — List students","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students","host":["{{baseUrl}}"],"path":["students"]},"description":"Returns a paginated list of students in the current district."}},{"name":"POST /students — Create a student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/students","host":["{{baseUrl}}"],"path":["students"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Creates a new student record. Emits StudentEnrolled when paired with an enrollment."}},{"name":"GET /students/{id} — Get student by ID","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}","host":["{{baseUrl}}"],"path":["students","{id}"]},"description":"Returns a single student record. Caller must have student.read permission."}},{"name":"GET /students/{id}/events — Get a student's event history (audit trail)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/events","host":["{{baseUrl}}"],"path":["students","{id}","events"]},"description":"Get a student's event history (audit trail)"}}]},{"name":"Persons","item":[{"name":"GET /persons — List persons (students, guardians, staff, alumni, contacts)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/persons","host":["{{baseUrl}}"],"path":["persons"]},"description":"List persons (students, guardians, staff, alumni, contacts)"}},{"name":"GET /persons/{id} — Get a single person record","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/persons/{id}","host":["{{baseUrl}}"],"path":["persons","{id}"]},"description":"Get a single person record"}},{"name":"POST /persons/import — Bulk CSV import — preview or apply (upserts by localId)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/persons/import","host":["{{baseUrl}}"],"path":["persons","import"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Upload a CSV of person records. Use `mode=preview` (default) to validate without committing. Use `mode=apply` to upsert all valid rows. Invalid rows are reported per-row and skipped. Upsert key: (districtId, localId)."}},{"name":"PATCH /persons/bulk — Bulk update persons matching a filter","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/persons/bulk","host":["{{baseUrl}}"],"path":["persons","bulk"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update one or more safe fields on all persons matching the filter. Allowed fields: isActive, email, phoneMobile, phoneHome, gender. PII fields (name, DOB) require individual edits."}},{"name":"GET /persons/duplicates — Detect potential duplicate person records (fuzzy matching)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/persons/duplicates","host":["{{baseUrl}}"],"path":["persons","duplicates"]},"description":"Detect potential duplicate person records (fuzzy matching)"}},{"name":"POST /persons/{id}/merge/{otherId} — Merge two person records (survivor absorbs the other)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/persons/{id}/merge/{otherId}","host":["{{baseUrl}}"],"path":["persons","{id}","merge","{otherId}"]},"description":"Re-points FK relations from the absorbed person to the survivor, fills blank fields on the survivor from the absorbed record, then soft-deletes the absorbed person. Student records are not mergeable via API — contact YRC support."}}]},{"name":"Guardians","item":[{"name":"GET /guardians — List guardians","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/guardians","host":["{{baseUrl}}"],"path":["guardians"]},"description":"List guardians"}},{"name":"POST /guardians — Create guardian","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/guardians","host":["{{baseUrl}}"],"path":["guardians"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create guardian"}},{"name":"GET /guardians/{id} — Get guardian","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/guardians/{id}","host":["{{baseUrl}}"],"path":["guardians","{id}"]},"description":"Get guardian"}},{"name":"GET /guardians/{id}/students — List students linked to this guardian","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/guardians/{id}/students","host":["{{baseUrl}}"],"path":["guardians","{id}","students"]},"description":"List students linked to this guardian"}},{"name":"POST /guardians/{id}/students — Link a guardian to a student (emits GuardianLinked)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/guardians/{id}/students","host":["{{baseUrl}}"],"path":["guardians","{id}","students"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Link a guardian to a student (emits GuardianLinked)"}},{"name":"DELETE /guardianships/{id} — Unlink a guardianship (emits GuardianUnlinked)","request":{"method":"DELETE","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/guardianships/{id}","host":["{{baseUrl}}"],"path":["guardianships","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Unlink a guardianship (emits GuardianUnlinked)"}}]},{"name":"Custody","item":[{"name":"GET /students/{studentId}/custody-orders — List custody orders for a student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{studentId}/custody-orders","host":["{{baseUrl}}"],"path":["students","{studentId}","custody-orders"]},"description":"List custody orders for a student"}},{"name":"POST /students/{studentId}/custody-orders — Record a new custody order for a student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/students/{studentId}/custody-orders","host":["{{baseUrl}}"],"path":["students","{studentId}","custody-orders"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a new custody order for a student"}},{"name":"GET /custody-orders/{id} — Get a single custody order by ID","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/custody-orders/{id}","host":["{{baseUrl}}"],"path":["custody-orders","{id}"]},"description":"Get a single custody order by ID"}},{"name":"PATCH /custody-orders/{id} — Update custody order metadata","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/custody-orders/{id}","host":["{{baseUrl}}"],"path":["custody-orders","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update custody order metadata"}},{"name":"POST /custody-orders/{id}/revoke — Revoke a custody order (soft-expire with reason)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/custody-orders/{id}/revoke","host":["{{baseUrl}}"],"path":["custody-orders","{id}","revoke"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Revoke a custody order (soft-expire with reason)"}},{"name":"GET /students/{studentId}/pickup-authorized — Check pickup authorization for a person + student pair","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{studentId}/pickup-authorized","host":["{{baseUrl}}"],"path":["students","{studentId}","pickup-authorized"]},"description":"Check pickup authorization for a person + student pair"}}]},{"name":"Staff","item":[{"name":"GET /staff — List staff (and faculty) records","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/staff","host":["{{baseUrl}}"],"path":["staff"]},"description":"List staff (and faculty) records"}},{"name":"POST /staff — Create a staff record","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/staff","host":["{{baseUrl}}"],"path":["staff"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a staff record"}},{"name":"GET /staff/{id} — Get a staff record","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/staff/{id}","host":["{{baseUrl}}"],"path":["staff","{id}"]},"description":"Get a staff record"}}]},{"name":"Enrollments","item":[{"name":"GET /enrollments — List enrollments (filter by person, organization, or active-only)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/enrollments","host":["{{baseUrl}}"],"path":["enrollments"]},"description":"List enrollments (filter by person, organization, or active-only)"}},{"name":"POST /enrollments — Create an enrollment (emits StudentEnrolled for students)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/enrollments","host":["{{baseUrl}}"],"path":["enrollments"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create an enrollment (emits StudentEnrolled for students)"}},{"name":"GET /enrollments/{id} — Get a single enrollment","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/enrollments/{id}","host":["{{baseUrl}}"],"path":["enrollments","{id}"]},"description":"Get a single enrollment"}},{"name":"POST /enrollments/{id}/end — End an enrollment (emits StudentWithdrawn for students)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/enrollments/{id}/end","host":["{{baseUrl}}"],"path":["enrollments","{id}","end"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"End an enrollment (emits StudentWithdrawn for students)"}}]},{"name":"Scheduling","item":[{"name":"GET /organizations — List organizations (school, department, grade, homeroom, program)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/organizations","host":["{{baseUrl}}"],"path":["organizations"]},"description":"List organizations (school, department, grade, homeroom, program)"}},{"name":"POST /organizations — Create an organization","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/organizations","host":["{{baseUrl}}"],"path":["organizations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create an organization"}},{"name":"GET /organizations/{id} — Get an organization","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/organizations/{id}","host":["{{baseUrl}}"],"path":["organizations","{id}"]},"description":"Get an organization"}},{"name":"PATCH /organizations/{id} — Update organization","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/organizations/{id}","host":["{{baseUrl}}"],"path":["organizations","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update organization"}},{"name":"GET /schools — List schools in the current district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/schools","host":["{{baseUrl}}"],"path":["schools"]},"description":"List schools in the current district"}},{"name":"POST /schools — Create a school (also creates its backing Organization row)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/schools","host":["{{baseUrl}}"],"path":["schools"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a school (also creates its backing Organization row)"}},{"name":"GET /schools/{id} — Get a school","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/schools/{id}","host":["{{baseUrl}}"],"path":["schools","{id}"]},"description":"Get a school"}},{"name":"PATCH /schools/{id} — Update a school","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/schools/{id}","host":["{{baseUrl}}"],"path":["schools","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a school"}},{"name":"GET /school-years — List school years","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/school-years","host":["{{baseUrl}}"],"path":["school-years"]},"description":"List school years"}},{"name":"POST /school-years — Create a school year","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/school-years","host":["{{baseUrl}}"],"path":["school-years"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a school year"}},{"name":"GET /school-years/current — Get the active school year for this district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/school-years/current","host":["{{baseUrl}}"],"path":["school-years","current"]},"description":"Get the active school year for this district"}},{"name":"GET /school-years/{id} — Get school year","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/school-years/{id}","host":["{{baseUrl}}"],"path":["school-years","{id}"]},"description":"Get school year"}},{"name":"PATCH /school-years/{id} — Update school year","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/school-years/{id}","host":["{{baseUrl}}"],"path":["school-years","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update school year"}},{"name":"POST /school-years/{id}/actions/set-current — Mark a school year as current (clears the flag on others)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/school-years/{id}/actions/set-current","host":["{{baseUrl}}"],"path":["school-years","{id}","actions","set-current"]},"description":"Mark a school year as current (clears the flag on others)"}},{"name":"GET /terms — List terms (optionally filter by school year or type)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/terms","host":["{{baseUrl}}"],"path":["terms"]},"description":"List terms (optionally filter by school year or type)"}},{"name":"POST /terms — Create a term","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/terms","host":["{{baseUrl}}"],"path":["terms"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a term"}},{"name":"GET /terms/{id} — Get a term","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/terms/{id}","host":["{{baseUrl}}"],"path":["terms","{id}"]},"description":"Get a term"}},{"name":"PATCH /terms/{id} — Update a term","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/terms/{id}","host":["{{baseUrl}}"],"path":["terms","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a term"}},{"name":"GET /course-requests — List course requests","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/course-requests","host":["{{baseUrl}}"],"path":["course-requests"]},"description":"List course requests"}},{"name":"POST /course-requests — Create a course request","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/course-requests","host":["{{baseUrl}}"],"path":["course-requests"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a course request"}},{"name":"GET /course-requests/{id} — Get a course request","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/course-requests/{id}","host":["{{baseUrl}}"],"path":["course-requests","{id}"]},"description":"Get a course request"}},{"name":"PATCH /course-requests/{id} — Update a course request","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/course-requests/{id}","host":["{{baseUrl}}"],"path":["course-requests","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a course request"}},{"name":"DELETE /course-requests/{id} — Delete a course request","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/course-requests/{id}","host":["{{baseUrl}}"],"path":["course-requests","{id}"]},"description":"Delete a course request"}},{"name":"GET /scheduling/master-schedule — Master schedule for a term (sections + live conflicts)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/scheduling/master-schedule","host":["{{baseUrl}}"],"path":["scheduling","master-schedule"]},"description":"Master schedule for a term (sections + live conflicts)"}},{"name":"GET /scheduling/conflicts — Detect master-schedule conflicts for a term","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/scheduling/conflicts","host":["{{baseUrl}}"],"path":["scheduling","conflicts"]},"description":"Detect master-schedule conflicts for a term"}},{"name":"POST /scheduling/propose — Run the CSP solver and return a proposed assignment (no writes)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/scheduling/propose","host":["{{baseUrl}}"],"path":["scheduling","propose"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Run the CSP solver and return a proposed assignment (no writes)"}},{"name":"POST /scheduling/publish — Apply a proposal: create participations + mark course requests scheduled + emit StudentScheduled events","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/scheduling/publish","host":["{{baseUrl}}"],"path":["scheduling","publish"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Apply a proposal: create participations + mark course requests scheduled + emit StudentScheduled events"}}]},{"name":"Admin","item":[{"name":"GET /admin/users — List district users","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/admin/users","host":["{{baseUrl}}"],"path":["admin","users"]},"description":"List district users"}},{"name":"GET /admin/users/{id} — Get a single user","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/admin/users/{id}","host":["{{baseUrl}}"],"path":["admin","users","{id}"]},"description":"Get a single user"}},{"name":"POST /admin/users/invite — Invite a new user (creates User row + issues invite token)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/admin/users/invite","host":["{{baseUrl}}"],"path":["admin","users","invite"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Invite a new user (creates User row + issues invite token)"}},{"name":"POST /admin/users/{id}/status — Set a user status (active / disabled)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/admin/users/{id}/status","host":["{{baseUrl}}"],"path":["admin","users","{id}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Disabling a user revokes all their active sessions."}},{"name":"POST /admin/users/{id}/send-password-reset — Issue a password-reset token for a user (admin action)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/admin/users/{id}/send-password-reset","host":["{{baseUrl}}"],"path":["admin","users","{id}","send-password-reset"]},"description":"Issue a password-reset token for a user (admin action)"}},{"name":"POST /admin/users/{id}/roles — Assign a role (district- or school-scoped) to a user","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/admin/users/{id}/roles","host":["{{baseUrl}}"],"path":["admin","users","{id}","roles"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assign a role (district- or school-scoped) to a user"}},{"name":"DELETE /admin/users/{id}/roles/{userRoleId} — Revoke a role binding from a user","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/admin/users/{id}/roles/{userRoleId}","host":["{{baseUrl}}"],"path":["admin","users","{id}","roles","{userRoleId}"]},"description":"Revoke a role binding from a user"}},{"name":"GET /admin/roles — List the canonical role catalog","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/admin/roles","host":["{{baseUrl}}"],"path":["admin","roles"]},"description":"List the canonical role catalog"}}]},{"name":"Attendance","item":[{"name":"POST /attendance — Bulk mark attendance","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/attendance","host":["{{baseUrl}}"],"path":["attendance"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Each mark produces one AttendanceMarked event; projections are rebuilt asynchronously."}},{"name":"GET /attendance — Query attendance days (projection)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/attendance","host":["{{baseUrl}}"],"path":["attendance"]},"description":"Reads from projection_attendance_days. Projection is eventually consistent — fresh writes may take a few seconds to reflect."}}]},{"name":"Events","item":[{"name":"GET /events — Query the event log","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/events","host":["{{baseUrl}}"],"path":["events"]},"description":"Filter by eventType, subjectId, actorId, and time range. The event log is append-only (spec §4 rule 7, §8)."}},{"name":"GET /events/{id} — Get a single event by id","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/events/{id}","host":["{{baseUrl}}"],"path":["events","{id}"]},"description":"Get a single event by id"}}]},{"name":"Compliance","item":[{"name":"GET /audit-log — Query the district audit log","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/audit-log","host":["{{baseUrl}}"],"path":["audit-log"]},"description":"Security-sensitive audit log (spec §4 rule 7). Distinct from the business event log at /events."}},{"name":"GET /compliance/rules — List the compliance rules available to this district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/rules","host":["{{baseUrl}}"],"path":["compliance","rules"]},"description":"List the compliance rules available to this district"}},{"name":"POST /compliance/rules/run — Evaluate all NJ rules against current district state","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/compliance/rules/run","host":["{{baseUrl}}"],"path":["compliance","rules","run"]},"description":"Runs every rule in the NJ rule set and returns a consolidated report of findings grouped by severity and rule id."}},{"name":"GET /compliance/smids/missing — List active students without a SMID","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/smids/missing","host":["{{baseUrl}}"],"path":["compliance","smids","missing"]},"description":"List active students without a SMID"}},{"name":"POST /compliance/smids/{id} — Assign a SMID to a student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/compliance/smids/{id}","host":["{{baseUrl}}"],"path":["compliance","smids","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assign a SMID to a student"}},{"name":"POST /compliance/smids/generate-missing — Generate placeholder SMIDs for every active student without one","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/compliance/smids/generate-missing","host":["{{baseUrl}}"],"path":["compliance","smids","generate-missing"]},"description":"Uses a deterministic `NJ########` prefix. These are placeholders until the official NJSMART-issued SMIDs are imported. Safe to re-run — only assigns where smid is currently null."}},{"name":"GET /compliance/reports — List generated state reports","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/reports","host":["{{baseUrl}}"],"path":["compliance","reports"]},"description":"List generated state reports"}},{"name":"GET /compliance/reports/available — List state-report adapters available for the calling district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/reports/available","host":["{{baseUrl}}"],"path":["compliance","reports","available"]},"description":"Reads the district's state code and returns the registered adapters for that state. Used by the admin UI to render generation buttons dynamically."}},{"name":"GET /compliance/smids/audit — Audit SMID coverage for the calling district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/smids/audit","host":["{{baseUrl}}"],"path":["compliance","smids","audit"]},"description":"Returns counts of students on placeholder (NJ########) IDs and students with no SMID. Used by the UI to show a \"ready to submit\" badge and by the strict-generation flow to block submission."}},{"name":"GET /compliance/reports/{id} — Get a state-report record","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/reports/{id}","host":["{{baseUrl}}"],"path":["compliance","reports","{id}"]},"description":"Get a state-report record"}},{"name":"GET /compliance/instructional-time — Per-school instructional-time breakdown","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/compliance/instructional-time","host":["{{baseUrl}}"],"path":["compliance","instructional-time"]},"description":"Evaluates the INSTRUCTIONAL_TIME_RULE and returns the per-school breakdown the rule computed: days counted, days projected, minutes counted, minutes projected, short-day list, findings. Designed for the drill-down dashboard."}}]},{"name":"Courses","item":[{"name":"GET /courses — List courses in the catalog","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/courses","host":["{{baseUrl}}"],"path":["courses"]},"description":"List courses in the catalog"}},{"name":"POST /courses — Create a course","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courses","host":["{{baseUrl}}"],"path":["courses"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a course"}},{"name":"GET /courses/{id} — Get a course","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/courses/{id}","host":["{{baseUrl}}"],"path":["courses","{id}"]},"description":"Get a course"}},{"name":"PATCH /courses/{id} — Update a course","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/courses/{id}","host":["{{baseUrl}}"],"path":["courses","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a course"}}]},{"name":"Sections","item":[{"name":"GET /sections — List sections","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sections","host":["{{baseUrl}}"],"path":["sections"]},"description":"Filter by term, course, organization, or teacher. Teacher filter returns sections where the person is a primary or co-teacher in an active participation."}},{"name":"POST /sections — Create a section (emits SectionCreated, optionally TeacherAssignedToSection)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sections","host":["{{baseUrl}}"],"path":["sections"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a section (emits SectionCreated, optionally TeacherAssignedToSection)"}},{"name":"GET /sections/{id} — Get a section","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sections/{id}","host":["{{baseUrl}}"],"path":["sections","{id}"]},"description":"Get a section"}},{"name":"PATCH /sections/{id} — Update a section (emits SectionScheduleChanged if the schedule changes)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sections/{id}","host":["{{baseUrl}}"],"path":["sections","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a section (emits SectionScheduleChanged if the schedule changes)"}},{"name":"GET /sections/{id}/roster — Get the active roster for a section","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sections/{id}/roster","host":["{{baseUrl}}"],"path":["sections","{id}","roster"]},"description":"Get the active roster for a section"}},{"name":"POST /participations — Add a person to a section (student, teacher, aide, observer)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/participations","host":["{{baseUrl}}"],"path":["participations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Emits StudentAddedToSection for students, TeacherAssignedToSection for PRIMARY_TEACHER/CO_TEACHER."}},{"name":"POST /participations/{id}/end — End a participation (emits StudentRemovedFromSection for students)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/participations/{id}/end","host":["{{baseUrl}}"],"path":["participations","{id}","end"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"End a participation (emits StudentRemovedFromSection for students)"}}]},{"name":"Gradebook","item":[{"name":"GET /assignments — List assignments","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assignments","host":["{{baseUrl}}"],"path":["assignments"]},"description":"List assignments"}},{"name":"POST /assignments — Create an assignment (emits AssignmentCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assignments","host":["{{baseUrl}}"],"path":["assignments"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create an assignment (emits AssignmentCreated)"}},{"name":"GET /assignments/{id} — Get an assignment","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assignments/{id}","host":["{{baseUrl}}"],"path":["assignments","{id}"]},"description":"Get an assignment"}},{"name":"PATCH /assignments/{id} — Update an assignment","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assignments/{id}","host":["{{baseUrl}}"],"path":["assignments","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update an assignment"}},{"name":"GET /assignments/{id}/scores — List scores for an assignment","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assignments/{id}/scores","host":["{{baseUrl}}"],"path":["assignments","{id}","scores"]},"description":"List scores for an assignment"}},{"name":"POST /assignments/{id}/scores — Bulk enter scores (emits AssignmentScored per student)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assignments/{id}/scores","host":["{{baseUrl}}"],"path":["assignments","{id}","scores"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Bulk enter scores (emits AssignmentScored per student)"}},{"name":"GET /grades/current — Query the section-grade projection","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/grades/current","host":["{{baseUrl}}"],"path":["grades","current"]},"description":"Reads from projection_section_grades. Eventually consistent — freshly entered scores may take a few seconds to reflect."}},{"name":"GET /sections/{id}/gradebook — Complete gradebook view for a section","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sections/{id}/gradebook","host":["{{baseUrl}}"],"path":["sections","{id}","gradebook"]},"description":"Returns the section, its active student roster, all assignments, and every score. Suitable for the teacher portal gradebook page."}},{"name":"POST /sections/{id}/actions/publish-grades — Publish final grades for the term (emits SectionGradePosted per student)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sections/{id}/actions/publish-grades","host":["{{baseUrl}}"],"path":["sections","{id}","actions","publish-grades"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Publish final grades for the term (emits SectionGradePosted per student)"}}]},{"name":"Parent Portal","item":[{"name":"GET /parent/notification-preferences — Get notification preferences for the signed-in guardian","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/notification-preferences","host":["{{baseUrl}}"],"path":["parent","notification-preferences"]},"description":"Get notification preferences for the signed-in guardian"}},{"name":"PATCH /parent/notification-preferences — Update notification preferences for the signed-in guardian","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/parent/notification-preferences","host":["{{baseUrl}}"],"path":["parent","notification-preferences"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update notification preferences for the signed-in guardian"}},{"name":"GET /parent/students — List students linked to the signed-in guardian","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students","host":["{{baseUrl}}"],"path":["parent","students"]},"description":"List students linked to the signed-in guardian"}},{"name":"GET /parent/students/{id}/attendance — Attendance days for one of the guardian's students","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/attendance","host":["{{baseUrl}}"],"path":["parent","students","{id}","attendance"]},"description":"Attendance days for one of the guardian's students"}},{"name":"GET /parent/students/{id}/grades — Current grades for one of the guardian's students","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/grades","host":["{{baseUrl}}"],"path":["parent","students","{id}","grades"]},"description":"Current grades for one of the guardian's students"}},{"name":"GET /parent/students/{id}/assignments — Upcoming + recent assignments for one of the guardian's students","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/assignments","host":["{{baseUrl}}"],"path":["parent","students","{id}","assignments"]},"description":"Upcoming + recent assignments for one of the guardian's students"}},{"name":"GET /parent/students/{id} — Student summary card (attendance rate + GPA + current sections)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}","host":["{{baseUrl}}"],"path":["parent","students","{id}"]},"description":"Student summary card (attendance rate + GPA + current sections)"}},{"name":"GET /parent/students/{id}/schedule — Current schedule for one of the guardian's students","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/schedule","host":["{{baseUrl}}"],"path":["parent","students","{id}","schedule"]},"description":"Current schedule for one of the guardian's students"}},{"name":"GET /parent/inbox — Messages addressed to the signed-in guardian","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/inbox","host":["{{baseUrl}}"],"path":["parent","inbox"]},"description":"Messages addressed to the signed-in guardian"}},{"name":"GET /parent/students/{id}/medications — Active medications + recent doses for a guardian's student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/medications","host":["{{baseUrl}}"],"path":["parent","students","{id}","medications"]},"description":"Active medications + recent doses for a guardian's student"}},{"name":"GET /parent/students/{id}/screenings — Recent health screenings for a guardianed student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/screenings","host":["{{baseUrl}}"],"path":["parent","students","{id}","screenings"]},"description":"Recent health screenings for a guardianed student"}},{"name":"GET /parent/students/{id}/transportation — A guardianed student's bus assignment + any alternate pickups","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/transportation","host":["{{baseUrl}}"],"path":["parent","students","{id}","transportation"]},"description":"A guardianed student's bus assignment + any alternate pickups"}},{"name":"POST /parent/students/{id}/alternate-pickups — Guardian opens an alternate-pickup request (emits AlternatePickupRequested)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/parent/students/{id}/alternate-pickups","host":["{{baseUrl}}"],"path":["parent","students","{id}","alternate-pickups"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Guardian opens an alternate-pickup request (emits AlternatePickupRequested)"}},{"name":"GET /parent/students/{id}/meal-service — Guardianed student's meal account + eligibility + recent activity","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/meal-service","host":["{{baseUrl}}"],"path":["parent","students","{id}","meal-service"]},"description":"Guardianed student's meal account + eligibility + recent activity"}},{"name":"POST /parent/students/{id}/meal-service/fund — Guardian adds funds to a student's meal account (emits MealAccountFunded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/parent/students/{id}/meal-service/fund","host":["{{baseUrl}}"],"path":["parent","students","{id}","meal-service","fund"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Guardian adds funds to a student's meal account (emits MealAccountFunded)"}},{"name":"POST /parent/meal-service/applications — Submit a household meal-benefits application","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/parent/meal-service/applications","host":["{{baseUrl}}"],"path":["parent","meal-service","applications"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Applicant must be the signed-in guardian. Each student member must be a student this guardian is linked to."}},{"name":"GET /parent/students/{id}/fees — Guardianed student's fees — balance, open charges, payment history","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/parent/students/{id}/fees","host":["{{baseUrl}}"],"path":["parent","students","{id}","fees"]},"description":"Guardianed student's fees — balance, open charges, payment history"}},{"name":"POST /parent/fees/{id}/pay — Finalize an online (Stripe) payment against a fee (emits FeePaid)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/parent/fees/{id}/pay","host":["{{baseUrl}}"],"path":["parent","fees","{id}","pay"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Called after the front end confirms a Stripe PaymentIntent. We record the payment, finalize status, and bump the ledger. The webhook handler is idempotent against `processorIntentId`."}}]},{"name":"Student Portal","item":[{"name":"GET /student/me — Signed-in student profile","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me","host":["{{baseUrl}}"],"path":["student","me"]},"description":"Signed-in student profile"}},{"name":"GET /student/me/schedule — Signed-in student's current schedule","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/schedule","host":["{{baseUrl}}"],"path":["student","me","schedule"]},"description":"Signed-in student's current schedule"}},{"name":"GET /student/me/attendance — Signed-in student's attendance history","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/attendance","host":["{{baseUrl}}"],"path":["student","me","attendance"]},"description":"Signed-in student's attendance history"}},{"name":"GET /student/me/grades — Signed-in student's current grades","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/grades","host":["{{baseUrl}}"],"path":["student","me","grades"]},"description":"Signed-in student's current grades"}},{"name":"GET /student/me/assignments — Signed-in student's upcoming + recent assignments","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/assignments","host":["{{baseUrl}}"],"path":["student","me","assignments"]},"description":"Signed-in student's upcoming + recent assignments"}},{"name":"GET /student/me/medications — The signed-in student's active medications + recent doses","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/medications","host":["{{baseUrl}}"],"path":["student","me","medications"]},"description":"The signed-in student's active medications + recent doses"}},{"name":"GET /student/me/screenings — The signed-in student's recent health screenings","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/screenings","host":["{{baseUrl}}"],"path":["student","me","screenings"]},"description":"The signed-in student's recent health screenings"}},{"name":"GET /student/me/transportation — The signed-in student's bus assignment + any alternate pickups","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/transportation","host":["{{baseUrl}}"],"path":["student","me","transportation"]},"description":"The signed-in student's bus assignment + any alternate pickups"}},{"name":"GET /student/me/meal-service — Signed-in student's meal account + recent activity","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/meal-service","host":["{{baseUrl}}"],"path":["student","me","meal-service"]},"description":"Signed-in student's meal account + recent activity"}},{"name":"GET /student/me/fees — Signed-in student's fees (read-only)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/fees","host":["{{baseUrl}}"],"path":["student","me","fees"]},"description":"Signed-in student's fees (read-only)"}}]},{"name":"Health","item":[{"name":"GET /health/visits — List nurse visits","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/visits","host":["{{baseUrl}}"],"path":["health","visits"]},"description":"List nurse visits"}},{"name":"POST /health/visits — Record a nurse visit (emits HealthEncounter)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/visits","host":["{{baseUrl}}"],"path":["health","visits"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a nurse visit (emits HealthEncounter)"}},{"name":"GET /health/visits/{id} — Get a nurse visit","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/visits/{id}","host":["{{baseUrl}}"],"path":["health","visits","{id}"]},"description":"Get a nurse visit"}},{"name":"GET /health/medications — List medication prescriptions","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/medications","host":["{{baseUrl}}"],"path":["health","medications"]},"description":"List medication prescriptions"}},{"name":"POST /health/medications — Record a medication prescription","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/medications","host":["{{baseUrl}}"],"path":["health","medications"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a medication prescription"}},{"name":"GET /health/medications/due — Scheduled doses due today","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/medications/due","host":["{{baseUrl}}"],"path":["health","medications","due"]},"description":"Returns one row per (med × scheduled time) for active scheduled orders today. PRN orders are not included."}},{"name":"GET /health/medications/{id} — Get a medication","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/medications/{id}","host":["{{baseUrl}}"],"path":["health","medications","{id}"]},"description":"Get a medication"}},{"name":"PATCH /health/medications/{id} — Update a medication order (cannot change controlled-substance class)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/medications/{id}","host":["{{baseUrl}}"],"path":["health","medications","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a medication order (cannot change controlled-substance class)"}},{"name":"GET /health/medications/{id}/administrations — Administration history for a medication","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/medications/{id}/administrations","host":["{{baseUrl}}"],"path":["health","medications","{id}","administrations"]},"description":"Administration history for a medication"}},{"name":"POST /health/medications/{id}/discontinue — Discontinue a medication order","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/medications/{id}/discontinue","host":["{{baseUrl}}"],"path":["health","medications","{id}","discontinue"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Flags the order inactive with a reason; further \"due\" rows and new doses are blocked. History remains."}},{"name":"POST /health/medications/administrations — Log a medication administration (emits MedicationAdministered)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/medications/administrations","host":["{{baseUrl}}"],"path":["health","medications","administrations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Supports status = given | refused | missed | held. Schedule-II controlled meds require a second-nurse `witnessUserId` on any dose with status=given."}},{"name":"GET /health/immunizations — List immunization records","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/immunizations","host":["{{baseUrl}}"],"path":["health","immunizations"]},"description":"List immunization records"}},{"name":"POST /health/immunizations — Record an immunization (emits ImmunizationRecorded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/immunizations","host":["{{baseUrl}}"],"path":["health","immunizations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record an immunization (emits ImmunizationRecorded)"}},{"name":"POST /health/immunizations/njiis-sync — Trigger NJIIS immunization sync for this district","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/health/immunizations/njiis-sync","host":["{{baseUrl}}"],"path":["health","immunizations","njiis-sync"]},"description":"Queries NJIIS for all active students, upserts matched vaccination records, detects conflicts with manually-entered data. Credentials must be configured via NJIIS_USERNAME / NJIIS_PASSWORD / NJIIS_FACILITY env vars (or district-scoped equivalents)."}},{"name":"GET /health/immunizations/njiis-status — NJIIS sync status and history for this district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/immunizations/njiis-status","host":["{{baseUrl}}"],"path":["health","immunizations","njiis-status"]},"description":"NJIIS sync status and history for this district"}},{"name":"GET /health/screenings — List health screenings","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/screenings","host":["{{baseUrl}}"],"path":["health","screenings"]},"description":"List health screenings"}},{"name":"POST /health/screenings — Record a health screening (emits HealthScreeningCompleted)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/screenings","host":["{{baseUrl}}"],"path":["health","screenings"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Status is derived from the result unless explicitly overridden. Abnormal results automatically set followupNeeded=true so the referral queue picks them up."}},{"name":"GET /health/screenings/compliance — Screening compliance matrix (who still owes what this year)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/screenings/compliance","host":["{{baseUrl}}"],"path":["health","screenings","compliance"]},"description":"Returns one row per (student × required screening) for the current school year. `satisfied` means there is a screening of that type on file since Aug 1. Use to surface a nurse-side \"still to do\" list."}},{"name":"GET /health/screenings/{id} — Get a screening","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/screenings/{id}","host":["{{baseUrl}}"],"path":["health","screenings","{id}"]},"description":"Get a screening"}},{"name":"PATCH /health/screenings/{id} — Edit a screening (correct a typo, update notes, override status)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/screenings/{id}","host":["{{baseUrl}}"],"path":["health","screenings","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Edit a screening (correct a typo, update notes, override status)"}},{"name":"POST /health/screenings/{id}/referral — Record that a family referral was sent for an abnormal screening","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/screenings/{id}/referral","host":["{{baseUrl}}"],"path":["health","screenings","{id}","referral"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stamps `referralSentOn` and appends a note. Emits ScreeningReferralSent. Only valid on screenings where followupNeeded=true."}},{"name":"POST /health/physical-exams — Record a pre-participation physical examination","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/health/physical-exams","host":["{{baseUrl}}"],"path":["health","physical-exams"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a pre-participation physical examination"}},{"name":"GET /health/physical-exams — List physical examinations (filter by studentId)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/health/physical-exams","host":["{{baseUrl}}"],"path":["health","physical-exams"]},"description":"List physical examinations (filter by studentId)"}}]},{"name":"Discipline","item":[{"name":"GET /incidents — List discipline incidents","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/incidents","host":["{{baseUrl}}"],"path":["incidents"]},"description":"List discipline incidents"}},{"name":"POST /incidents — Create a discipline incident (emits IncidentReported)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents","host":["{{baseUrl}}"],"path":["incidents"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a discipline incident (emits IncidentReported)"}},{"name":"GET /incidents/{id} — Get an incident with participants and actions","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/incidents/{id}","host":["{{baseUrl}}"],"path":["incidents","{id}"]},"description":"Get an incident with participants and actions"}},{"name":"POST /incidents/{id}/actions — Assign a consequence (emits IncidentActionAssigned)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents/{id}/actions","host":["{{baseUrl}}"],"path":["incidents","{id}","actions"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assign a consequence (emits IncidentActionAssigned)"}},{"name":"GET /hib/policy — Resolve the district's effective HIB policy (state default + district overrides).","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hib/policy","host":["{{baseUrl}}"],"path":["hib","policy"]},"description":"Returns the policy code, deadline (school-days or calendar-days), recognized outcomes, bias categories, and notification checklist for the current district. When the district's state has no HIB statute, `disabled` is true and the feature is inert."}},{"name":"GET /hib/policy/catalog — List all built-in HIB policies in the Forge catalog.","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hib/policy/catalog","host":["{{baseUrl}}"],"path":["hib","policy","catalog"]},"description":"Surfaces every policy definition shipped with the product — the admin UI picker uses this to show the full option set to districts setting an override."}},{"name":"GET /hib-investigations — List HIB investigations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hib-investigations","host":["{{baseUrl}}"],"path":["hib-investigations"]},"description":"List HIB investigations"}},{"name":"POST /hib-investigations — Open an HIB investigation against an existing incident (emits HibInvestigationOpened)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hib-investigations","host":["{{baseUrl}}"],"path":["hib-investigations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deadline is computed from the district's resolved HIB policy — school-days when a district calendar feed is available, calendar-day approximation otherwise. `deadlineApproximate` on the response flags when the UI should warn that the deadline is an approximation."}},{"name":"GET /hib-investigations/{id} — Get an HIB investigation","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hib-investigations/{id}","host":["{{baseUrl}}"],"path":["hib-investigations","{id}"]},"description":"Get an HIB investigation"}},{"name":"POST /hib-investigations/{id}/complete — Close an HIB investigation (emits HibInvestigationCompleted)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hib-investigations/{id}/complete","host":["{{baseUrl}}"],"path":["hib-investigations","{id}","complete"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"The outcome must be one recognized by the district's resolved HIB policy. Unknown outcomes return a 422 with the list of valid codes."}},{"name":"POST /restraint-seclusion — Log a restraint or seclusion event (emits RestraintSeclusionLogged)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/restraint-seclusion","host":["{{baseUrl}}"],"path":["restraint-seclusion"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"NJ-reportable event; the audit log retains this record indefinitely. Witnesses are recorded as person ids."}},{"name":"GET /incidents/{id}/escalations — List escalations for a discipline incident","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/incidents/{id}/escalations","host":["{{baseUrl}}"],"path":["incidents","{id}","escalations"]},"description":"List escalations for a discipline incident"}},{"name":"POST /incidents/{id}/escalations — Open a formal escalation for an incident (emits DisciplineEscalationOpened)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents/{id}/escalations","host":["{{baseUrl}}"],"path":["incidents","{id}","escalations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Open a formal escalation for an incident (emits DisciplineEscalationOpened)"}},{"name":"PATCH /incidents/{id}/escalations/{escId} — Update an escalation — schedule/hold hearing, record outcome, set sanction","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents/{id}/escalations/{escId}","host":["{{baseUrl}}"],"path":["incidents","{id}","escalations","{escId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update an escalation — schedule/hold hearing, record outcome, set sanction"}},{"name":"POST /incidents/{id}/escalations/{escId}/notice — Record that a parent notice was issued (emits EscalationNoticeIssued)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents/{id}/escalations/{escId}/notice","host":["{{baseUrl}}"],"path":["incidents","{id}","escalations","{escId}","notice"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record that a parent notice was issued (emits EscalationNoticeIssued)"}},{"name":"POST /incidents/{id}/escalations/{escId}/appeal — File a family appeal of the escalation outcome (emits DisciplineAppealFiled)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents/{id}/escalations/{escId}/appeal","host":["{{baseUrl}}"],"path":["incidents","{id}","escalations","{escId}","appeal"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"File a family appeal of the escalation outcome (emits DisciplineAppealFiled)"}},{"name":"PATCH /incidents/{id}/escalations/{escId}/appeal — Record the appeal decision (emits DisciplineAppealDecided)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/incidents/{id}/escalations/{escId}/appeal","host":["{{baseUrl}}"],"path":["incidents","{id}","escalations","{escId}","appeal"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record the appeal decision (emits DisciplineAppealDecided)"}}]},{"name":"Communications","item":[{"name":"GET /messages — List messages sent from this district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/messages","host":["{{baseUrl}}"],"path":["messages"]},"description":"List messages sent from this district"}},{"name":"POST /messages — Send a message (one-to-many) via the worker (emits CommunicationSent)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/messages","host":["{{baseUrl}}"],"path":["messages"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Records a row in `communications`, enqueues a send-notification job, and emits CommunicationSent. Actual delivery happens in the notifications worker; check delivery status via GET /v1/messages/:id."}},{"name":"POST /broadcasts — Emergency or district-wide broadcast to a named audience","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/broadcasts","host":["{{baseUrl}}"],"path":["broadcasts"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Resolves the audience to a recipient list at send time, records one Communication row, enqueues the notification job, and emits CommunicationSent. Requires broadcast.send permission."}},{"name":"GET /templates — List message templates","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/templates","host":["{{baseUrl}}"],"path":["templates"]},"description":"List message templates"}},{"name":"POST /templates — Create a message template","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/templates","host":["{{baseUrl}}"],"path":["templates"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a message template"}},{"name":"GET /templates/{id} — Get a message template","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/templates/{id}","host":["{{baseUrl}}"],"path":["templates","{id}"]},"description":"Get a message template"}},{"name":"PATCH /templates/{id} — Update a message template","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/templates/{id}","host":["{{baseUrl}}"],"path":["templates","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a message template"}},{"name":"GET /comms/settings — Get communications provider settings (masked — no credentials returned)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/comms/settings","host":["{{baseUrl}}"],"path":["comms","settings"]},"description":"Get communications provider settings (masked — no credentials returned)"}},{"name":"PATCH /comms/settings — Update email / SMS provider configuration","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/comms/settings","host":["{{baseUrl}}"],"path":["comms","settings"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Writes email and/or SMS provider credentials into District.settings.comms. Credentials (API keys, auth tokens) are write-only — omit them to keep existing values unchanged. A webhook token is generated automatically for SendGrid on first save."}},{"name":"DELETE /comms/settings/suppressions — Clear the bounce/unsubscribe suppression list (or remove one address)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/comms/settings/suppressions","host":["{{baseUrl}}"],"path":["comms","settings","suppressions"]},"description":"Clear the bounce/unsubscribe suppression list (or remove one address)"}}]},{"name":"District","item":[{"name":"GET /districts/instructional-time-policy — Read the district instructional-time policy","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/districts/instructional-time-policy","host":["{{baseUrl}}"],"path":["districts","instructional-time-policy"]},"description":"Read the district instructional-time policy"}},{"name":"PATCH /districts/instructional-time-policy — Update the district instructional-time policy","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/districts/instructional-time-policy","host":["{{baseUrl}}"],"path":["districts","instructional-time-policy"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update the district instructional-time policy"}}]},{"name":"Migration","item":[{"name":"POST /migration/preview/genesis — Preview a Genesis CSV migration (read-only — no writes)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/migration/preview/genesis","host":["{{baseUrl}}"],"path":["migration","preview","genesis"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Paste students.csv, guardians.csv (optional), and enrollments.csv from a Genesis 5 export. Returns row counts, warnings, and the first 10 students so the district can validate the mapping. Does NOT commit. To actually apply the migration, contact your Forge SIS account manager."}},{"name":"POST /migration/preview/powerschool — Preview a PowerSchool CSV migration (read-only — no writes)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/migration/preview/powerschool","host":["{{baseUrl}}"],"path":["migration","preview","powerschool"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Preview a PowerSchool CSV migration (read-only — no writes)"}},{"name":"POST /migration/preview/oneroster — Preview a OneRoster CSV migration (read-only — no writes)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/migration/preview/oneroster","host":["{{baseUrl}}"],"path":["migration","preview","oneroster"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Preview a OneRoster CSV migration (read-only — no writes)"}}]},{"name":"Business Office","item":[{"name":"GET /hr/positions — List HR positions","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/positions","host":["{{baseUrl}}"],"path":["hr","positions"]},"description":"List HR positions"}},{"name":"POST /hr/positions — Create HR position","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/positions","host":["{{baseUrl}}"],"path":["hr","positions"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create HR position"}},{"name":"GET /hr/positions/{id} — Get HR position","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/positions/{id}","host":["{{baseUrl}}"],"path":["hr","positions","{id}"]},"description":"Get HR position"}},{"name":"PATCH /hr/positions/{id} — Update HR position","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/positions/{id}","host":["{{baseUrl}}"],"path":["hr","positions","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update HR position"}},{"name":"GET /hr/payroll/cycles — List payroll cycles","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/payroll/cycles","host":["{{baseUrl}}"],"path":["hr","payroll","cycles"]},"description":"List payroll cycles"}},{"name":"POST /hr/payroll/cycles — Create a draft payroll cycle","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/payroll/cycles","host":["{{baseUrl}}"],"path":["hr","payroll","cycles"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a draft payroll cycle"}},{"name":"GET /hr/payroll/cycles/{id}/entries — List entries for a payroll cycle","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/payroll/cycles/{id}/entries","host":["{{baseUrl}}"],"path":["hr","payroll","cycles","{id}","entries"]},"description":"List entries for a payroll cycle"}},{"name":"POST /hr/payroll/cycles/{id}/entries — Add/update a payroll entry (auto-computes TPAF/PERS + net)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/payroll/cycles/{id}/entries","host":["{{baseUrl}}"],"path":["hr","payroll","cycles","{id}","entries"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add/update a payroll entry (auto-computes TPAF/PERS + net)"}},{"name":"POST /hr/payroll/cycles/{id}/actions/close — Close a payroll cycle (emits PayrollCycleClosed)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/hr/payroll/cycles/{id}/actions/close","host":["{{baseUrl}}"],"path":["hr","payroll","cycles","{id}","actions","close"]},"description":"Marks the cycle final; no further entries can be added. Totals are computed at close time and stamped on the event."}},{"name":"GET /hr/retirement-plans — List retirement plans available in this district's state","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/retirement-plans","host":["{{baseUrl}}"],"path":["hr","retirement-plans"]},"description":"List retirement plans available in this district's state"}},{"name":"POST /hr/retirement-plans/resolve — Dry-run a retirement-contribution calculation","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/retirement-plans/resolve","host":["{{baseUrl}}"],"path":["hr","retirement-plans","resolve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Without writing a payroll entry, compute what the employee/employer contribution would be for a given gross, plan/category, and hire date. Used by the admin contribution tester and by bulk-import validators."}},{"name":"GET /hr/budget/accounts — List budget accounts","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/budget/accounts","host":["{{baseUrl}}"],"path":["hr","budget","accounts"]},"description":"List budget accounts"}},{"name":"POST /hr/budget/accounts — Create a budget account","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/budget/accounts","host":["{{baseUrl}}"],"path":["hr","budget","accounts"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a budget account"}},{"name":"POST /hr/budget/entries — Post a budget journal entry","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/budget/entries","host":["{{baseUrl}}"],"path":["hr","budget","entries"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Post a budget journal entry"}},{"name":"GET /hr/budget/summary — Budget summary by account for a fiscal year","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/budget/summary","host":["{{baseUrl}}"],"path":["hr","budget","summary"]},"description":"Budget summary by account for a fiscal year"}},{"name":"GET /hr/evaluations — List staff evaluations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations","host":["{{baseUrl}}"],"path":["hr","evaluations"]},"description":"List staff evaluations"}},{"name":"POST /hr/evaluations — Open an evaluation cycle for a staff member","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations","host":["{{baseUrl}}"],"path":["hr","evaluations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Framework defaults to the district's resolved evaluation framework (state default or district override). Pass `frameworkCode` explicitly to pin a cycle to a specific rubric."}},{"name":"GET /hr/evaluations/{id} — Get an evaluation","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}"]},"description":"Get an evaluation"}},{"name":"POST /hr/evaluations/{id}/observations — Append an observation to an evaluation","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/observations","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","observations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Validates the observation against the cycle's framework. Unknown domains, out-of-range scores, and off-step scores return 422 with structured issues rather than silently storing garbage."}},{"name":"POST /hr/evaluations/{id}/sgo — Set the SGO plan on an evaluation","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/sgo","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","sgo"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Set the SGO plan on an evaluation"}},{"name":"POST /hr/evaluations/{id}/complete — Close an evaluation with a final score (emits EvaluationCompleted)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/complete","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","complete"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Auto-computes the summative score from observations + SGO using the cycle's framework. If the caller supplies `finalScore`, that value is persisted; otherwise the computed score is used. The scoring breakdown (per-domain averages, warnings, summative rating band) is always returned alongside."}},{"name":"GET /hr/evaluation-framework — Resolve the teacher evaluation framework for this district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluation-framework","host":["{{baseUrl}}"],"path":["hr","evaluation-framework"]},"description":"Returns the framework currently applied to this district: district override if set, otherwise the state default, otherwise the generic fallback. Observation scores for all open cycles should match this framework."}},{"name":"GET /hr/evaluation-framework/catalog — List all built-in evaluation frameworks","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluation-framework/catalog","host":["{{baseUrl}}"],"path":["hr","evaluation-framework","catalog"]},"description":"Returns the full catalog of frameworks Forge ships with. Used by the admin UI to let districts pick an override framework."}},{"name":"GET /hr/evaluations/{id}/detail — Get full evaluation detail including conferences, artifacts, and observations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/detail","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","detail"]},"description":"Get full evaluation detail including conferences, artifacts, and observations"}},{"name":"GET /hr/evaluations/mine — List the signed-in teacher's own evaluation cycles (read-only)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations/mine","host":["{{baseUrl}}"],"path":["hr","evaluations","mine"]},"description":"List the signed-in teacher's own evaluation cycles (read-only)"}},{"name":"GET /hr/evaluations/{id}/conferences — List conferences for an evaluation cycle","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/conferences","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","conferences"]},"description":"List conferences for an evaluation cycle"}},{"name":"POST /hr/evaluations/{id}/conferences — Schedule a conference for an evaluation cycle (emits EvalConferenceScheduled)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/conferences","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","conferences"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Schedule a conference for an evaluation cycle (emits EvalConferenceScheduled)"}},{"name":"PATCH /hr/evaluations/{id}/conferences/{subId} — Update a conference (mark as held, add notes)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/conferences/{subId}","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","conferences","{subId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a conference (mark as held, add notes)"}},{"name":"GET /hr/evaluations/{id}/artifacts — List evidence artifacts for an evaluation cycle","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/artifacts","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","artifacts"]},"description":"List evidence artifacts for an evaluation cycle"}},{"name":"POST /hr/evaluations/{id}/artifacts — Add an evidence artifact (emits EvalArtifactUploaded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/artifacts","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","artifacts"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add an evidence artifact (emits EvalArtifactUploaded)"}},{"name":"DELETE /hr/evaluations/{id}/artifacts/{subId} — Soft-delete an evidence artifact","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/artifacts/{subId}","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","artifacts","{subId}"]},"description":"Soft-delete an evidence artifact"}},{"name":"POST /hr/evaluations/{id}/sgo/approve — Supervisor approves the teacher's SGO plan (emits SgoApproved)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/sgo/approve","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","sgo","approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Supervisor approves the teacher's SGO plan (emits SgoApproved)"}},{"name":"PATCH /hr/evaluations/{id}/status — Transition an evaluation cycle through the lifecycle","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/hr/evaluations/{id}/status","host":["{{baseUrl}}"],"path":["hr","evaluations","{id}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Valid transitions: draft → in_progress, in_progress → pending_review, pending_review → complete. The complete route (POST /complete) closes the cycle with a computed score — use this route only to transition back to pending_review if a score needs revision, or draft → in_progress."}}]},{"name":"AI","item":[{"name":"POST /ai/report-card-comment — Draft a grounded report-card comment for one (student, section, term)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/report-card-comment","host":["{{baseUrl}}"],"path":["ai","report-card-comment"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Draft a grounded report-card comment for one (student, section, term)"}},{"name":"POST /ai/student-summary — Generate a grounded summary for one student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/student-summary","host":["{{baseUrl}}"],"path":["ai","student-summary"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Generate a grounded summary for one student"}},{"name":"POST /ai/ask — Parent portal Q&A — grounded in the asking guardian’s visible data","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/ask","host":["{{baseUrl}}"],"path":["ai","ask"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Parent portal Q&A — grounded in the asking guardian’s visible data"}},{"name":"POST /ai/early-warning — Grounded early-warning narrative for one student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/early-warning","host":["{{baseUrl}}"],"path":["ai","early-warning"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Grounded early-warning narrative for one student"}},{"name":"POST /ai/teacher-copilot — Weekly digest for one section (trends + check-ins + overdue)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/teacher-copilot","host":["{{baseUrl}}"],"path":["ai","teacher-copilot"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Weekly digest for one section (trends + check-ins + overdue)"}},{"name":"POST /ai/nlq — Turn a natural-language question into a read-only query plan","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/nlq","host":["{{baseUrl}}"],"path":["ai","nlq"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Returns a JSON plan (no execution). The admin console previews the plan before running it; SQL injection is impossible because the API validates the plan against an allowlist of tables + filter keys."}},{"name":"GET /ai/usage — AI usage and cost for this district (last 1000 calls)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/ai/usage","host":["{{baseUrl}}"],"path":["ai","usage"]},"description":"AI usage and cost for this district (last 1000 calls)"}},{"name":"POST /ai/registration/documents/extract — Extract structured fields from a scanned registration document","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/registration/documents/extract","host":["{{baseUrl}}"],"path":["ai","registration","documents","extract"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Vision endpoint — takes a base64 image or PDF and returns a typed field bag plus region citations. Registrars click \"Extract\" to pre-fill the application from uploaded documents; the human always reviews before saving."}},{"name":"POST /ai/translate — Translate a short school message into a target language","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/translate","host":["{{baseUrl}}"],"path":["ai","translate"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Used by the messaging composer to reach families in their home language. Preserves proper nouns, dates, and times. Non-grounded prompt — the source text is the only authoritative input."}},{"name":"POST /ai/nurse/visit-note/expand — Expand a nurse’s shorthand into a SOAP-structured visit note","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/nurse/visit-note/expand","host":["{{baseUrl}}"],"path":["ai","nurse","visit-note","expand"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Optional `studentId` pulls the student’s last 3 visits as grounding so the narrative is consistent with prior care."}},{"name":"POST /ai/iep/progress-narrative — Draft a quarterly IEP-goal progress narrative for one student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/iep/progress-narrative","host":["{{baseUrl}}"],"path":["ai","iep","progress-narrative"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Pulls recent assignment scores + attendance + any assertions on the student record and drafts a parent-facing narrative. Teacher of record reviews before saving into the IEP."}},{"name":"POST /ai/scheduling/propose-change — Parse a free-text schedule-change request into structured operations","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/scheduling/propose-change","host":["{{baseUrl}}"],"path":["ai","scheduling","propose-change"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Preview-only — returns the operations the scheduler would need to execute. No changes are applied until the admin confirms via the existing scheduling endpoints."}},{"name":"POST /ai/grading/rubric-score — Draft rubric-aligned scores and a teacher comment for a student essay","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/ai/grading/rubric-score","host":["{{baseUrl}}"],"path":["ai","grading","rubric-score"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"The teacher retains final authority — this endpoint produces a draft score with evidence quoted verbatim from the essay and a suggested comment. Every `evidence` value must be a substring of the essay."}}]},{"name":"Dashboard","item":[{"name":"GET /dashboard/teacher/me — Summary for the signed-in teacher’s dashboard","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/dashboard/teacher/me","host":["{{baseUrl}}"],"path":["dashboard","teacher","me"]},"description":"Resolves the teacher’s Person row from the session, lists their current sections, and computes per-section attendance + grade averages plus a 10-day attendance/grade sparkline from real rows."}},{"name":"GET /dashboard/admin/summary — District-wide rollups for the admin overview","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/dashboard/admin/summary","host":["{{baseUrl}}"],"path":["dashboard","admin","summary"]},"description":"Enrollment count + trend, attendance rate + trend, open compliance findings, open incidents, pending registration applications, health visits in the past 7 days, and AI cost for the last 30 days."}},{"name":"GET /dashboard/superintendent — Executive overview for the district superintendent","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/dashboard/superintendent","host":["{{baseUrl}}"],"path":["dashboard","superintendent"]},"description":"Aggregates student metrics, compliance alerts, staff KPIs, financial snapshot, recent event activity, and state reporting deadlines into a single payload for the superintendent dashboard."}}]},{"name":"Registration","item":[{"name":"POST /registration/districts/{districtId}/applications — Submit a new family / re-registration application","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/registration/districts/{districtId}/applications","host":["{{baseUrl}}"],"path":["registration","districts","{districtId}","applications"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Public endpoint used by the registration wizard. Returns an access token families use to resume the draft and upload documents."}},{"name":"GET /registration/districts/{districtId}/applications/by-token/{token} — Resume a registration draft by access token","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/registration/districts/{districtId}/applications/by-token/{token}","host":["{{baseUrl}}"],"path":["registration","districts","{districtId}","applications","by-token","{token}"]},"description":"Resume a registration draft by access token"}},{"name":"POST /registration/districts/{districtId}/applications/by-token/{token}/documents — Attach an uploaded document to an application","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/registration/districts/{districtId}/applications/by-token/{token}/documents","host":["{{baseUrl}}"],"path":["registration","districts","{districtId}","applications","by-token","{token}","documents"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"The actual bytes are uploaded to object storage out-of-band; this records the metadata + storage key."}},{"name":"GET /registration/applications — List registration applications (registrar view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/registration/applications","host":["{{baseUrl}}"],"path":["registration","applications"]},"description":"List registration applications (registrar view)"}},{"name":"GET /registration/applications/{id} — Get a full application (registrar view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/registration/applications/{id}","host":["{{baseUrl}}"],"path":["registration","applications","{id}"]},"description":"Get a full application (registrar view)"}},{"name":"POST /registration/applications/{id}/approve — Approve an application and create the student + enrollment","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/registration/applications/{id}/approve","host":["{{baseUrl}}"],"path":["registration","applications","{id}","approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Approve an application and create the student + enrollment"}},{"name":"POST /registration/applications/{id}/reject — Reject an application","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/registration/applications/{id}/reject","host":["{{baseUrl}}"],"path":["registration","applications","{id}","reject"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Reject an application"}}]},{"name":"Reports","item":[{"name":"GET /reports/catalog — List the field catalog for every report scope","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/reports/catalog","host":["{{baseUrl}}"],"path":["reports","catalog"]},"description":"List the field catalog for every report scope"}},{"name":"GET /reports/custom — List saved custom reports","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/reports/custom","host":["{{baseUrl}}"],"path":["reports","custom"]},"description":"List saved custom reports"}},{"name":"POST /reports/custom — Create a saved custom report","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/reports/custom","host":["{{baseUrl}}"],"path":["reports","custom"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a saved custom report"}},{"name":"GET /reports/custom/{id} — Get a saved custom report","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/reports/custom/{id}","host":["{{baseUrl}}"],"path":["reports","custom","{id}"]},"description":"Get a saved custom report"}},{"name":"PUT /reports/custom/{id} — Update a saved custom report","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/reports/custom/{id}","host":["{{baseUrl}}"],"path":["reports","custom","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a saved custom report"}},{"name":"DELETE /reports/custom/{id} — Delete a saved custom report","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/reports/custom/{id}","host":["{{baseUrl}}"],"path":["reports","custom","{id}"]},"description":"Delete a saved custom report"}},{"name":"POST /reports/custom/{id}/run — Execute a saved report and return the result set","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/reports/custom/{id}/run","host":["{{baseUrl}}"],"path":["reports","custom","{id}","run"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Execute a saved report and return the result set"}},{"name":"GET /reports/custom/{id}/export — Export a saved report as CSV","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/reports/custom/{id}/export","host":["{{baseUrl}}"],"path":["reports","custom","{id}","export"]},"description":"Export a saved report as CSV"}}]},{"name":"Lookups","item":[{"name":"GET /lookups/categories — List every lookup category available to this caller","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/lookups/categories","host":["{{baseUrl}}"],"path":["lookups","categories"]},"description":"List every lookup category available to this caller"}},{"name":"GET /lookups/{category} — Get the active options for a lookup category","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/lookups/{category}","host":["{{baseUrl}}"],"path":["lookups","{category}"]},"description":"Merges platform defaults → state defaults → district overrides. Sorted by sortOrder then label."}}]},{"name":"Transcripts","item":[{"name":"GET /students/{id}/transcript — Get a student’s transcript (registrar view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/transcript","host":["{{baseUrl}}"],"path":["students","{id}","transcript"]},"description":"Get a student’s transcript (registrar view)"}},{"name":"GET /students/{id}/transcript.pdf — Download a student’s transcript as a PDF","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/transcript.pdf","host":["{{baseUrl}}"],"path":["students","{id}","transcript.pdf"]},"description":"Renders an official-style transcript PDF using pdf-lib. Single binary response with content-type application/pdf."}},{"name":"GET /student/me/transcript — Current student’s own transcript","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/transcript","host":["{{baseUrl}}"],"path":["student","me","transcript"]},"description":"Current student’s own transcript"}},{"name":"GET /honor-roll — District honor roll (current term, by cumulative GPA)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/honor-roll","host":["{{baseUrl}}"],"path":["honor-roll"]},"description":"District honor roll (current term, by cumulative GPA)"}},{"name":"POST /transcripts/backfill — Backfill academic records from SectionGrade for a school year","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transcripts/backfill","host":["{{baseUrl}}"],"path":["transcripts","backfill"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Backfill academic records from SectionGrade for a school year"}},{"name":"POST /transcripts/refresh-metrics — Recompute GPA / credits / class rank / honor roll for a cohort","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transcripts/refresh-metrics","host":["{{baseUrl}}"],"path":["transcripts","refresh-metrics"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Recompute GPA / credits / class rank / honor roll for a cohort"}}]},{"name":"Report cards","item":[{"name":"POST /report-cards/generate — Generate / refresh report cards for every student in a term","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/report-cards/generate","host":["{{baseUrl}}"],"path":["report-cards","generate"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Idempotent: re-running refreshes snapshots but preserves ‘published’ status."}},{"name":"POST /report-cards/lock — Lock (freeze) all draft report cards in a term","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/report-cards/lock","host":["{{baseUrl}}"],"path":["report-cards","lock"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Lock (freeze) all draft report cards in a term"}},{"name":"POST /report-cards/publish — Publish report cards to families (marks them as visible)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/report-cards/publish","host":["{{baseUrl}}"],"path":["report-cards","publish"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Publish report cards to families (marks them as visible)"}},{"name":"GET /report-cards — List report cards for a term (registrar view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/report-cards","host":["{{baseUrl}}"],"path":["report-cards"]},"description":"List report cards for a term (registrar view)"}},{"name":"GET /students/{id}/report-cards — All report cards for a specific student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/report-cards","host":["{{baseUrl}}"],"path":["students","{id}","report-cards"]},"description":"All report cards for a specific student"}},{"name":"GET /students/{id}/report-cards/{termId} — Get a single report card for a student + term","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/report-cards/{termId}","host":["{{baseUrl}}"],"path":["students","{id}","report-cards","{termId}"]},"description":"Get a single report card for a student + term"}},{"name":"GET /student/me/report-cards — Current student’s published report cards","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/report-cards","host":["{{baseUrl}}"],"path":["student","me","report-cards"]},"description":"Current student’s published report cards"}},{"name":"GET /sections/{id}/report-comments — List teacher comments for all students in a section + term","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sections/{id}/report-comments","host":["{{baseUrl}}"],"path":["sections","{id}","report-comments"]},"description":"List teacher comments for all students in a section + term"}},{"name":"PUT /sections/{sectionId}/report-comments/{studentId} — Save / update a teacher comment for one student in one section","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sections/{sectionId}/report-comments/{studentId}","host":["{{baseUrl}}"],"path":["sections","{sectionId}","report-comments","{studentId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Save / update a teacher comment for one student in one section"}}]},{"name":"Graduation","item":[{"name":"GET /students/{id}/graduation-progress — Progress-to-graduation for a specific student (registrar / counselor view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/graduation-progress","host":["{{baseUrl}}"],"path":["students","{id}","graduation-progress"]},"description":"Progress-to-graduation for a specific student (registrar / counselor view)"}},{"name":"GET /student/me/graduation-progress — Current student’s own progress-to-graduation","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/graduation-progress","host":["{{baseUrl}}"],"path":["student","me","graduation-progress"]},"description":"Current student’s own progress-to-graduation"}},{"name":"GET /graduation/seniors — Senior roster with progress + status (registrar clearance view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/graduation/seniors","host":["{{baseUrl}}"],"path":["graduation","seniors"]},"description":"Senior roster with progress + status (registrar clearance view)"}},{"name":"POST /students/{id}/graduation-waivers — Waive a subject-area credit requirement for a student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/students/{id}/graduation-waivers","host":["{{baseUrl}}"],"path":["students","{id}","graduation-waivers"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Waive a subject-area credit requirement for a student"}}]},{"name":"Section 504","item":[{"name":"GET /504-plans — List every 504 plan in the district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/504-plans","host":["{{baseUrl}}"],"path":["504-plans"]},"description":"List every 504 plan in the district"}},{"name":"POST /504-plans — Draft a new 504 plan after eligibility determination","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/504-plans","host":["{{baseUrl}}"],"path":["504-plans"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Draft a new 504 plan after eligibility determination"}},{"name":"GET /students/{id}/504-plans — Plans for a specific student (current + history)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{id}/504-plans","host":["{{baseUrl}}"],"path":["students","{id}","504-plans"]},"description":"Plans for a specific student (current + history)"}},{"name":"GET /student/me/504-plans — Current student’s own 504 plans","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/student/me/504-plans","host":["{{baseUrl}}"],"path":["student","me","504-plans"]},"description":"Current student’s own 504 plans"}},{"name":"GET /504-plans/{id} — Single plan with accommodations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/504-plans/{id}","host":["{{baseUrl}}"],"path":["504-plans","{id}"]},"description":"Single plan with accommodations"}},{"name":"PATCH /504-plans/{id} — Update plan metadata (status, end date, notes)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/504-plans/{id}","host":["{{baseUrl}}"],"path":["504-plans","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update plan metadata (status, end date, notes)"}},{"name":"POST /504-plans/{id}/review — Record the annual review meeting outcome","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/504-plans/{id}/review","host":["{{baseUrl}}"],"path":["504-plans","{id}","review"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record the annual review meeting outcome"}},{"name":"POST /504-plans/{id}/accommodations — Add an accommodation to a plan","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/504-plans/{id}/accommodations","host":["{{baseUrl}}"],"path":["504-plans","{id}","accommodations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add an accommodation to a plan"}},{"name":"POST /504-plans/{planId}/accommodations/{accId}/remove — Deactivate an accommodation (soft-remove)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/504-plans/{planId}/accommodations/{accId}/remove","host":["{{baseUrl}}"],"path":["504-plans","{planId}","accommodations","{accId}","remove"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deactivate an accommodation (soft-remove)"}},{"name":"GET /teacher/sections/{id}/accommodations — Accommodations for the students in one of my sections","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/teacher/sections/{id}/accommodations","host":["{{baseUrl}}"],"path":["teacher","sections","{id}","accommodations"]},"description":"Accommodations for the students in one of my sections"}}]},{"name":"Truancy","item":[{"name":"GET /truancy/cases — District truancy caseload","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/truancy/cases","host":["{{baseUrl}}"],"path":["truancy","cases"]},"description":"District truancy caseload"}},{"name":"GET /truancy/cases/{id} — One case with full letter history","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/truancy/cases/{id}","host":["{{baseUrl}}"],"path":["truancy","cases","{id}"]},"description":"One case with full letter history"}},{"name":"GET /truancy/policy — District truancy policy (thresholds + letter templates)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/truancy/policy","host":["{{baseUrl}}"],"path":["truancy","policy"]},"description":"District truancy policy (thresholds + letter templates)"}},{"name":"PATCH /truancy/policy — Update thresholds or letter templates","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/truancy/policy","host":["{{baseUrl}}"],"path":["truancy","policy"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update thresholds or letter templates"}},{"name":"POST /truancy/evaluate — Scan attendance and open/advance cases","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/truancy/evaluate","host":["{{baseUrl}}"],"path":["truancy","evaluate"]},"description":"Scan attendance and open/advance cases"}},{"name":"POST /truancy/cases/{id}/generate-letter — Draft a letter of the specified tier for the case","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/truancy/cases/{id}/generate-letter","host":["{{baseUrl}}"],"path":["truancy","cases","{id}","generate-letter"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Draft a letter of the specified tier for the case"}},{"name":"POST /truancy/letters/{id}/send — Mark a generated letter as sent via the chosen channel","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/truancy/letters/{id}/send","host":["{{baseUrl}}"],"path":["truancy","letters","{id}","send"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Mark a generated letter as sent via the chosen channel"}},{"name":"POST /truancy/letters/{id}/acknowledge — Record parent acknowledgement of a truancy letter","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/truancy/letters/{id}/acknowledge","host":["{{baseUrl}}"],"path":["truancy","letters","{id}","acknowledge"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record parent acknowledgement of a truancy letter"}},{"name":"POST /truancy/cases/{id}/resolve — Resolve a truancy case (attendance restored, transfer, etc.)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/truancy/cases/{id}/resolve","host":["{{baseUrl}}"],"path":["truancy","cases","{id}","resolve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Resolve a truancy case (attendance restored, transfer, etc.)"}}]},{"name":"Counselor","item":[{"name":"GET /counselors/me/caseload — List the calling counselor's active caseload","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/counselors/me/caseload","host":["{{baseUrl}}"],"path":["counselors","me","caseload"]},"description":"List the calling counselor's active caseload"}},{"name":"GET /counselors/{counselorPersonId}/caseload — List active caseload for a specific counselor","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/counselors/{counselorPersonId}/caseload","host":["{{baseUrl}}"],"path":["counselors","{counselorPersonId}","caseload"]},"description":"List active caseload for a specific counselor"}},{"name":"GET /counselors/unassigned — List active students with no current counselor assignment","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/counselors/unassigned","host":["{{baseUrl}}"],"path":["counselors","unassigned"]},"description":"List active students with no current counselor assignment"}},{"name":"POST /counselors/caseload/assign — Assign a student to a counselor","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/counselors/caseload/assign","host":["{{baseUrl}}"],"path":["counselors","caseload","assign"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Idempotent. If the same counselor↔student pair already has an active row, the existing row is end-dated and a new row is created so the change is auditable."}},{"name":"POST /counselors/caseload/{assignmentId}/unassign — End a counselor assignment","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/counselors/caseload/{assignmentId}/unassign","host":["{{baseUrl}}"],"path":["counselors","caseload","{assignmentId}","unassign"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"End a counselor assignment"}},{"name":"POST /counselors/caseload/request — Counselor requests assignment of a specific student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/counselors/caseload/request","host":["{{baseUrl}}"],"path":["counselors","caseload","request"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Counselors cannot self-assign; this endpoint emits an event so a principal/school_admin can review and action it."}}]},{"name":"IEP","item":[{"name":"GET /iep/referrals — List SPED referrals","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/referrals","host":["{{baseUrl}}"],"path":["iep","referrals"]},"description":"List SPED referrals"}},{"name":"POST /iep/referrals — Open a new SPED referral (Child Find)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/referrals","host":["{{baseUrl}}"],"path":["iep","referrals"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Open a new SPED referral (Child Find)"}},{"name":"GET /iep/referrals/{id} — One referral with evaluations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/referrals/{id}","host":["{{baseUrl}}"],"path":["iep","referrals","{id}"]},"description":"One referral with evaluations"}},{"name":"PATCH /iep/referrals/{id} — Update referral (status, consent, eligibility decision, notes)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/referrals/{id}","host":["{{baseUrl}}"],"path":["iep","referrals","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update referral (status, consent, eligibility decision, notes)"}},{"name":"POST /iep/referrals/{id}/evaluations — Schedule an evaluation on a referral","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/referrals/{id}/evaluations","host":["{{baseUrl}}"],"path":["iep","referrals","{id}","evaluations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Schedule an evaluation on a referral"}},{"name":"PATCH /iep/evaluations/{id} — Update an evaluation (status, findings, completed date)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/evaluations/{id}","host":["{{baseUrl}}"],"path":["iep","evaluations","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update an evaluation (status, findings, completed date)"}},{"name":"GET /iep/plans — List IEPs (district caseload)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/plans","host":["{{baseUrl}}"],"path":["iep","plans"]},"description":"List IEPs (district caseload)"}},{"name":"POST /iep/plans — Draft a new IEP after eligibility determination","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans","host":["{{baseUrl}}"],"path":["iep","plans"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Draft a new IEP after eligibility determination"}},{"name":"GET /iep/plans/{id} — Single IEP with goals, services, accommodations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/plans/{id}","host":["{{baseUrl}}"],"path":["iep","plans","{id}"]},"description":"Single IEP with goals, services, accommodations"}},{"name":"PATCH /iep/plans/{id} — Update IEP metadata (status, disability, dates, notes)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}","host":["{{baseUrl}}"],"path":["iep","plans","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update IEP metadata (status, disability, dates, notes)"}},{"name":"GET /iep/students/{id}/plans — IEPs for a specific student (history)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/students/{id}/plans","host":["{{baseUrl}}"],"path":["iep","students","{id}","plans"]},"description":"IEPs for a specific student (history)"}},{"name":"GET /iep/student/me/plans — Current student’s own IEPs","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/student/me/plans","host":["{{baseUrl}}"],"path":["iep","student","me","plans"]},"description":"Current student’s own IEPs"}},{"name":"POST /iep/plans/{id}/review — Record the annual review meeting outcome","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/review","host":["{{baseUrl}}"],"path":["iep","plans","{id}","review"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record the annual review meeting outcome"}},{"name":"POST /iep/plans/{id}/goals — Add a measurable annual goal to an IEP","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/goals","host":["{{baseUrl}}"],"path":["iep","plans","{id}","goals"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a measurable annual goal to an IEP"}},{"name":"POST /iep/goals/{id}/retire — Deactivate a goal (kept for history)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/iep/goals/{id}/retire","host":["{{baseUrl}}"],"path":["iep","goals","{id}","retire"]},"description":"Deactivate a goal (kept for history)"}},{"name":"POST /iep/plans/{id}/services — Add a related service (SLP, OT, PT, counseling, …) to an IEP","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/services","host":["{{baseUrl}}"],"path":["iep","plans","{id}","services"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a related service (SLP, OT, PT, counseling, …) to an IEP"}},{"name":"POST /iep/services/{id}/retire — Deactivate an IEP service","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/iep/services/{id}/retire","host":["{{baseUrl}}"],"path":["iep","services","{id}","retire"]},"description":"Deactivate an IEP service"}},{"name":"POST /iep/plans/{id}/accommodations — Add an accommodation to an IEP","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/accommodations","host":["{{baseUrl}}"],"path":["iep","plans","{id}","accommodations"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add an accommodation to an IEP"}},{"name":"POST /iep/accommodations/{id}/remove — Retire an IEP accommodation with reason","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/accommodations/{id}/remove","host":["{{baseUrl}}"],"path":["iep","accommodations","{id}","remove"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Retire an IEP accommodation with reason"}},{"name":"GET /iep/teacher/sections/{id}/accommodations — Active IEP accommodations for students in this section","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/teacher/sections/{id}/accommodations","host":["{{baseUrl}}"],"path":["iep","teacher","sections","{id}","accommodations"]},"description":"Active IEP accommodations for students in this section"}},{"name":"GET /iep/plans/{id}/signatures — List signatures captured against an IEP plan","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/signatures","host":["{{baseUrl}}"],"path":["iep","plans","{id}","signatures"]},"description":"List signatures captured against an IEP plan"}},{"name":"POST /iep/plans/{id}/signatures — Capture a typed-name signature against an IEP (consent, agreement, attendance, amendment)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/signatures","host":["{{baseUrl}}"],"path":["iep","plans","{id}","signatures"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Capture a typed-name signature against an IEP (consent, agreement, attendance, amendment)"}},{"name":"POST /iep/signatures/{id}/revoke — Revoke a previously captured IEP signature","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/signatures/{id}/revoke","host":["{{baseUrl}}"],"path":["iep","signatures","{id}","revoke"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Revoke a previously captured IEP signature"}},{"name":"GET /iep/plans/{id}/meetings — List IEP team meetings for a plan","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/meetings","host":["{{baseUrl}}"],"path":["iep","plans","{id}","meetings"]},"description":"List IEP team meetings for a plan"}},{"name":"POST /iep/plans/{id}/meetings — Schedule an IEP team meeting (IDEA 10-day notice)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/meetings","host":["{{baseUrl}}"],"path":["iep","plans","{id}","meetings"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Schedule an IEP team meeting (IDEA 10-day notice)"}},{"name":"PATCH /iep/meetings/{id} — Update meeting attendance / minutes / outcomes. Setting `heldAt` emits IepMeeting.Held.","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/meetings/{id}","host":["{{baseUrl}}"],"path":["iep","meetings","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update meeting attendance / minutes / outcomes. Setting `heldAt` emits IepMeeting.Held."}},{"name":"GET /iep/goals/{id}/progress — List progress notes for a specific goal","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/goals/{id}/progress","host":["{{baseUrl}}"],"path":["iep","goals","{id}","progress"]},"description":"List progress notes for a specific goal"}},{"name":"POST /iep/goals/{id}/progress — Record a progress observation against a goal","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/iep/goals/{id}/progress","host":["{{baseUrl}}"],"path":["iep","goals","{id}","progress"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a progress observation against a goal"}},{"name":"GET /iep/plans/{id}/progress — List all progress notes across every goal on a plan (reverse-chron).","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/iep/plans/{id}/progress","host":["{{baseUrl}}"],"path":["iep","plans","{id}","progress"]},"description":"List all progress notes across every goal on a plan (reverse-chron)."}},{"name":"PATCH /iep/progress-notes/{id}/share-with-parent — Mark a progress note as included in a periodic parent report (sets sharedWithParentAt).","request":{"method":"PATCH","header":[],"url":{"raw":"{{baseUrl}}/iep/progress-notes/{id}/share-with-parent","host":["{{baseUrl}}"],"path":["iep","progress-notes","{id}","share-with-parent"]},"description":"Mark a progress note as included in a periodic parent report (sets sharedWithParentAt)."}}]},{"name":"Transportation","item":[{"name":"GET /transportation/routes — List bus routes","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/routes","host":["{{baseUrl}}"],"path":["transportation","routes"]},"description":"List bus routes"}},{"name":"POST /transportation/routes — Create a bus route (emits BusRouteCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/routes","host":["{{baseUrl}}"],"path":["transportation","routes"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a bus route (emits BusRouteCreated)"}},{"name":"GET /transportation/routes/{id} — Get a bus route with its stops","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/routes/{id}","host":["{{baseUrl}}"],"path":["transportation","routes","{id}"]},"description":"Get a bus route with its stops"}},{"name":"PATCH /transportation/routes/{id} — Edit a bus route (emits BusRouteUpdated)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/routes/{id}","host":["{{baseUrl}}"],"path":["transportation","routes","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Passing `stops` replaces the stop list — requires that there be no active assignments on the route. Omit `stops` to keep the current list unchanged."}},{"name":"POST /transportation/routes/{id}/deactivate — Retire a bus route (emits BusRouteDeactivated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/routes/{id}/deactivate","host":["{{baseUrl}}"],"path":["transportation","routes","{id}","deactivate"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Marks the route inactive so no new assignments can be attached. Existing assignments remain historical. Refuses if the route already has active assignments — end them first."}},{"name":"GET /transportation/assignments — List route assignments","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/assignments","host":["{{baseUrl}}"],"path":["transportation","assignments"]},"description":"Default is active-only (no effectiveTo or effectiveTo in the future). Pass ?activeOnly=false to include history."}},{"name":"POST /transportation/assignments — Assign a student to a route (emits StudentAssignedToRoute)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/assignments","host":["{{baseUrl}}"],"path":["transportation","assignments"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assign a student to a route (emits StudentAssignedToRoute)"}},{"name":"GET /transportation/assignments/{id} — Get a route assignment","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/assignments/{id}","host":["{{baseUrl}}"],"path":["transportation","assignments","{id}"]},"description":"Get a route assignment"}},{"name":"POST /transportation/assignments/{id}/end — End an assignment (emits StudentUnassignedFromRoute)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/assignments/{id}/end","host":["{{baseUrl}}"],"path":["transportation","assignments","{id}","end"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stamps `effectiveTo` so the student no longer appears on the active manifest. Historical data stays on file. Defaults to today if `endedOn` is omitted."}},{"name":"GET /transportation/alternate-pickups — List alternate-pickup requests","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/alternate-pickups","host":["{{baseUrl}}"],"path":["transportation","alternate-pickups"]},"description":"List alternate-pickup requests"}},{"name":"POST /transportation/alternate-pickups — Request an alternate pickup (emits AlternatePickupRequested)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/alternate-pickups","host":["{{baseUrl}}"],"path":["transportation","alternate-pickups"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Opens a request in `pending` status. A district user reviews via /approve or /deny. Requests cannot overlap an existing pending/approved window for the same student."}},{"name":"GET /transportation/alternate-pickups/{id} — Get an alternate-pickup request","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/alternate-pickups/{id}","host":["{{baseUrl}}"],"path":["transportation","alternate-pickups","{id}"]},"description":"Get an alternate-pickup request"}},{"name":"POST /transportation/alternate-pickups/{id}/approve — Approve an alternate-pickup request (emits AlternatePickupApproved)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/alternate-pickups/{id}/approve","host":["{{baseUrl}}"],"path":["transportation","alternate-pickups","{id}","approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Approve an alternate-pickup request (emits AlternatePickupApproved)"}},{"name":"POST /transportation/alternate-pickups/{id}/deny — Deny an alternate-pickup request (emits AlternatePickupDenied)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/alternate-pickups/{id}/deny","host":["{{baseUrl}}"],"path":["transportation","alternate-pickups","{id}","deny"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deny an alternate-pickup request (emits AlternatePickupDenied)"}},{"name":"GET /transportation/field-trips — List field trips","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/field-trips","host":["{{baseUrl}}"],"path":["transportation","field-trips"]},"description":"List field trips"}},{"name":"POST /transportation/field-trips — Schedule a field trip (emits FieldTripScheduled)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/field-trips","host":["{{baseUrl}}"],"path":["transportation","field-trips"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Schedule a field trip (emits FieldTripScheduled)"}},{"name":"GET /transportation/field-trips/{id} — Get a field trip with its roster","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transportation/field-trips/{id}","host":["{{baseUrl}}"],"path":["transportation","field-trips","{id}"]},"description":"Get a field trip with its roster"}},{"name":"PATCH /transportation/field-trips/{id} — Edit a field trip","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/field-trips/{id}","host":["{{baseUrl}}"],"path":["transportation","field-trips","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Status transitions emit FieldTripStatusChanged. Other edits are logged as regular updates."}},{"name":"PATCH /transportation/field-trips/{id}/roster — Add or remove students from the field-trip roster","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/field-trips/{id}/roster","host":["{{baseUrl}}"],"path":["transportation","field-trips","{id}","roster"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Emits FieldTripRosterUpdated when any students were added or removed. Duplicates in `add` are silently ignored (the unique constraint covers it)."}},{"name":"POST /transportation/field-trips/{id}/roster/{rosterId}/board — Mark a roster row as boarded / not boarded","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transportation/field-trips/{id}/roster/{rosterId}/board","host":["{{baseUrl}}"],"path":["transportation","field-trips","{id}","roster","{rosterId}","board"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Used at bus-loading time to tick off each student. Does not emit a separate event — boarding counts roll up on the trip read."}}]},{"name":"Food Service","item":[{"name":"GET /meal-service/applications — List meal-benefits applications","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/applications","host":["{{baseUrl}}"],"path":["meal-service","applications"]},"description":"List meal-benefits applications"}},{"name":"POST /meal-service/applications — Submit a meal-benefits application (emits MealApplicationSubmitted)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/applications","host":["{{baseUrl}}"],"path":["meal-service","applications"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Submit a meal-benefits application (emits MealApplicationSubmitted)"}},{"name":"GET /meal-service/applications/{id} — Get a meal-benefits application with its members","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/applications/{id}","host":["{{baseUrl}}"],"path":["meal-service","applications","{id}"]},"description":"Get a meal-benefits application with its members"}},{"name":"POST /meal-service/applications/{id}/approve — Approve an application and stamp eligibility for covered students","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/applications/{id}/approve","host":["{{baseUrl}}"],"path":["meal-service","applications","{id}","approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Derives the NSLP category from the household income (or honors a categorical basis). Writes a MealEligibility row and a MealAccount for every student member. Emits MealApplicationApproved + MealEligibilitySet per student."}},{"name":"POST /meal-service/applications/{id}/deny — Deny an application (emits MealApplicationDenied)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/applications/{id}/deny","host":["{{baseUrl}}"],"path":["meal-service","applications","{id}","deny"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deny an application (emits MealApplicationDenied)"}},{"name":"GET /meal-service/eligibility — List per-student meal eligibility records","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/eligibility","host":["{{baseUrl}}"],"path":["meal-service","eligibility"]},"description":"List per-student meal eligibility records"}},{"name":"POST /meal-service/eligibility — Write a per-student eligibility record (emits MealEligibilitySet)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/eligibility","host":["{{baseUrl}}"],"path":["meal-service","eligibility"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Used for direct-certification matches, CEP-district bulk writes, and manual corrections. Open records for the student in the same window are ended at effectiveFrom. Ensures a meal account exists."}},{"name":"GET /meal-service/eligibility/summary — Eligibility category distribution + ISEP","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/eligibility/summary","host":["{{baseUrl}}"],"path":["meal-service","eligibility","summary"]},"description":"Counts active students in each NSLP category (free / reduced / paid) and the Identified Student Percentage (ISEP). ISEP drives whether the district can apply for Community Eligibility Provision (CEP)."}},{"name":"POST /meal-service/eligibility/{id}/end — End an eligibility window (emits MealEligibilityEnded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/eligibility/{id}/end","host":["{{baseUrl}}"],"path":["meal-service","eligibility","{id}","end"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"End an eligibility window (emits MealEligibilityEnded)"}},{"name":"GET /meal-service/accounts — List student meal accounts","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/accounts","host":["{{baseUrl}}"],"path":["meal-service","accounts"]},"description":"List student meal accounts"}},{"name":"POST /meal-service/accounts — Create or adopt a student meal account","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/accounts","host":["{{baseUrl}}"],"path":["meal-service","accounts"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Idempotent: if the student already has an account, its settings are updated with any provided fields."}},{"name":"GET /meal-service/accounts/{id} — Get a student meal account","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/accounts/{id}","host":["{{baseUrl}}"],"path":["meal-service","accounts","{id}"]},"description":"Get a student meal account"}},{"name":"PATCH /meal-service/accounts/{id} — Update meal-account settings","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/accounts/{id}","host":["{{baseUrl}}"],"path":["meal-service","accounts","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update meal-account settings"}},{"name":"POST /meal-service/accounts/{id}/fund — Add funds to a meal account (emits MealAccountFunded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/accounts/{id}/fund","host":["{{baseUrl}}"],"path":["meal-service","accounts","{id}","fund"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Records the payment, bumps the balance, and creates a payment transaction. Does NOT run a real payment — integrate a processor at the route boundary and then call this to finalize."}},{"name":"GET /meal-service/transactions — List meal transactions (POS ledger)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/transactions","host":["{{baseUrl}}"],"path":["meal-service","transactions"]},"description":"List meal transactions (POS ledger)"}},{"name":"POST /meal-service/pos/purchase — Record a POS meal purchase (emits MealPurchased)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/pos/purchase","host":["{{baseUrl}}"],"path":["meal-service","pos","purchase"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Looks up the student's current eligibility, charges the correct amount (free = $0, reduced = capped, paid = list price), debits the account, and marks the transaction reimbursable unless meal type is `a_la_carte`."}},{"name":"POST /meal-service/pos/transactions/{id}/refund — Refund a prior POS purchase (emits MealRefunded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/pos/transactions/{id}/refund","host":["{{baseUrl}}"],"path":["meal-service","pos","transactions","{id}","refund"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Refund a prior POS purchase (emits MealRefunded)"}},{"name":"GET /meal-service/service-days — List daily reimbursement claim rollups","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/service-days","host":["{{baseUrl}}"],"path":["meal-service","service-days"]},"description":"List daily reimbursement claim rollups"}},{"name":"POST /meal-service/service-days/close — Close a day's counts for reimbursement (emits MealServiceDayClosed)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/service-days/close","host":["{{baseUrl}}"],"path":["meal-service","service-days","close"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Recomputes counts from the ledger, then flips the status to `closed`. Re-runs are safe while status is `open`; once `claimed`, use an audit event to reopen."}},{"name":"GET /meal-service/reports/daily-counts — Daily reimbursable-counts report across a date range","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/reports/daily-counts","host":["{{baseUrl}}"],"path":["meal-service","reports","daily-counts"]},"description":"The basis for the state claim file. One row per school/date/meal-type. Results include open days so the director can see running totals."}}]},{"name":"Food Service – Direct Cert","item":[{"name":"GET /meal-service/direct-cert/imports — List direct-certification CSV imports","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/direct-cert/imports","host":["{{baseUrl}}"],"path":["meal-service","direct-cert","imports"]},"description":"List direct-certification CSV imports"}},{"name":"POST /meal-service/direct-cert/imports — Upload a state direct-cert CSV (returns a preview; not yet applied)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/direct-cert/imports","host":["{{baseUrl}}"],"path":["meal-service","direct-cert","imports"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Parse the CSV, match against the enrolled student roster, and persist a `preview` import. No eligibility records are written until you POST to `/:id/apply`. The CSV text is accepted as a JSON string field to avoid a multipart dependency."}},{"name":"GET /meal-service/direct-cert/imports/{id} — Get a direct-cert import with all per-student result rows","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/direct-cert/imports/{id}","host":["{{baseUrl}}"],"path":["meal-service","direct-cert","imports","{id}"]},"description":"Get a direct-cert import with all per-student result rows"}},{"name":"POST /meal-service/direct-cert/imports/{id}/apply — Apply a preview import — writes eligibility records for all matched students","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/direct-cert/imports/{id}/apply","host":["{{baseUrl}}"],"path":["meal-service","direct-cert","imports","{id}","apply"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stamps a `MealEligibility` row (basis=direct_cert, category=free) for every matched (or manually accepted) result row, then marks the import as `applied`. This action is irreversible — discard first if you want to reject the import."}},{"name":"POST /meal-service/direct-cert/imports/{id}/discard — Discard a preview import (no eligibility records written)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/meal-service/direct-cert/imports/{id}/discard","host":["{{baseUrl}}"],"path":["meal-service","direct-cert","imports","{id}","discard"]},"description":"Discard a preview import (no eligibility records written)"}},{"name":"PATCH /meal-service/direct-cert/imports/{id}/results/{resultId} — Manually accept or reject a single match row before applying","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/direct-cert/imports/{id}/results/{resultId}","host":["{{baseUrl}}"],"path":["meal-service","direct-cert","imports","{id}","results","{resultId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Use `action=accept` to link an unmatched row to a specific student. Use `action=reject` to prevent an incorrectly auto-matched row from receiving an eligibility record when the import is applied."}}]},{"name":"Food Service – POS Inbound","item":[{"name":"POST /meal-service/pos/inbound — External POS terminal webhook — ingest a transaction for staging","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/pos/inbound","host":["{{baseUrl}}"],"path":["meal-service","pos","inbound"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Called by external POS hardware or software on each meal served. The request MUST include an `X-Forge-Signature: sha256=<hex-hmac>` header computed over the raw JSON body using the terminal's shared secret configured in `District.settings.posTerminals[terminalId].secret`. Duplicate payloads (same districtId + terminalId + externalTxnId) are silently accepted and return the existing record — safe for at-least-once delivery."}},{"name":"GET /meal-service/pos/inbound — List external POS inbound transactions (staging)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/pos/inbound","host":["{{baseUrl}}"],"path":["meal-service","pos","inbound"]},"description":"List external POS inbound transactions (staging)"}},{"name":"GET /meal-service/pos/inbound/{id} — Get a single external POS inbound transaction","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/pos/inbound/{id}","host":["{{baseUrl}}"],"path":["meal-service","pos","inbound","{id}"]},"description":"Get a single external POS inbound transaction"}},{"name":"POST /meal-service/pos/inbound/{id}/reconcile — Reconcile a staged POS transaction → writes a canonical MealTransaction","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/meal-service/pos/inbound/{id}/reconcile","host":["{{baseUrl}}"],"path":["meal-service","pos","inbound","{id}","reconcile"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"The director confirms the student was present and received the meal. This writes a `MealTransaction` via the same `recordPurchase` path used by the internal cashier POS (eligibility lookup, free/reduced pricing, reimbursable flag, service-day rollup rebuild all apply)."}},{"name":"POST /meal-service/pos/inbound/{id}/ignore — Mark a staged POS transaction as ignored (no meal transaction created)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/meal-service/pos/inbound/{id}/ignore","host":["{{baseUrl}}"],"path":["meal-service","pos","inbound","{id}","ignore"]},"description":"Use when a transaction is a duplicate, test ping, or a non-meal event from the external terminal. Ignored rows stay in the audit log but do not affect counts or reimbursable totals."}},{"name":"GET /meal-service/pos/inbound/reconciliation — POS inbound reconciliation summary — counts per terminal over a date range","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/meal-service/pos/inbound/reconciliation","host":["{{baseUrl}}"],"path":["meal-service","pos","inbound","reconciliation"]},"description":"POS inbound reconciliation summary — counts per terminal over a date range"}}]},{"name":"Fees","item":[{"name":"GET /fees/catalog — List fee catalog entries","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees/catalog","host":["{{baseUrl}}"],"path":["fees","catalog"]},"description":"List fee catalog entries"}},{"name":"POST /fees/catalog — Create a fee catalog entry (emits FeeCatalogCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/catalog","host":["{{baseUrl}}"],"path":["fees","catalog"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a fee catalog entry (emits FeeCatalogCreated)"}},{"name":"GET /fees/catalog/{id} — Get a fee catalog entry","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees/catalog/{id}","host":["{{baseUrl}}"],"path":["fees","catalog","{id}"]},"description":"Get a fee catalog entry"}},{"name":"PATCH /fees/catalog/{id} — Update a fee catalog entry (emits FeeCatalogUpdated)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/catalog/{id}","host":["{{baseUrl}}"],"path":["fees","catalog","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a fee catalog entry (emits FeeCatalogUpdated)"}},{"name":"DELETE /fees/catalog/{id} — Archive a fee catalog entry (soft delete; emits FeeCatalogArchived)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/fees/catalog/{id}","host":["{{baseUrl}}"],"path":["fees","catalog","{id}"]},"description":"Archive a fee catalog entry (soft delete; emits FeeCatalogArchived)"}},{"name":"GET /fees — List student fees","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees","host":["{{baseUrl}}"],"path":["fees"]},"description":"List student fees"}},{"name":"POST /fees — Assess a single fee against a student (emits FeeAssessed)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees","host":["{{baseUrl}}"],"path":["fees"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assess a single fee against a student (emits FeeAssessed)"}},{"name":"GET /fees/{id} — Get a student fee with its payments","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees/{id}","host":["{{baseUrl}}"],"path":["fees","{id}"]},"description":"Get a student fee with its payments"}},{"name":"POST /fees/bulk-assess — Assess a catalog fee against many students (emits one FeeAssessed per student)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/bulk-assess","host":["{{baseUrl}}"],"path":["fees","bulk-assess"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assess a catalog fee against many students (emits one FeeAssessed per student)"}},{"name":"POST /fees/{id}/waive — Waive a student fee (admin forgiveness; emits FeeWaived)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/{id}/waive","host":["{{baseUrl}}"],"path":["fees","{id}","waive"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Waive a student fee (admin forgiveness; emits FeeWaived)"}},{"name":"POST /fees/{id}/void — Void a student fee (assessed in error; emits FeeVoided)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/{id}/void","host":["{{baseUrl}}"],"path":["fees","{id}","void"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Void a student fee (assessed in error; emits FeeVoided)"}},{"name":"GET /fees/reports/summary — District-wide fees summary (for business-office dashboard)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees/reports/summary","host":["{{baseUrl}}"],"path":["fees","reports","summary"]},"description":"District-wide fees summary (for business-office dashboard)"}},{"name":"GET /fees/payments — List fee payments (includes refunds as negative rows)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees/payments","host":["{{baseUrl}}"],"path":["fees","payments"]},"description":"List fee payments (includes refunds as negative rows)"}},{"name":"POST /fees/{id}/payments — Record an in-office payment against a fee (emits FeePaid)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/{id}/payments","host":["{{baseUrl}}"],"path":["fees","{id}","payments"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Use for check, cash, school-cash (external), or manual adjustment payments. Online Stripe payments use the family endpoint which also finalizes the PaymentIntent."}},{"name":"POST /fees/payments/{id}/refund — Refund a previous payment (emits FeeRefunded)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/payments/{id}/refund","host":["{{baseUrl}}"],"path":["fees","payments","{id}","refund"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Stored as a negative `FeePayment` that points at the original via `refundedFromId`. Refuses over-refund."}},{"name":"POST /fees/{id}/checkout — Create a Stripe hosted-checkout session for a fee (parent portal)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/fees/{id}/checkout","host":["{{baseUrl}}"],"path":["fees","{id}","checkout"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Creates a Stripe Checkout Session for the specified fee. The response contains `sessionUrl` — the parent portal navigates to this URL. Stripe handles the card form. On completion, Stripe calls our webhook which projects the payment into the fee ledger."}},{"name":"GET /fees/payments/reconciliation — Payment reconciliation — online vs. in-office totals (admin GL export)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/fees/payments/reconciliation","host":["{{baseUrl}}"],"path":["fees","payments","reconciliation"]},"description":"Aggregate payment totals by processor channel for a given date range. Used by the business office to reconcile Stripe settlements against in-office deposits."}}]},{"name":"Substitutes","item":[{"name":"GET /sub/profiles — List substitute teachers in the district pool","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/profiles","host":["{{baseUrl}}"],"path":["sub","profiles"]},"description":"List substitute teachers in the district pool"}},{"name":"POST /sub/profiles — Add a substitute to the pool (emits SubstituteProfileCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/profiles","host":["{{baseUrl}}"],"path":["sub","profiles"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a substitute to the pool (emits SubstituteProfileCreated)"}},{"name":"GET /sub/profiles/{id} — Get a substitute profile","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/profiles/{id}","host":["{{baseUrl}}"],"path":["sub","profiles","{id}"]},"description":"Get a substitute profile"}},{"name":"PATCH /sub/profiles/{id} — Update a substitute profile (emits SubstituteProfileUpdated)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/profiles/{id}","host":["{{baseUrl}}"],"path":["sub","profiles","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a substitute profile (emits SubstituteProfileUpdated)"}},{"name":"POST /sub/profiles/{id}/archive — Archive a substitute (emits SubstituteProfileArchived)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/profiles/{id}/archive","host":["{{baseUrl}}"],"path":["sub","profiles","{id}","archive"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Archive a substitute (emits SubstituteProfileArchived)"}},{"name":"GET /sub/profiles/me — Load the current user's own substitute profile (sub portal)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/profiles/me","host":["{{baseUrl}}"],"path":["sub","profiles","me"]},"description":"Load the current user's own substitute profile (sub portal)"}},{"name":"GET /sub/absences — List staff absences","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/absences","host":["{{baseUrl}}"],"path":["sub","absences"]},"description":"List staff absences"}},{"name":"POST /sub/absences — Report a staff absence (emits StaffAbsenceReported)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/absences","host":["{{baseUrl}}"],"path":["sub","absences"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Report a staff absence (emits StaffAbsenceReported)"}},{"name":"GET /sub/absences/mine — List the acting teacher's own absences (scoped server-side by personId)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/absences/mine","host":["{{baseUrl}}"],"path":["sub","absences","mine"]},"description":"List the acting teacher's own absences (scoped server-side by personId)"}},{"name":"GET /sub/absences/{id} — Get a staff absence","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/absences/{id}","host":["{{baseUrl}}"],"path":["sub","absences","{id}"]},"description":"Get a staff absence"}},{"name":"POST /sub/absences/report-mine — Report the acting teacher's own absence (scoped server-side by personId)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/absences/report-mine","host":["{{baseUrl}}"],"path":["sub","absences","report-mine"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Report the acting teacher's own absence (scoped server-side by personId)"}},{"name":"POST /sub/absences/{id}/approve — Approve a reported absence (emits StaffAbsenceApproved)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/absences/{id}/approve","host":["{{baseUrl}}"],"path":["sub","absences","{id}","approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Approve a reported absence (emits StaffAbsenceApproved)"}},{"name":"POST /sub/absences/{id}/deny — Deny a reported absence (emits StaffAbsenceDenied)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/absences/{id}/deny","host":["{{baseUrl}}"],"path":["sub","absences","{id}","deny"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deny a reported absence (emits StaffAbsenceDenied)"}},{"name":"POST /sub/absences/{id}/cancel — Cancel a reported absence (emits StaffAbsenceCancelled + SubJobCancelled per open job)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/absences/{id}/cancel","host":["{{baseUrl}}"],"path":["sub","absences","{id}","cancel"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Cancel a reported absence (emits StaffAbsenceCancelled + SubJobCancelled per open job)"}},{"name":"GET /sub/jobs — List sub jobs","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/jobs","host":["{{baseUrl}}"],"path":["sub","jobs"]},"description":"List sub jobs"}},{"name":"POST /sub/jobs — Post a sub job against an approved absence (emits SubJobPosted)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/jobs","host":["{{baseUrl}}"],"path":["sub","jobs"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Post a sub job against an approved absence (emits SubJobPosted)"}},{"name":"GET /sub/jobs/{id} — Get a sub job with offers + assignment + absence","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/jobs/{id}","host":["{{baseUrl}}"],"path":["sub","jobs","{id}"]},"description":"Get a sub job with offers + assignment + absence"}},{"name":"POST /sub/jobs/{id}/offer — Offer a sub job to a specific substitute (emits SubJobOffered)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/jobs/{id}/offer","host":["{{baseUrl}}"],"path":["sub","jobs","{id}","offer"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Offer a sub job to a specific substitute (emits SubJobOffered)"}},{"name":"POST /sub/jobs/{id}/assign — Manually assign a sub to a job (emits SubJobFilled; rescinds pending offers)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/jobs/{id}/assign","host":["{{baseUrl}}"],"path":["sub","jobs","{id}","assign"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Manually assign a sub to a job (emits SubJobFilled; rescinds pending offers)"}},{"name":"POST /sub/jobs/{id}/cancel — Cancel a sub job (emits SubJobCancelled; rescinds pending offers)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/jobs/{id}/cancel","host":["{{baseUrl}}"],"path":["sub","jobs","{id}","cancel"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Cancel a sub job (emits SubJobCancelled; rescinds pending offers)"}},{"name":"POST /sub/jobs/{id}/complete — Close out a filled job with clock-in/out (emits SubJobCompleted)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/jobs/{id}/complete","host":["{{baseUrl}}"],"path":["sub","jobs","{id}","complete"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Close out a filled job with clock-in/out (emits SubJobCompleted)"}},{"name":"POST /sub/jobs/{id}/auto-match — Rank substitute pool against a job (emits SubJobAutoMatched; optionally sends offers)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/sub/jobs/{id}/auto-match","host":["{{baseUrl}}"],"path":["sub","jobs","{id}","auto-match"]},"description":"Scores all active substitutes against availability, school preference, certifications, and recent load. Returns ranked candidates. When sendOffers=true, dispatches offers to the top sendTopN candidates automatically. Offer dispatch is idempotent — safe to run multiple times."}},{"name":"GET /sub/reports/summary — District-wide sub-pool KPIs (fill rate, time-to-fill, unfilled mustFill)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/reports/summary","host":["{{baseUrl}}"],"path":["sub","reports","summary"]},"description":"District-wide sub-pool KPIs (fill rate, time-to-fill, unfilled mustFill)"}},{"name":"GET /sub/portal/my-board — List the acting substitute's open offers, accepted assignments, and general job board","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/sub/portal/my-board","host":["{{baseUrl}}"],"path":["sub","portal","my-board"]},"description":"List the acting substitute's open offers, accepted assignments, and general job board"}},{"name":"POST /sub/portal/offers/{id}/accept — Accept a pending offer (emits SubJobOfferAccepted + SubJobFilled)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/sub/portal/offers/{id}/accept","host":["{{baseUrl}}"],"path":["sub","portal","offers","{id}","accept"]},"description":"Accept a pending offer (emits SubJobOfferAccepted + SubJobFilled)"}},{"name":"POST /sub/portal/offers/{id}/decline — Decline a pending offer (emits SubJobOfferDeclined)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/sub/portal/offers/{id}/decline","host":["{{baseUrl}}"],"path":["sub","portal","offers","{id}","decline"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Decline a pending offer (emits SubJobOfferDeclined)"}}]},{"name":"Certifications","item":[{"name":"GET /certs — List teacher certifications","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/certs","host":["{{baseUrl}}"],"path":["certs"]},"description":"List teacher certifications"}},{"name":"POST /certs — Record a certification (emits TeacherCertificationCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/certs","host":["{{baseUrl}}"],"path":["certs"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a certification (emits TeacherCertificationCreated)"}},{"name":"GET /certs/{id} — Get a single certification","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/certs/{id}","host":["{{baseUrl}}"],"path":["certs","{id}"]},"description":"Get a single certification"}},{"name":"PATCH /certs/{id} — Update a certification (emits TeacherCertificationUpdated)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/certs/{id}","host":["{{baseUrl}}"],"path":["certs","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a certification (emits TeacherCertificationUpdated)"}},{"name":"POST /certs/{id}/revoke — Mark a certification revoked (emits TeacherCertificationRevoked)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/certs/{id}/revoke","host":["{{baseUrl}}"],"path":["certs","{id}","revoke"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Mark a certification revoked (emits TeacherCertificationRevoked)"}},{"name":"POST /certs/sweep-expirations — Sweep expired certs (manual trigger — normally runs on schedule). Emits TeacherCertificationExpired per flipped row.","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/certs/sweep-expirations","host":["{{baseUrl}}"],"path":["certs","sweep-expirations"]},"description":"Sweep expired certs (manual trigger — normally runs on schedule). Emits TeacherCertificationExpired per flipped row."}},{"name":"GET /certs/assignment-check — Check whether a person holds the certs required for a given role/subject/grade assignment","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/certs/assignment-check","host":["{{baseUrl}}"],"path":["certs","assignment-check"]},"description":"Check whether a person holds the certs required for a given role/subject/grade assignment"}},{"name":"GET /certs/requirements — List certification requirement rules","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/certs/requirements","host":["{{baseUrl}}"],"path":["certs","requirements"]},"description":"List certification requirement rules"}},{"name":"POST /certs/requirements — Add a cert requirement rule (emits CertificationRequirementCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/certs/requirements","host":["{{baseUrl}}"],"path":["certs","requirements"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a cert requirement rule (emits CertificationRequirementCreated)"}},{"name":"PATCH /certs/requirements/{id} — Update a cert requirement rule (emits CertificationRequirementUpdated)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/certs/requirements/{id}","host":["{{baseUrl}}"],"path":["certs","requirements","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a cert requirement rule (emits CertificationRequirementUpdated)"}},{"name":"POST /certs/requirements/{id}/deactivate — Deactivate a cert requirement rule (emits CertificationRequirementDeactivated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/certs/requirements/{id}/deactivate","host":["{{baseUrl}}"],"path":["certs","requirements","{id}","deactivate"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deactivate a cert requirement rule (emits CertificationRequirementDeactivated)"}}]},{"name":"Facilities","item":[{"name":"GET /facilities/settings — Get the district facilities settings (SLAs, ticket format, depreciation defaults)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/facilities/settings","host":["{{baseUrl}}"],"path":["facilities","settings"]},"description":"Get the district facilities settings (SLAs, ticket format, depreciation defaults)"}},{"name":"PATCH /facilities/settings — Update the district facilities settings (emits FacilitiesSettingsUpdated)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/facilities/settings","host":["{{baseUrl}}"],"path":["facilities","settings"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update the district facilities settings (emits FacilitiesSettingsUpdated)"}},{"name":"GET /rooms — List rooms (filter by school, type, bookability)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/rooms","host":["{{baseUrl}}"],"path":["rooms"]},"description":"List rooms (filter by school, type, bookability)"}},{"name":"POST /rooms — Create a room (emits RoomCreated)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/rooms","host":["{{baseUrl}}"],"path":["rooms"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a room (emits RoomCreated)"}},{"name":"GET /rooms/{id} — Get a room","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/rooms/{id}","host":["{{baseUrl}}"],"path":["rooms","{id}"]},"description":"Get a room"}},{"name":"PATCH /rooms/{id} — Edit a room (emits RoomUpdated when fields change)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/rooms/{id}","host":["{{baseUrl}}"],"path":["rooms","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Edit a room (emits RoomUpdated when fields change)"}},{"name":"POST /rooms/{id}/retire — Retire a room (soft-delete, emits RoomRetired)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/rooms/{id}/retire","host":["{{baseUrl}}"],"path":["rooms","{id}","retire"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Retire a room (soft-delete, emits RoomRetired)"}},{"name":"GET /work-orders — List work orders (board view)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/work-orders","host":["{{baseUrl}}"],"path":["work-orders"]},"description":"List work orders (board view)"}},{"name":"POST /work-orders — Open a work order (emits WorkOrderOpened)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders","host":["{{baseUrl}}"],"path":["work-orders"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Open a work order (emits WorkOrderOpened)"}},{"name":"GET /work-orders/{id} — Get a work order with its full event thread","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/work-orders/{id}","host":["{{baseUrl}}"],"path":["work-orders","{id}"]},"description":"Get a work order with its full event thread"}},{"name":"PATCH /work-orders/{id} — Edit a work order (title / description / category / priority / room / SLA)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders/{id}","host":["{{baseUrl}}"],"path":["work-orders","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Edit a work order (title / description / category / priority / room / SLA)"}},{"name":"POST /work-orders/{id}/assign — Assign or reassign the ticket (emits WorkOrderAssigned)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders/{id}/assign","host":["{{baseUrl}}"],"path":["work-orders","{id}","assign"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assign or reassign the ticket (emits WorkOrderAssigned)"}},{"name":"POST /work-orders/{id}/status — Transition ticket status (emits WorkOrderStatusChanged)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders/{id}/status","host":["{{baseUrl}}"],"path":["work-orders","{id}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Transition ticket status (emits WorkOrderStatusChanged)"}},{"name":"POST /work-orders/{id}/comments — Comment on a work-order thread (emits WorkOrderCommented)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders/{id}/comments","host":["{{baseUrl}}"],"path":["work-orders","{id}","comments"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Comment on a work-order thread (emits WorkOrderCommented)"}},{"name":"POST /work-orders/{id}/resolve — Resolve a work order (emits WorkOrderResolved)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders/{id}/resolve","host":["{{baseUrl}}"],"path":["work-orders","{id}","resolve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Resolve a work order (emits WorkOrderResolved)"}},{"name":"POST /work-orders/{id}/cancel — Cancel a work order (emits WorkOrderCancelled)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/work-orders/{id}/cancel","host":["{{baseUrl}}"],"path":["work-orders","{id}","cancel"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Cancel a work order (emits WorkOrderCancelled)"}},{"name":"GET /assets — List assets","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assets","host":["{{baseUrl}}"],"path":["assets"]},"description":"List assets"}},{"name":"POST /assets — Register a new asset (emits AssetRegistered)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets","host":["{{baseUrl}}"],"path":["assets"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Register a new asset (emits AssetRegistered)"}},{"name":"GET /assets/reports/depreciation — Roll-up of book value by asset category","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assets/reports/depreciation","host":["{{baseUrl}}"],"path":["assets","reports","depreciation"]},"description":"Roll-up of book value by asset category"}},{"name":"GET /assets/{id} — Get an asset with its adjustment history","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assets/{id}","host":["{{baseUrl}}"],"path":["assets","{id}"]},"description":"Get an asset with its adjustment history"}},{"name":"PATCH /assets/{id} — Edit an asset","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets/{id}","host":["{{baseUrl}}"],"path":["assets","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Edit an asset"}},{"name":"POST /assets/{id}/move — Move an asset between rooms (emits AssetMoved)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets/{id}/move","host":["{{baseUrl}}"],"path":["assets","{id}","move"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Move an asset between rooms (emits AssetMoved)"}},{"name":"POST /assets/{id}/assign — Assign / unassign custody of an asset (emits AssetAssigned)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets/{id}/assign","host":["{{baseUrl}}"],"path":["assets","{id}","assign"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Assign / unassign custody of an asset (emits AssetAssigned)"}},{"name":"POST /assets/{id}/status — Change asset status (emits AssetStatusChanged)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets/{id}/status","host":["{{baseUrl}}"],"path":["assets","{id}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Change asset status (emits AssetStatusChanged)"}},{"name":"POST /assets/{id}/revalue — Apply a valuation adjustment (write-down, revaluation, etc.)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets/{id}/revalue","host":["{{baseUrl}}"],"path":["assets","{id}","revalue"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Apply a valuation adjustment (write-down, revaluation, etc.)"}},{"name":"POST /assets/{id}/retire — Retire an asset (soft-delete, emits AssetRetired)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assets/{id}/retire","host":["{{baseUrl}}"],"path":["assets","{id}","retire"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Retire an asset (soft-delete, emits AssetRetired)"}}]},{"name":"Safety","item":[{"name":"GET /safety-drills — List safety drills","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/safety-drills","host":["{{baseUrl}}"],"path":["safety-drills"]},"description":"List safety drills"}},{"name":"POST /safety-drills — Log a new safety drill (emits SafetyDrillLogged)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/safety-drills","host":["{{baseUrl}}"],"path":["safety-drills"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Log a new safety drill (emits SafetyDrillLogged)"}},{"name":"GET /safety-drills/annual-report — Annual state-report roll-up (NJ category counts per school)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/safety-drills/annual-report","host":["{{baseUrl}}"],"path":["safety-drills","annual-report"]},"description":"Annual state-report roll-up (NJ category counts per school)"}},{"name":"GET /safety-drills/{id} — Get a safety drill","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/safety-drills/{id}","host":["{{baseUrl}}"],"path":["safety-drills","{id}"]},"description":"Get a safety drill"}},{"name":"PATCH /safety-drills/{id} — Correct a drill entry (emits SafetyDrillCorrected when fields change)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/safety-drills/{id}","host":["{{baseUrl}}"],"path":["safety-drills","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Correct a drill entry (emits SafetyDrillCorrected when fields change)"}},{"name":"POST /safety-drills/{id}/visibility — Toggle public (parent-page) visibility (emits SafetyDrillVisibilityChanged)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/safety-drills/{id}/visibility","host":["{{baseUrl}}"],"path":["safety-drills","{id}","visibility"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Toggle public (parent-page) visibility (emits SafetyDrillVisibilityChanged)"}},{"name":"POST /safety-drills/report-filed — Mark all unreported drills for (school, schoolYear) as filed","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/safety-drills/report-filed","host":["{{baseUrl}}"],"path":["safety-drills","report-filed"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Mark all unreported drills for (school, schoolYear) as filed"}},{"name":"GET /schools/{schoolId}/safety/public-drills — Parent-facing drill list (date, type, duration only)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/schools/{schoolId}/safety/public-drills","host":["{{baseUrl}}"],"path":["schools","{schoolId}","safety","public-drills"]},"description":"No authentication required. Caller supplies districtId via the X-District-Id header (same mechanism the other dev-header routes use). Only drills flagged publicVisible=true are returned."}}]},{"name":"District Calendar","item":[{"name":"GET /district-calendar — List all calendar days for a school year (school overrides folded in if schoolId is passed)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/district-calendar","host":["{{baseUrl}}"],"path":["district-calendar"]},"description":"List all calendar days for a school year (school overrides folded in if schoolId is passed)"}},{"name":"POST /district-calendar/publish — Bulk-publish or re-publish the district calendar for a school year (emits CalendarPublished)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/district-calendar/publish","host":["{{baseUrl}}"],"path":["district-calendar","publish"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Bulk-publish or re-publish the district calendar for a school year (emits CalendarPublished)"}},{"name":"PATCH /district-calendar/days/{date} — Create or edit a single district calendar day (emits CalendarDaySet)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/district-calendar/days/{date}","host":["{{baseUrl}}"],"path":["district-calendar","days","{date}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create or edit a single district calendar day (emits CalendarDaySet)"}},{"name":"DELETE /district-calendar/days/{date} — Soft-delete a district calendar day (emits CalendarDayCleared)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/district-calendar/days/{date}","host":["{{baseUrl}}"],"path":["district-calendar","days","{date}"]},"description":"Soft-delete a district calendar day (emits CalendarDayCleared)"}},{"name":"POST /schools/{schoolId}/calendar-overrides — Create or replace a school-level calendar override (emits SchoolCalendarDayOverridden)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/schools/{schoolId}/calendar-overrides","host":["{{baseUrl}}"],"path":["schools","{schoolId}","calendar-overrides"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create or replace a school-level calendar override (emits SchoolCalendarDayOverridden)"}},{"name":"DELETE /schools/{schoolId}/calendar-overrides/{date} — Clear a school-level calendar override (emits SchoolCalendarOverrideCleared)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/schools/{schoolId}/calendar-overrides/{date}","host":["{{baseUrl}}"],"path":["schools","{schoolId}","calendar-overrides","{date}"]},"description":"Clear a school-level calendar override (emits SchoolCalendarOverrideCleared)"}},{"name":"GET /district-calendar/school-months — Enumerate NJDOE school months (20 consecutive instructional days)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/district-calendar/school-months","host":["{{baseUrl}}"],"path":["district-calendar","school-months"]},"description":"Enumerate NJDOE school months (20 consecutive instructional days)"}},{"name":"GET /district-calendar/nth-school-day — Compute the Nth instructional day from a starting date (HIB 10-school-day clock, truancy)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/district-calendar/nth-school-day","host":["{{baseUrl}}"],"path":["district-calendar","nth-school-day"]},"description":"Compute the Nth instructional day from a starting date (HIB 10-school-day clock, truancy)"}}]},{"name":"Feature Flags","item":[{"name":"GET /feature-flags — Effective feature flags for the current district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/feature-flags","host":["{{baseUrl}}"],"path":["feature-flags"]},"description":"Returns all platform feature flags resolved for this district. District-level overrides take precedence over platform defaults. Expired overrides are ignored."}}]},{"name":"Extracurriculars","item":[{"name":"GET /extracurriculars — List extracurricular activities","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/extracurriculars","host":["{{baseUrl}}"],"path":["extracurriculars"]},"description":"List extracurricular activities"}},{"name":"POST /extracurriculars — Create an extracurricular activity","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/extracurriculars","host":["{{baseUrl}}"],"path":["extracurriculars"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create an extracurricular activity"}},{"name":"GET /extracurriculars/{id} — Get a single extracurricular activity","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}","host":["{{baseUrl}}"],"path":["extracurriculars","{id}"]},"description":"Get a single extracurricular activity"}},{"name":"PATCH /extracurriculars/{id} — Update an extracurricular activity","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}","host":["{{baseUrl}}"],"path":["extracurriculars","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update an extracurricular activity"}},{"name":"GET /extracurriculars/{id}/roster — Get the roster for an extracurricular activity","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}/roster","host":["{{baseUrl}}"],"path":["extracurriculars","{id}","roster"]},"description":"Get the roster for an extracurricular activity"}},{"name":"POST /extracurriculars/{id}/roster — Add a student to the roster (runs eligibility check)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}/roster","host":["{{baseUrl}}"],"path":["extracurriculars","{id}","roster"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a student to the roster (runs eligibility check)"}},{"name":"DELETE /extracurriculars/{id}/roster/{studentId} — Drop a student from the roster","request":{"method":"DELETE","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}/roster/{studentId}","host":["{{baseUrl}}"],"path":["extracurriculars","{id}","roster","{studentId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Drop a student from the roster"}},{"name":"GET /extracurriculars/{id}/eligibility/{studentId} — Check eligibility for a single student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}/eligibility/{studentId}","host":["{{baseUrl}}"],"path":["extracurriculars","{id}","eligibility","{studentId}"]},"description":"Check eligibility for a single student"}},{"name":"POST /extracurriculars/{id}/consent/{studentId} — Record parental consent for a student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}/consent/{studentId}","host":["{{baseUrl}}"],"path":["extracurriculars","{id}","consent","{studentId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record parental consent for a student"}},{"name":"GET /extracurriculars/{id}/eligibility-report — Run eligibility check for all rostered students and return report","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/extracurriculars/{id}/eligibility-report","host":["{{baseUrl}}"],"path":["extracurriculars","{id}","eligibility-report"]},"description":"Run eligibility check for all rostered students and return report"}}]},{"name":"Assessments","item":[{"name":"GET /assessments/results — List assessment results across the district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assessments/results","host":["{{baseUrl}}"],"path":["assessments","results"]},"description":"List assessment results across the district"}},{"name":"GET /students/{studentId}/assessment-results — Get all assessment results for a student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{studentId}/assessment-results","host":["{{baseUrl}}"],"path":["students","{studentId}","assessment-results"]},"description":"Get all assessment results for a student"}},{"name":"POST /assessments/import/preview — Preview a CSV import — parse and match students without persisting","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assessments/import/preview","host":["{{baseUrl}}"],"path":["assessments","import","preview"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Preview a CSV import — parse and match students without persisting"}},{"name":"POST /assessments/import/apply — Apply a previewed import — persist assessment results","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/assessments/import/apply","host":["{{baseUrl}}"],"path":["assessments","import","apply"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Apply a previewed import — persist assessment results"}},{"name":"GET /assessments/imports — List assessment import history","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assessments/imports","host":["{{baseUrl}}"],"path":["assessments","imports"]},"description":"List assessment import history"}},{"name":"GET /assessments/imports/{id} — Get an assessment import record","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/assessments/imports/{id}","host":["{{baseUrl}}"],"path":["assessments","imports","{id}"]},"description":"Get an assessment import record"}}]},{"name":"Transfers","item":[{"name":"GET /students/{studentId}/transfers — List transfer requests for a student","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/students/{studentId}/transfers","host":["{{baseUrl}}"],"path":["students","{studentId}","transfers"]},"description":"List transfer requests for a student"}},{"name":"POST /students/{studentId}/transfers — Initiate an outbound transfer for a student","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/students/{studentId}/transfers","host":["{{baseUrl}}"],"path":["students","{studentId}","transfers"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Initiate an outbound transfer for a student"}},{"name":"GET /transfers/{id} — Get a single transfer request","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/transfers/{id}","host":["{{baseUrl}}"],"path":["transfers","{id}"]},"description":"Get a single transfer request"}},{"name":"PATCH /transfers/{id} — Update status or notes on a transfer request","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transfers/{id}","host":["{{baseUrl}}"],"path":["transfers","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update status or notes on a transfer request"}},{"name":"POST /transfers/{id}/package-records — Package student records using the configured adapter","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/transfers/{id}/package-records","host":["{{baseUrl}}"],"path":["transfers","{id}","package-records"]},"description":"Package student records using the configured adapter"}},{"name":"POST /transfers/{id}/complete — Mark a transfer as completed","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/transfers/{id}/complete","host":["{{baseUrl}}"],"path":["transfers","{id}","complete"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Mark a transfer as completed"}}]},{"name":"Purchase Orders","item":[{"name":"GET /purchase-orders — List purchase orders","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/purchase-orders","host":["{{baseUrl}}"],"path":["purchase-orders"]},"description":"List purchase orders"}},{"name":"POST /purchase-orders — Create a purchase order draft","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders","host":["{{baseUrl}}"],"path":["purchase-orders"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a purchase order draft"}},{"name":"GET /purchase-orders/{id} — Get a single purchase order with line items and approvals","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}","host":["{{baseUrl}}"],"path":["purchase-orders","{id}"]},"description":"Get a single purchase order with line items and approvals"}},{"name":"PATCH /purchase-orders/{id} — Update PO metadata (only before approval)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}","host":["{{baseUrl}}"],"path":["purchase-orders","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update PO metadata (only before approval)"}},{"name":"POST /purchase-orders/{id}/line-items — Add a line item to a PO","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/line-items","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","line-items"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a line item to a PO"}},{"name":"PATCH /purchase-orders/{id}/line-items/{itemId} — Update a PO line item","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/line-items/{itemId}","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","line-items","{itemId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a PO line item"}},{"name":"DELETE /purchase-orders/{id}/line-items/{itemId} — Remove a line item from a PO","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/line-items/{itemId}","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","line-items","{itemId}"]},"description":"Remove a line item from a PO"}},{"name":"POST /purchase-orders/{id}/submit — Submit a draft PO for approval","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/submit","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","submit"]},"description":"Submit a draft PO for approval"}},{"name":"POST /purchase-orders/{id}/approve — Approve a submitted PO","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/approve","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Approve a submitted PO"}},{"name":"POST /purchase-orders/{id}/reject — Reject a submitted PO","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/reject","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","reject"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Reject a submitted PO"}},{"name":"POST /purchase-orders/{id}/receive-items — Record received quantity for a line item","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/receive-items","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","receive-items"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record received quantity for a line item"}},{"name":"POST /purchase-orders/{id}/cancel — Cancel a purchase order","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/purchase-orders/{id}/cancel","host":["{{baseUrl}}"],"path":["purchase-orders","{id}","cancel"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Cancel a purchase order"}}]},{"name":"Professional Development","item":[{"name":"GET /pd/activities — List PD activities","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/pd/activities","host":["{{baseUrl}}"],"path":["pd","activities"]},"description":"List PD activities"}},{"name":"POST /pd/activities — Create a PD activity","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pd/activities","host":["{{baseUrl}}"],"path":["pd","activities"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a PD activity"}},{"name":"GET /pd/activities/{id} — Get a PD activity with enrollment and completion counts","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/pd/activities/{id}","host":["{{baseUrl}}"],"path":["pd","activities","{id}"]},"description":"Get a PD activity with enrollment and completion counts"}},{"name":"PATCH /pd/activities/{id} — Update a PD activity","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pd/activities/{id}","host":["{{baseUrl}}"],"path":["pd","activities","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a PD activity"}},{"name":"POST /pd/activities/{id}/enroll — Enroll a staff member in a PD activity","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pd/activities/{id}/enroll","host":["{{baseUrl}}"],"path":["pd","activities","{id}","enroll"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Enroll a staff member in a PD activity"}},{"name":"DELETE /pd/activities/{id}/enroll/{staffPersonId} — Cancel enrollment for a staff member","request":{"method":"DELETE","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pd/activities/{id}/enroll/{staffPersonId}","host":["{{baseUrl}}"],"path":["pd","activities","{id}","enroll","{staffPersonId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Cancel enrollment for a staff member"}},{"name":"POST /pd/activities/{id}/complete — Record completion for a staff member","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/pd/activities/{id}/complete","host":["{{baseUrl}}"],"path":["pd","activities","{id}","complete"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record completion for a staff member"}},{"name":"GET /pd/staff/{personId}/history — All PD completions for a staff member","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/pd/staff/{personId}/history","host":["{{baseUrl}}"],"path":["pd","staff","{personId}","history"]},"description":"All PD completions for a staff member"}},{"name":"GET /pd/staff/{personId}/credits-summary — PD credit hour totals by type and cert renewal category for a staff member","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/pd/staff/{personId}/credits-summary","host":["{{baseUrl}}"],"path":["pd","staff","{personId}","credits-summary"]},"description":"PD credit hour totals by type and cert renewal category for a staff member"}}]},{"name":"Volunteers","item":[{"name":"GET /volunteers/{personId}/clearances — List clearances for a volunteer","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/volunteers/{personId}/clearances","host":["{{baseUrl}}"],"path":["volunteers","{personId}","clearances"]},"description":"List clearances for a volunteer"}},{"name":"POST /volunteers/{personId}/clearances — Record a new clearance for a volunteer","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/volunteers/{personId}/clearances","host":["{{baseUrl}}"],"path":["volunteers","{personId}","clearances"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a new clearance for a volunteer"}},{"name":"GET /volunteers/clearances/expiring-soon — List active clearances expiring within 30 days","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/volunteers/clearances/expiring-soon","host":["{{baseUrl}}"],"path":["volunteers","clearances","expiring-soon"]},"description":"List active clearances expiring within 30 days"}},{"name":"PATCH /volunteers/clearances/{id} — Update a clearance record","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/volunteers/clearances/{id}","host":["{{baseUrl}}"],"path":["volunteers","clearances","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a clearance record"}},{"name":"POST /volunteers/clearances/{id}/revoke — Revoke a volunteer clearance","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/volunteers/clearances/{id}/revoke","host":["{{baseUrl}}"],"path":["volunteers","clearances","{id}","revoke"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Revoke a volunteer clearance"}}]},{"name":"Board","item":[{"name":"GET /board/meetings — List board meetings","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/board/meetings","host":["{{baseUrl}}"],"path":["board","meetings"]},"description":"List board meetings"}},{"name":"POST /board/meetings — Schedule a new board meeting","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/board/meetings","host":["{{baseUrl}}"],"path":["board","meetings"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Schedule a new board meeting"}},{"name":"GET /board/meetings/{id} — Get a board meeting with agenda items and minutes","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/board/meetings/{id}","host":["{{baseUrl}}"],"path":["board","meetings","{id}"]},"description":"Get a board meeting with agenda items and minutes"}},{"name":"PATCH /board/meetings/{id} — Update a board meeting","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/board/meetings/{id}","host":["{{baseUrl}}"],"path":["board","meetings","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a board meeting"}},{"name":"POST /board/meetings/{id}/agenda — Add an agenda item to a meeting","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/board/meetings/{id}/agenda","host":["{{baseUrl}}"],"path":["board","meetings","{id}","agenda"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add an agenda item to a meeting"}},{"name":"PATCH /board/meetings/{id}/agenda/{itemId} — Update an agenda item","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/board/meetings/{id}/agenda/{itemId}","host":["{{baseUrl}}"],"path":["board","meetings","{id}","agenda","{itemId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update an agenda item"}},{"name":"DELETE /board/meetings/{id}/agenda/{itemId} — Remove an agenda item","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/board/meetings/{id}/agenda/{itemId}","host":["{{baseUrl}}"],"path":["board","meetings","{id}","agenda","{itemId}"]},"description":"Remove an agenda item"}},{"name":"POST /board/meetings/{id}/minutes — Create or update meeting minutes","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/board/meetings/{id}/minutes","host":["{{baseUrl}}"],"path":["board","meetings","{id}","minutes"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create or update meeting minutes"}},{"name":"POST /board/meetings/{id}/publish-minutes — Publish meeting minutes publicly","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/board/meetings/{id}/publish-minutes","host":["{{baseUrl}}"],"path":["board","meetings","{id}","publish-minutes"]},"description":"Publish meeting minutes publicly"}},{"name":"GET /public/board/meetings/{districtId} — Public: upcoming meetings with published minutes for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/public/board/meetings/{districtId}","host":["{{baseUrl}}"],"path":["public","board","meetings","{districtId}"]},"description":"Public: upcoming meetings with published minutes for a district"}}]},{"name":"OPRA","item":[{"name":"GET /opra/requests — List OPRA requests","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/opra/requests","host":["{{baseUrl}}"],"path":["opra","requests"]},"description":"List OPRA requests"}},{"name":"POST /opra/requests — Record a new OPRA request (auto-computes 7-business-day deadline)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/opra/requests","host":["{{baseUrl}}"],"path":["opra","requests"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a new OPRA request (auto-computes 7-business-day deadline)"}},{"name":"GET /opra/requests/overdue — List overdue OPRA requests (past due date, not fulfilled or denied)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/opra/requests/overdue","host":["{{baseUrl}}"],"path":["opra","requests","overdue"]},"description":"List overdue OPRA requests (past due date, not fulfilled or denied)"}},{"name":"GET /opra/requests/{id} — Get a single OPRA request","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/opra/requests/{id}","host":["{{baseUrl}}"],"path":["opra","requests","{id}"]},"description":"Get a single OPRA request"}},{"name":"PATCH /opra/requests/{id} — Update an OPRA request status, response, notes, or assignment","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/opra/requests/{id}","host":["{{baseUrl}}"],"path":["opra","requests","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update an OPRA request status, response, notes, or assignment"}}]},{"name":"ChildFind","item":[{"name":"GET /child-find/referrals — List Child Find referrals","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/child-find/referrals","host":["{{baseUrl}}"],"path":["child-find","referrals"]},"description":"List Child Find referrals"}},{"name":"POST /child-find/referrals — Record a new Child Find referral (validates IDEA age window)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/child-find/referrals","host":["{{baseUrl}}"],"path":["child-find","referrals"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record a new Child Find referral (validates IDEA age window)"}},{"name":"GET /child-find/referrals/evaluation-due-soon — List referrals with evaluation deadlines within 14 days","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/child-find/referrals/evaluation-due-soon","host":["{{baseUrl}}"],"path":["child-find","referrals","evaluation-due-soon"]},"description":"List referrals with evaluation deadlines within 14 days"}},{"name":"GET /child-find/referrals/{id} — Get a Child Find referral","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/child-find/referrals/{id}","host":["{{baseUrl}}"],"path":["child-find","referrals","{id}"]},"description":"Get a Child Find referral"}},{"name":"PATCH /child-find/referrals/{id} — Update a Child Find referral","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/child-find/referrals/{id}","host":["{{baseUrl}}"],"path":["child-find","referrals","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a Child Find referral"}},{"name":"POST /child-find/referrals/{id}/determine-eligibility — Record eligibility determination for a referral","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/child-find/referrals/{id}/determine-eligibility","host":["{{baseUrl}}"],"path":["child-find","referrals","{id}","determine-eligibility"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Record eligibility determination for a referral"}},{"name":"POST /child-find/referrals/{id}/create-iep — Mark IEP as created from this referral","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/child-find/referrals/{id}/create-iep","host":["{{baseUrl}}"],"path":["child-find","referrals","{id}","create-iep"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Mark IEP as created from this referral"}}]},{"name":"Visitor","item":[{"name":"GET /visitor/kiosk-info — Return district/school branding for the public kiosk","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/visitor/kiosk-info","host":["{{baseUrl}}"],"path":["visitor","kiosk-info"]},"description":"Return district/school branding for the public kiosk"}},{"name":"POST /visitor/check-in — Check a visitor in (emits VisitorCheckedIn)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/visitor/check-in","host":["{{baseUrl}}"],"path":["visitor","check-in"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Check a visitor in (emits VisitorCheckedIn)"}},{"name":"GET /visitor/active — List visitors currently checked in","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/visitor/active","host":["{{baseUrl}}"],"path":["visitor","active"]},"description":"List visitors currently checked in"}},{"name":"GET /visitor — List visitor log entries (paginated)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/visitor","host":["{{baseUrl}}"],"path":["visitor"]},"description":"List visitor log entries (paginated)"}},{"name":"GET /visitor/{id} — Get a single visitor log entry","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/visitor/{id}","host":["{{baseUrl}}"],"path":["visitor","{id}"]},"description":"Get a single visitor log entry"}},{"name":"DELETE /visitor/{id} — Permanently delete a visitor log entry (emits VisitorDeleted)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/visitor/{id}","host":["{{baseUrl}}"],"path":["visitor","{id}"]},"description":"Permanently delete a visitor log entry (emits VisitorDeleted)"}},{"name":"POST /visitor/{id}/check-out — Check a visitor out (emits VisitorCheckedOut)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/visitor/{id}/check-out","host":["{{baseUrl}}"],"path":["visitor","{id}","check-out"]},"description":"Check a visitor out (emits VisitorCheckedOut)"}},{"name":"POST /visitor/{id}/deny — Deny a visitor entry (emits VisitorDenied)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/visitor/{id}/deny","host":["{{baseUrl}}"],"path":["visitor","{id}","deny"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Deny a visitor entry (emits VisitorDenied)"}}]},{"name":"Surveys","item":[{"name":"GET /surveys — List surveys with response counts","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/surveys","host":["{{baseUrl}}"],"path":["surveys"]},"description":"List surveys with response counts"}},{"name":"POST /surveys — Create a survey (status = DRAFT)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/surveys","host":["{{baseUrl}}"],"path":["surveys"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a survey (status = DRAFT)"}},{"name":"GET /surveys/{id} — Get a survey with its questions","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}","host":["{{baseUrl}}"],"path":["surveys","{id}"]},"description":"Get a survey with its questions"}},{"name":"PATCH /surveys/{id} — Update a survey (active surveys: only dates may change)","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/surveys/{id}","host":["{{baseUrl}}"],"path":["surveys","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a survey (active surveys: only dates may change)"}},{"name":"DELETE /surveys/{id} — Delete a DRAFT survey (hard delete — only if 0 responses)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}","host":["{{baseUrl}}"],"path":["surveys","{id}"]},"description":"Delete a DRAFT survey (hard delete — only if 0 responses)"}},{"name":"POST /surveys/{id}/publish — Publish a survey (must have ≥1 question)","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}/publish","host":["{{baseUrl}}"],"path":["surveys","{id}","publish"]},"description":"Publish a survey (must have ≥1 question)"}},{"name":"POST /surveys/{id}/close — Close a survey","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}/close","host":["{{baseUrl}}"],"path":["surveys","{id}","close"]},"description":"Close a survey"}},{"name":"POST /surveys/{id}/questions — Add a question to a survey","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/surveys/{id}/questions","host":["{{baseUrl}}"],"path":["surveys","{id}","questions"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a question to a survey"}},{"name":"PATCH /surveys/{id}/questions/{qid} — Update a survey question","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/surveys/{id}/questions/{qid}","host":["{{baseUrl}}"],"path":["surveys","{id}","questions","{qid}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a survey question"}},{"name":"DELETE /surveys/{id}/questions/{qid} — Delete a question (only on DRAFT surveys)","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}/questions/{qid}","host":["{{baseUrl}}"],"path":["surveys","{id}","questions","{qid}"]},"description":"Delete a question (only on DRAFT surveys)"}},{"name":"GET /surveys/respond-eligible — List active surveys the calling user can respond to","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/surveys/respond-eligible","host":["{{baseUrl}}"],"path":["surveys","respond-eligible"]},"description":"List active surveys the calling user can respond to"}},{"name":"GET /surveys/{id}/respond — Get survey questions for responding (audience-gated)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}/respond","host":["{{baseUrl}}"],"path":["surveys","{id}","respond"]},"description":"Get survey questions for responding (audience-gated)"}},{"name":"POST /surveys/{id}/responses — Submit a survey response","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/surveys/{id}/responses","host":["{{baseUrl}}"],"path":["surveys","{id}","responses"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Submit a survey response"}},{"name":"GET /surveys/{id}/responses — List individual responses (admin only)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}/responses","host":["{{baseUrl}}"],"path":["surveys","{id}","responses"]},"description":"List individual responses (admin only)"}},{"name":"GET /surveys/{id}/results — Aggregate results by question","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/surveys/{id}/results","host":["{{baseUrl}}"],"path":["surveys","{id}","results"]},"description":"Aggregate results by question"}}]},{"name":"Websites","item":[{"name":"GET /websites/templates — List available website templates","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/templates","host":["{{baseUrl}}"],"path":["websites","templates"]},"description":"List available website templates"}},{"name":"GET /websites/sites — List sites for this district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites","host":["{{baseUrl}}"],"path":["websites","sites"]},"description":"List sites for this district"}},{"name":"POST /websites/sites — Create a site","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites","host":["{{baseUrl}}"],"path":["websites","sites"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a site"}},{"name":"GET /websites/sites/{siteId} — Get a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}"]},"description":"Get a site"}},{"name":"PATCH /websites/sites/{siteId} — Update a site","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a site"}},{"name":"DELETE /websites/sites/{siteId} — Archive (soft-delete) a site","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}"]},"description":"Archive (soft-delete) a site"}},{"name":"GET /websites/sites/{siteId}/pages — List pages for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages"]},"description":"List pages for a site"}},{"name":"POST /websites/sites/{siteId}/pages — Create a page","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a page"}},{"name":"GET /websites/sites/{siteId}/pages/{pageId} — Get a page with its blocks","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}"]},"description":"Get a page with its blocks"}},{"name":"PATCH /websites/sites/{siteId}/pages/{pageId} — Update a page","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a page"}},{"name":"DELETE /websites/sites/{siteId}/pages/{pageId} — Delete a page","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}"]},"description":"Delete a page"}},{"name":"POST /websites/sites/{siteId}/pages/{pageId}/blocks — Add a block to a page","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}/blocks","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}","blocks"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a block to a page"}},{"name":"PATCH /websites/sites/{siteId}/pages/{pageId}/blocks/{blockId} — Update a block","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}/blocks/{blockId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}","blocks","{blockId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a block"}},{"name":"DELETE /websites/sites/{siteId}/pages/{pageId}/blocks/{blockId} — Remove a block","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}/blocks/{blockId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}","blocks","{blockId}"]},"description":"Remove a block"}},{"name":"POST /websites/sites/{siteId}/pages/{pageId}/blocks/reorder — Reorder blocks on a page","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/pages/{pageId}/blocks/reorder","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","pages","{pageId}","blocks","reorder"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Reorder blocks on a page"}},{"name":"GET /websites/sites/{siteId}/branding — Get branding for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/branding","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","branding"]},"description":"Get branding for a site"}},{"name":"PUT /websites/sites/{siteId}/branding — Upsert branding for a site","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/branding","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","branding"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Upsert branding for a site"}},{"name":"GET /websites/sites/{siteId}/domains — List domains for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/domains","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","domains"]},"description":"List domains for a site"}},{"name":"POST /websites/sites/{siteId}/domains — Add a custom domain","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/domains","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","domains"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add a custom domain"}},{"name":"POST /websites/sites/{siteId}/domains/{domainId}/verify — Trigger domain verification","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/domains/{domainId}/verify","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","domains","{domainId}","verify"]},"description":"Trigger domain verification"}},{"name":"DELETE /websites/sites/{siteId}/domains/{domainId} — Remove a domain","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/domains/{domainId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","domains","{domainId}"]},"description":"Remove a domain"}},{"name":"GET /websites/sites/{siteId}/redirects — List redirects for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/redirects","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","redirects"]},"description":"List redirects for a site"}},{"name":"POST /websites/sites/{siteId}/redirects — Create a redirect","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/redirects","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","redirects"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a redirect"}},{"name":"PATCH /websites/sites/{siteId}/redirects/{redirectId} — Update a redirect","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/redirects/{redirectId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","redirects","{redirectId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update a redirect"}},{"name":"DELETE /websites/sites/{siteId}/redirects/{redirectId} — Delete a redirect","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/redirects/{redirectId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","redirects","{redirectId}"]},"description":"Delete a redirect"}},{"name":"POST /websites/sites/{siteId}/redirects/bulk-approve — Bulk approve crawl-suggested redirects","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/redirects/bulk-approve","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","redirects","bulk-approve"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Bulk approve crawl-suggested redirects"}},{"name":"GET /websites/sites/{siteId}/media — List media assets for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/media","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","media"]},"description":"List media assets for a site"}},{"name":"POST /websites/sites/{siteId}/media — Register an uploaded media asset","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/media","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","media"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Register an uploaded media asset"}},{"name":"DELETE /websites/sites/{siteId}/media/{assetId} — Soft-delete a media asset","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/media/{assetId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","media","{assetId}"]},"description":"Soft-delete a media asset"}},{"name":"GET /websites/sites/{siteId}/crawl — List crawl jobs for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/crawl","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","crawl"]},"description":"List crawl jobs for a site"}},{"name":"POST /websites/sites/{siteId}/crawl — Start a site crawl job","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/crawl","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","crawl"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Start a site crawl job"}},{"name":"GET /websites/sites/{siteId}/crawl/{jobId} — Get crawl job with results","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/crawl/{jobId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","crawl","{jobId}"]},"description":"Get crawl job with results"}},{"name":"GET /websites/sites/{siteId}/permissions — List editor permissions for a site","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/permissions","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","permissions"]},"description":"List editor permissions for a site"}},{"name":"POST /websites/sites/{siteId}/permissions — Add an editor to a site","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/permissions","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","permissions"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Add an editor to a site"}},{"name":"PATCH /websites/sites/{siteId}/permissions/{permId} — Update editor role","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/permissions/{permId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","permissions","{permId}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update editor role"}},{"name":"DELETE /websites/sites/{siteId}/permissions/{permId} — Remove an editor from a site","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/websites/sites/{siteId}/permissions/{permId}","host":["{{baseUrl}}"],"path":["websites","sites","{siteId}","permissions","{permId}"]},"description":"Remove an editor from a site"}}]},{"name":"Websites – Preview","item":[{"name":"GET /websites/preview/{previewSlug} — Get site layout (public)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/preview/{previewSlug}","host":["{{baseUrl}}"],"path":["websites","preview","{previewSlug}"]},"description":"Get site layout (public)"}},{"name":"GET /websites/preview/{previewSlug}/page — Get a page with blocks (public)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/preview/{previewSlug}/page","host":["{{baseUrl}}"],"path":["websites","preview","{previewSlug}","page"]},"description":"Get a page with blocks (public)"}},{"name":"GET /websites/preview/{previewSlug}/live-data — Get live district data for website blocks (public)","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/websites/preview/{previewSlug}/live-data","host":["{{baseUrl}}"],"path":["websites","preview","{previewSlug}","live-data"]},"description":"Get live district data for website blocks (public)"}}]},{"name":"Integrations · OneRoster","item":[{"name":"GET /integrations/oneroster/outbound/export — Generate and download a OneRoster 1.2 CSV ZIP export","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/integrations/oneroster/outbound/export","host":["{{baseUrl}}"],"path":["integrations","oneroster","outbound","export"]},"description":"Generates a complete OneRoster 1.2 bulk export for the district and returns it as a ZIP file. Requires the district to be on Professional or Enterprise plan."}},{"name":"GET /integrations/oneroster/outbound/status — Last OneRoster export metadata","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/integrations/oneroster/outbound/status","host":["{{baseUrl}}"],"path":["integrations","oneroster","outbound","status"]},"description":"Last OneRoster export metadata"}},{"name":"POST /integrations/oneroster/outbound/sync — Push OneRoster export to configured endpoint","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/integrations/oneroster/outbound/sync","host":["{{baseUrl}}"],"path":["integrations","oneroster","outbound","sync"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Generates a fresh OneRoster export and pushes it to the configured push endpoint. Configure the endpoint URL + bearer token in district settings.oneRoster.endpointUrl / .bearerToken."}},{"name":"PATCH /integrations/oneroster/outbound/config — Save the OneRoster outbound push endpoint config","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/integrations/oneroster/outbound/config","host":["{{baseUrl}}"],"path":["integrations","oneroster","outbound","config"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Save the OneRoster outbound push endpoint config"}}]},{"name":"Integrations · Microsoft 365","item":[{"name":"GET /integrations/m365/config — Get M365 integration config for the district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/integrations/m365/config","host":["{{baseUrl}}"],"path":["integrations","m365","config"]},"description":"Get M365 integration config for the district"}},{"name":"PATCH /integrations/m365/config — Update M365 tenantId, clientId, or sync toggle","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/integrations/m365/config","host":["{{baseUrl}}"],"path":["integrations","m365","config"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Update the M365 configuration. Client secret is NOT stored here — set it as an environment variable: ${DISTRICT_ID}__M365_CLIENT_SECRET."}},{"name":"POST /integrations/m365/sync-users — Sync all active students and staff to M365","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/integrations/m365/sync-users","host":["{{baseUrl}}"],"path":["integrations","m365","sync-users"]},"description":"Provisions or updates all active STUDENT and STAFF persons in Azure AD. Respects the configured tenantId/clientId and reads M365_CLIENT_SECRET from env."}},{"name":"POST /integrations/m365/sync-teams — Sync section roster as Teams class groups","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/integrations/m365/sync-teams","host":["{{baseUrl}}"],"path":["integrations","m365","sync-teams"]},"description":"Creates or updates Microsoft Teams Education class groups for each active section. Each section becomes a Teams class with the lead teacher as owner."}},{"name":"GET /integrations/m365/sync-status — Last M365 sync results","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/integrations/m365/sync-status","host":["{{baseUrl}}"],"path":["integrations","m365","sync-status"]},"description":"Last M365 sync results"}}]},{"name":"Platform","item":[{"name":"GET /api/platform/v1/dashboard/summary — Super Admin: aggregate platform metrics","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/dashboard/summary","host":["{{baseUrl}}"],"path":["api","platform","v1","dashboard","summary"]},"description":"Super Admin: aggregate platform metrics"}},{"name":"GET /api/platform/v1/districts — Super Admin: list every district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts","host":["{{baseUrl}}"],"path":["api","platform","v1","districts"]},"description":"Super Admin: list every district"}},{"name":"POST /api/platform/v1/districts — Super Admin: provision a new district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts","host":["{{baseUrl}}"],"path":["api","platform","v1","districts"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: provision a new district"}},{"name":"GET /api/platform/v1/audit — Recent platform audit entries","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/audit","host":["{{baseUrl}}"],"path":["api","platform","v1","audit"]},"description":"Recent platform audit entries"}},{"name":"GET /api/platform/v1/feature-flags — Feature flags with per-district override counts","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/feature-flags","host":["{{baseUrl}}"],"path":["api","platform","v1","feature-flags"]},"description":"Feature flags with per-district override counts"}},{"name":"POST /api/platform/v1/feature-flags — Super Admin: create a feature flag","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/feature-flags","host":["{{baseUrl}}"],"path":["api","platform","v1","feature-flags"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: create a feature flag"}},{"name":"GET /api/platform/v1/districts/{id} — Super Admin: district detail","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}"]},"description":"Super Admin: district detail"}},{"name":"PATCH /api/platform/v1/districts/{id} — Super Admin: edit district","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: edit district"}},{"name":"POST /api/platform/v1/districts/{id}/status — Super Admin: activate / suspend / churn a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/status","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: activate / suspend / churn a district"}},{"name":"GET /api/platform/v1/districts/{id}/users — Super Admin: list users of a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/users","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","users"]},"description":"Super Admin: list users of a district"}},{"name":"POST /api/platform/v1/districts/{id}/users/{userId}/status — Super Admin: activate / suspend / disable a district user","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/users/{userId}/status","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","users","{userId}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: activate / suspend / disable a district user"}},{"name":"PATCH /api/platform/v1/districts/{id}/users/{userId}/roles — Super Admin: replace role set for a district user","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/users/{userId}/roles","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","users","{userId}","roles"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: replace role set for a district user"}},{"name":"GET /api/platform/v1/operators — Super Admin: list YRC operators","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/operators","host":["{{baseUrl}}"],"path":["api","platform","v1","operators"]},"description":"Super Admin: list YRC operators"}},{"name":"POST /api/platform/v1/operators — Super Admin: invite a new YRC operator","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/operators","host":["{{baseUrl}}"],"path":["api","platform","v1","operators"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: invite a new YRC operator"}},{"name":"PATCH /api/platform/v1/operators/{id} — Super Admin: update YRC operator","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/operators/{id}","host":["{{baseUrl}}"],"path":["api","platform","v1","operators","{id}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: update YRC operator"}},{"name":"POST /api/platform/v1/operators/{id}/status — Super Admin: activate / suspend / disable YRC operator","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/operators/{id}/status","host":["{{baseUrl}}"],"path":["api","platform","v1","operators","{id}","status"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: activate / suspend / disable YRC operator"}},{"name":"POST /api/platform/v1/operators/{id}/reset-password — Super Admin: generate a new temporary password","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/operators/{id}/reset-password","host":["{{baseUrl}}"],"path":["api","platform","v1","operators","{id}","reset-password"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: generate a new temporary password"}},{"name":"GET /api/platform/v1/districts/{id}/feature-flags — Super Admin: all flags with this district's overrides","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/feature-flags","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","feature-flags"]},"description":"Super Admin: all flags with this district's overrides"}},{"name":"PATCH /api/platform/v1/feature-flags/{key} — Super Admin: update feature flag default / description","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/feature-flags/{key}","host":["{{baseUrl}}"],"path":["api","platform","v1","feature-flags","{key}"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: update feature flag default / description"}},{"name":"POST /api/platform/v1/districts/{id}/feature-flags/{key}/override — Super Admin: set a district-level feature flag override","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/feature-flags/{key}/override","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","feature-flags","{key}","override"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: set a district-level feature flag override"}},{"name":"DELETE /api/platform/v1/districts/{id}/feature-flags/{key}/override — Super Admin: remove a district-level feature flag override","request":{"method":"DELETE","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/feature-flags/{key}/override","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","feature-flags","{key}","override"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Super Admin: remove a district-level feature flag override"}},{"name":"POST /api/platform/v1/reconciler/run — Trigger projection reconciliation (all districts or one)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/reconciler/run","host":["{{baseUrl}}"],"path":["api","platform","v1","reconciler","run"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Trigger projection reconciliation (all districts or one)"}},{"name":"GET /api/platform/v1/reconciler/status — Last reconciler run summary per district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/reconciler/status","host":["{{baseUrl}}"],"path":["api","platform","v1","reconciler","status"]},"description":"Last reconciler run summary per district"}},{"name":"GET /api/platform/v1/districts/{districtId}/api-keys — Super Admin: list API keys for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{districtId}/api-keys","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{districtId}","api-keys"]},"description":"Returns all non-revoked API keys for the district. The key hash is never returned."}},{"name":"POST /api/platform/v1/districts/{districtId}/api-keys — Super Admin: create an API key for a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{districtId}/api-keys","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{districtId}","api-keys"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Generates a cryptographically random key. The plaintext key is returned ONCE and cannot be retrieved again."}},{"name":"DELETE /api/platform/v1/districts/{districtId}/api-keys/{keyId} — Super Admin: revoke an API key","request":{"method":"DELETE","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{districtId}/api-keys/{keyId}","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{districtId}","api-keys","{keyId}"]},"description":"Soft-deletes the key by setting revokedAt to now. The key stops working immediately."}}]},{"name":"Platform · Integrations","item":[{"name":"GET /api/platform/v1/integrations/districts/{districtId}/connectors — List available connectors and their configuration status for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/connectors","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","connectors"]},"description":"List available connectors and their configuration status for a district"}},{"name":"PUT /api/platform/v1/integrations/districts/{districtId}/connectors/{id}/config — Upsert a connector configuration for a district","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/connectors/{id}/config","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","connectors","{id}","config"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Upsert a connector configuration for a district"}},{"name":"GET /api/platform/v1/integrations/districts/{districtId}/sync-runs — History of connector sync runs for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/sync-runs","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","sync-runs"]},"description":"History of connector sync runs for a district"}},{"name":"POST /api/platform/v1/integrations/districts/{districtId}/genesis/import — Import a Genesis CSV export into a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/genesis/import","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","genesis","import"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Paste CSV bodies directly. Default `dryRun: true` — run once to preview counts, then set false to apply."}},{"name":"POST /api/platform/v1/integrations/districts/{districtId}/powerschool/import — Import a PowerSchool CSV export into a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/powerschool/import","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","powerschool","import"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Import a PowerSchool CSV export into a district"}},{"name":"POST /api/platform/v1/integrations/districts/{districtId}/oneroster/import — Import a OneRoster 1.2 CSV set into a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/oneroster/import","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","oneroster","import"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Import a OneRoster 1.2 CSV set into a district"}},{"name":"POST /api/platform/v1/integrations/districts/{districtId}/lti/launch — Canvas LTI 1.3 launch endpoint (scaffold)","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/lti/launch","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","lti","launch"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Accepts the LTI 1.3 `id_token` POST from Canvas, validates the JWT against the configured platform keys, and redirects the user into Forge with a session. M11 ships the endpoint shape; full JWT validation + user provisioning lands when a district configures Canvas."}},{"name":"GET /api/platform/v1/integrations/lti/schoology/config — Schoology LTI 1.3 registration metadata","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/lti/schoology/config","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","lti","schoology","config"]},"description":"Returns the Schoology LTI 1.3 registration payload. Requires `integration.admin` permission. Use this to populate Schoology LTI tool registration manually or via the register endpoint."}},{"name":"POST /api/platform/v1/integrations/districts/{districtId}/lti/schoology/register — Register Forge as Schoology LTI 1.3 tool","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/lti/schoology/register","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","lti","schoology","register"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Calls Schoology API to register the Forge SIS LTI tool for a district."}},{"name":"GET /api/platform/v1/integrations/lti/blackboard/config — Blackboard LTI 1.3 registration metadata","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/lti/blackboard/config","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","lti","blackboard","config"]},"description":"Returns the Blackboard LTI 1.3 registration payload. Requires `integration.admin` permission. Use this to populate Blackboard LTI tool registration manually or via the register endpoint."}},{"name":"POST /api/platform/v1/integrations/districts/{districtId}/lti/blackboard/register — Register Forge as Blackboard LTI 1.3 tool","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/integrations/districts/{districtId}/lti/blackboard/register","host":["{{baseUrl}}"],"path":["api","platform","v1","integrations","districts","{districtId}","lti","blackboard","register"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Calls Blackboard API to register the Forge SIS LTI tool for a district."}}]},{"name":"Platform · Billing","item":[{"name":"GET /api/platform/v1/districts/{id}/billing — Get subscription info for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/billing","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","billing"]},"description":"Get subscription info for a district"}},{"name":"POST /api/platform/v1/districts/{id}/billing/create-customer — Create a Stripe customer for a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/billing/create-customer","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","billing","create-customer"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a Stripe customer for a district"}},{"name":"POST /api/platform/v1/districts/{id}/billing/subscribe — Create a Stripe subscription for a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/billing/subscribe","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","billing","subscribe"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Create a Stripe subscription for a district"}},{"name":"POST /api/platform/v1/districts/{id}/billing/cancel — Cancel the Stripe subscription for a district","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/billing/cancel","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","billing","cancel"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Cancel the Stripe subscription for a district"}},{"name":"GET /api/platform/v1/districts/{id}/invoices — List invoices for a district","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/invoices","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","invoices"]},"description":"List invoices for a district"}},{"name":"GET /api/platform/v1/districts/{id}/ai-usage — Per-district AI usage report for billing passthrough","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/districts/{id}/ai-usage","host":["{{baseUrl}}"],"path":["api","platform","v1","districts","{id}","ai-usage"]},"description":"Returns AI token counts and USD cost for a district in the given period. If `from` and `to` are omitted, defaults to the rolling 30-day window. The `invoiceLineItem` field is pre-formatted for inclusion on a platform invoice."}}]},{"name":"Platform — Billing","item":[{"name":"GET /api/platform/v1/billing/prospects — List Stripe checkouts pending or completed district provisioning","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/billing/prospects","host":["{{baseUrl}}"],"path":["api","platform","v1","billing","prospects"]},"description":"List Stripe checkouts pending or completed district provisioning"}},{"name":"POST /api/platform/v1/billing/prospects/{auditId}/provision — Provision a District + initial district_admin user from a prospect","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{baseUrl}}/api/platform/v1/billing/prospects/{auditId}/provision","host":["{{baseUrl}}"],"path":["api","platform","v1","billing","prospects","{auditId}","provision"]},"body":{"mode":"raw","raw":"{}","options":{"raw":{"language":"json"}}},"description":"Creates the District row using the supplied details, an initial User with the prospect email as a district_admin, and binds the existing Stripe customer/subscription. Idempotent — if the prospect was already provisioned, returns the existing districtId."}}]},{"name":"Platform — Logs","item":[{"name":"GET /api/platform/v1/logs/processes — List PM2 processes with status + uptime","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/logs/processes","host":["{{baseUrl}}"],"path":["api","platform","v1","logs","processes"]},"description":"List PM2 processes with status + uptime"}},{"name":"GET /api/platform/v1/logs/tail — Tail the last N lines of a process log","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/logs/tail","host":["{{baseUrl}}"],"path":["api","platform","v1","logs","tail"]},"description":"Tail the last N lines of a process log"}}]},{"name":"Platform — Queues","item":[{"name":"GET /api/platform/v1/queues — List BullMQ queue depths","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/queues","host":["{{baseUrl}}"],"path":["api","platform","v1","queues"]},"description":"List BullMQ queue depths"}},{"name":"GET /api/platform/v1/queues/{name}/failed — List recent failed jobs in a queue","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/api/platform/v1/queues/{name}/failed","host":["{{baseUrl}}"],"path":["api","platform","v1","queues","{name}","failed"]},"description":"List recent failed jobs in a queue"}}]}]}