{"openapi":"3.1.0","info":{"title":"District Resolve API","version":"0.20.0","description":"API-first endpoints for District Resolve, a secure multi-tenant school district operations and ticketing platform. Tenant-specific resources require organizationId isolation on the server."},"servers":[{"url":"/api"},{"url":"/api/v1","description":"Versioned compatibility entrypoint. Requests redirect to canonical /api routes."}],"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"},"sessionCookie":{"type":"apiKey","in":"cookie","name":"next-auth.session-token"}},"parameters":{"organizationId":{"name":"organizationId","in":"query","required":false,"schema":{"type":"string"},"description":"Optional organization context. Non-super-admin users may only request their own organization."}},"schemas":{"ApiTokenCreate":{"type":"object","required":["name","scopes"],"properties":{"organizationId":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":["string","null"],"format":"date-time"}}},"WebhookCreate":{"type":"object","required":["name","url","events"],"properties":{"organizationId":{"type":"string"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}}},"UploadIntent":{"type":"object","required":["fileName","mimeType","sizeBytes","purpose"],"properties":{"organizationId":{"type":"string"},"fileName":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"integer"},"purpose":{"enum":["TICKET_ATTACHMENT","ASSET_ATTACHMENT","IMPORT_FILE","CHROME_SCREENSHOT"]},"ticketId":{"type":["string","null"]},"assetId":{"type":["string","null"]}}},"SecurityComplianceSettings":{"type":"object","properties":{"organizationId":{"type":"string"},"auditRetentionDays":{"type":"integer","minimum":90,"maximum":3650},"dataRetentionYears":{"type":"integer","minimum":1,"maximum":20},"auditExportRequiresReportsExport":{"type":"boolean"},"requireMfaForAdmins":{"type":"boolean"},"requireMfaForSuperAdmins":{"type":"boolean"},"sessionTimeoutMinutes":{"type":"integer","minimum":30,"maximum":43200},"maxFailedLoginAttempts":{"type":"integer","minimum":3,"maximum":20},"lockoutMinutes":{"type":"integer","minimum":5,"maximum":1440},"ipAllowlist":{"type":"array","items":{"type":"string"}},"ferpaMode":{"type":"boolean"},"studentDataAccessLogging":{"type":"boolean"},"suspiciousLoginAlerts":{"type":"boolean"},"uploadVirusScanMode":{"enum":["metadata_only","clamav_ready","external_provider"]},"dataExportReviewRequired":{"type":"boolean"}}},"MobilePushToken":{"type":"object","required":["token","platform"],"properties":{"organizationId":{"type":"string"},"token":{"type":"string"},"platform":{"enum":["web","ios","android"]},"deviceId":{"type":["string","null"]},"deviceName":{"type":["string","null"]},"appVersion":{"type":["string","null"]}}},"MobileDeepLink":{"type":"object","required":["target"],"properties":{"organizationId":{"type":"string"},"target":{"enum":["dashboard","ticket","asset","room","submit-ticket"]},"entityId":{"type":["string","null"]},"mode":{"enum":["view","edit","create"]},"includeWebUrl":{"type":"boolean"}}},"AiSettingsUpdate":{"type":"object","required":["provider","features"],"properties":{"organizationId":{"type":"string"},"provider":{"enum":["none","platform","openai","anthropic"]},"apiKey":{"type":["string","null"],"description":"Accepted once and stored as a fingerprint, never returned."},"features":{"type":"object","properties":{"smartTriage":{"type":"boolean"},"smartRouting":{"type":"boolean"},"summaries":{"type":"boolean"},"suggestedReplies":{"type":"boolean"},"kbSuggestions":{"type":"boolean"},"duplicateDetection":{"type":"boolean"},"trendDetection":{"type":"boolean"},"dailyBriefing":{"type":"boolean"},"autoTag":{"type":"boolean"},"sentiment":{"type":"boolean"},"resolutionRecommendation":{"type":"boolean"},"requireHumanApproval":{"type":"boolean"}}}}},"AiTriagePreview":{"type":"object","required":["title","description"],"properties":{"organizationId":{"type":"string"},"departmentId":{"type":["string","null"]},"categoryId":{"type":["string","null"]},"siteId":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":"string"}}},"WebhookRetry":{"type":"object","properties":{"organizationId":{"type":"string"},"deliveryId":{"type":["string","null"]}}},"ChromeExtensionTicket":{"type":"object","required":["title","description"],"properties":{"organizationId":{"type":"string"},"departmentId":{"type":["string","null"]},"siteId":{"type":["string","null"]},"buildingId":{"type":["string","null"]},"locationId":{"type":["string","null"]},"categoryId":{"type":["string","null"]},"priorityId":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":"string"},"assetTag":{"type":["string","null"]},"serialNumber":{"type":["string","null"]},"screenshotStorageKey":{"type":["string","null"]},"browserUrl":{"type":["string","null"]},"extensionVersion":{"type":["string","null"]},"diagnostics":{"type":"object"}}},"InventoryPartCreate":{"type":"object","required":["name"],"properties":{"organizationId":{"type":"string"},"departmentId":{"type":["string","null"]},"vendorId":{"type":["string","null"]},"name":{"type":"string"},"partNumber":{"type":["string","null"]},"manufacturer":{"type":["string","null"]},"category":{"type":["string","null"]},"unitCost":{"type":"number"},"currentStock":{"type":"integer"},"reorderPoint":{"type":"integer"},"reorderQuantity":{"type":"integer"},"locationName":{"type":["string","null"]},"locationQuantity":{"type":"integer"},"status":{"enum":["active","low_stock","backordered","discontinued"]}}},"VendorCreate":{"type":"object","required":["name"],"properties":{"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"contactName":{"type":["string","null"]},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"website":{"type":["string","null"],"format":"uri"},"w9OnFile":{"type":"boolean"},"insuranceOnFile":{"type":"boolean"},"performanceRating":{"type":["integer","null"]},"status":{"enum":["active","preferred","review","inactive"]}}},"PurchaseOrderCreate":{"type":"object","required":["poNumber","lineItems"],"properties":{"organizationId":{"type":"string"},"vendorId":{"type":["string","null"]},"departmentId":{"type":["string","null"]},"ticketId":{"type":["string","null"]},"poNumber":{"type":"string"},"status":{"enum":["draft","pending_approval","approved","sent","partial","received","cancelled"]},"totalAmount":{"type":["number","null"]},"fundingSource":{"type":["string","null"]},"description":{"type":["string","null"]},"lineItems":{"type":"array","items":{"type":"object","required":["description","quantity","unitCost"],"properties":{"description":{"type":"string"},"partNumber":{"type":["string","null"]},"quantity":{"type":"integer"},"unitCost":{"type":"number"}}}}}},"KnowledgeBaseArticleCreate":{"type":"object","required":["categoryId","title","body"],"properties":{"organizationId":{"type":"string"},"categoryId":{"type":"string"},"title":{"type":"string"},"slug":{"type":["string","null"]},"body":{"type":"string"},"excerpt":{"type":["string","null"]},"status":{"enum":["draft","published","archived"]},"visibility":{"enum":["public","staff_only","technicians_only","admins_only"]},"audience":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}}}},"KnowledgeBaseFeedbackCreate":{"type":"object","required":["helpful"],"properties":{"helpful":{"type":"boolean"},"comment":{"type":["string","null"]}}},"MajorIncidentCreate":{"type":"object","required":["title"],"properties":{"organizationId":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"enum":["investigating","identified","monitoring","resolved"]},"severity":{"enum":["low","medium","high","critical"]},"affectedSites":{"type":"array","items":{"type":"string"}},"affectedDepartments":{"type":"array","items":{"type":"string"}},"publicStatusPageVisible":{"type":"boolean"},"linkedTicketIds":{"type":"array","items":{"type":"string"}}}},"MajorIncidentUpdateCreate":{"type":"object","required":["body"],"properties":{"body":{"type":"string"},"statusChange":{"enum":["investigating","identified","monitoring","resolved",null]},"publicStatusPageVisible":{"type":"boolean"}}}}},"paths":{"/auth/login":{"post":{"summary":"Email/password login for API clients."}},"/auth/google":{"post":{"summary":"Resolve Google OAuth domain matching."}},"/platform/overview":{"get":{"summary":"Return platform-wide super admin metrics, organizations, support tickets, audit events, and integration health."}},"/platform/support-tickets":{"get":{"summary":"List District Resolve platform support tickets for website super administrators."},"post":{"summary":"Create a platform support ticket for a tenant or the District Resolve platform."}},"/platform/announcements":{"get":{"summary":"List platform-wide announcements for super administrators."},"post":{"summary":"Publish or schedule a platform-wide announcement."}},"/platform/reports/export":{"post":{"summary":"Create a platform-level report export for usage, support, security, tenant health, or growth."}},"/platform/settings":{"get":{"summary":"Read global District Resolve platform settings."},"post":{"summary":"Update global platform settings and write an audit event."}},"/platform/health":{"get":{"summary":"Return platform health checks for API, database, email, Redis, and storage readiness."}},"/organizations":{"get":{"summary":"List organizations for platform administrators."},"post":{"summary":"Create an organization."}},"/organizations/{id}":{"get":{"summary":"View one organization with domains and settings."},"patch":{"summary":"Update organization profile, branding, or lifecycle status."},"delete":{"summary":"Archive an organization."}},"/organizations/{id}/impersonate":{"post":{"summary":"Prepare an audited super-admin support impersonation handoff for an organization."}},"/users":{"get":{"summary":"List users in the current organization."},"post":{"summary":"Create or invite a user."}},"/departments":{"get":{"summary":"List departments in the current organization."},"post":{"summary":"Create a department."}},"/tickets":{"get":{"summary":"List tenant-scoped tickets."},"post":{"summary":"Create a tenant-scoped ticket."}},"/tickets/{id}":{"get":{"summary":"View one tenant-scoped ticket."},"patch":{"summary":"Update tenant-scoped ticket fields."}},"/tickets/{id}/comments":{"post":{"summary":"Add a public ticket comment."}},"/tickets/{id}/internal-notes":{"post":{"summary":"Add a staff-only internal note."}},"/tickets/{id}/attachments":{"post":{"summary":"Attach a private file to a ticket."}},"/tickets/{id}/assign":{"patch":{"summary":"Assign or reassign a ticket."}},"/tickets/{id}/status":{"patch":{"summary":"Update ticket workflow status."}},"/tickets/{id}/close":{"patch":{"summary":"Resolve or close a ticket."}},"/tickets/{id}/reopen":{"patch":{"summary":"Reopen a closed ticket."}},"/routing-rules":{"get":{"summary":"List tenant-scoped routing and assignment automation rules."},"post":{"summary":"Create a routing automation rule."}},"/routing-rules/{id}":{"patch":{"summary":"Update a routing automation rule."},"delete":{"summary":"Delete a routing automation rule."}},"/routing-rules/test":{"post":{"summary":"Dry-run active routing rules against a sample ticket."}},"/sla-rules":{"get":{"summary":"List tenant-scoped SLA policies."},"post":{"summary":"Create an SLA policy."}},"/automation/sla-scan":{"post":{"summary":"Run the SLA due-soon and overdue escalation scan for the current organization."}},"/reports/tickets":{"get":{"summary":"Generate ticket analytics data."}},"/reports/departments":{"get":{"summary":"Generate department analytics data."}},"/reports/users":{"get":{"summary":"Generate user activity and workload reporting data."}},"/reports/sla":{"get":{"summary":"Generate SLA compliance reporting data."}},"/reports/library":{"get":{"summary":"List the full District Resolve report catalog and custom builder fields."}},"/reports/custom":{"post":{"summary":"Generate a tenant-scoped custom report preview from selected fields and grouping."}},"/reports/schedules":{"get":{"summary":"List scheduled report deliveries for the current organization and user scope."},"post":{"summary":"Create a scheduled report delivery using the selected filters and export format."}},"/reports/export":{"get":{"summary":"Export report data as CSV, Excel, or PDF."}},"/assets":{"get":{"summary":"List assets."},"post":{"summary":"Create an asset."}},"/assets/{id}":{"get":{"summary":"View one tenant-scoped asset."},"patch":{"summary":"Update one tenant-scoped asset."}},"/assets/{id}/tickets":{"get":{"summary":"List tickets related to an asset."}},"/inventory/parts":{"get":{"summary":"List tenant-scoped parts inventory records with department isolation."},"post":{"summary":"Create a tenant-scoped part inventory record.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryPartCreate"}}}}}},"/vendors":{"get":{"summary":"List tenant-scoped vendors connected to visible departments, assets, parts, or purchase orders."},"post":{"summary":"Create a tenant-scoped vendor record.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorCreate"}}}}}},"/purchase-orders":{"get":{"summary":"List tenant-scoped purchase orders with department isolation."},"post":{"summary":"Create a tenant-scoped purchase order and audit the financial operation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseOrderCreate"}}}}}},"/imports":{"get":{"summary":"List tenant-scoped CSV and Active Directory import jobs."}},"/imports/preview":{"post":{"summary":"Upload, map, validate, and preview asset, room, part, or vendor CSV rows before confirmation."}},"/imports/users":{"post":{"summary":"Upload, map, validate, and preview user CSV import rows."}},"/imports/{id}":{"get":{"summary":"View an import preview, rows, mapping, errors, and summary."}},"/imports/{id}/confirm":{"post":{"summary":"Confirm a previewed import and apply reviewed user, asset, room, part, or vendor changes."}},"/imports/{id}/errors":{"get":{"summary":"Download import validation issues as CSV."}},"/exports":{"get":{"summary":"List tenant-scoped export jobs with filters, format, requester, expiration, and status."},"post":{"summary":"Create an audited CSV, Excel, or PDF export job for a supported District Resolve dataset."}},"/announcements":{"get":{"summary":"List announcements."},"post":{"summary":"Create an announcement."}},"/announcements/{id}":{"patch":{"summary":"Update an announcement."},"delete":{"summary":"Deactivate an announcement."}},"/knowledge-base":{"get":{"summary":"List tenant-scoped knowledge base categories and visible articles."},"post":{"summary":"Create a tenant-scoped knowledge base article and initial version.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeBaseArticleCreate"}}}}}},"/knowledge-base/{id}/feedback":{"post":{"summary":"Submit helpful/not-helpful feedback for a tenant-scoped knowledge base article.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeBaseFeedbackCreate"}}}}}},"/incidents":{"get":{"summary":"List tenant-scoped major incidents visible to the current user."},"post":{"summary":"Declare a major incident, optionally link tickets, and optionally publish it to the status page.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajorIncidentCreate"}}}}}},"/incidents/{id}/updates":{"post":{"summary":"Post a major incident update and optional status/public visibility change.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MajorIncidentUpdateCreate"}}}}}},"/audit-logs":{"get":{"summary":"List tenant-scoped audit events or export authorized audit rows as CSV.","parameters":[{"$ref":"#/components/parameters/organizationId"},{"name":"q","in":"query","required":false,"schema":{"type":"string"}},{"name":"severity","in":"query","required":false,"schema":{"enum":["Info","Warning","Critical"]}},{"name":"category","in":"query","required":false,"schema":{"type":"string"}},{"name":"entityType","in":"query","required":false,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"enum":["csv"]}}]}},"/security/settings":{"get":{"summary":"Read tenant-scoped security posture, upload policy, security headers, recent security events, and compliance settings.","parameters":[{"$ref":"#/components/parameters/organizationId"}]},"patch":{"summary":"Update organization security and compliance policy settings and write an audit event.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityComplianceSettings"}}}}}},"/security/checklist/run":{"post":{"summary":"Run a security checklist against the current tenant and return control evidence, headers, and upload policy status.","parameters":[{"$ref":"#/components/parameters/organizationId"}]}},"/saved-views":{"get":{"summary":"List saved table or report views for the current organization and user."},"post":{"summary":"Create a saved view with filters, sorting, and column preferences."}},"/saved-views/{id}":{"patch":{"summary":"Update a saved view."},"delete":{"summary":"Delete a saved view."}},"/table-preferences/{tableType}":{"get":{"summary":"Get user-specific column preferences for a table type."}},"/table-preferences":{"post":{"summary":"Create or update table preferences."}},"/table-preferences/{id}":{"patch":{"summary":"Update a table preference record."}},"/table-preferences/{id}/columns":{"post":{"summary":"Create or update table column preferences."}},"/table-preferences/{id}/columns/reorder":{"patch":{"summary":"Persist table column order."}},"/api-tokens":{"get":{"summary":"List organization API tokens without exposing token hashes.","parameters":[{"$ref":"#/components/parameters/organizationId"}]},"post":{"summary":"Create a scoped bearer token for future clients and return the raw token once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiTokenCreate"}}}}}},"/api-tokens/{id}/revoke":{"patch":{"summary":"Revoke an organization API token."}},"/webhooks":{"get":{"summary":"List tenant-scoped webhook endpoints."},"post":{"summary":"Create a signed webhook endpoint and return the signing secret once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}}}}},"/webhooks/{id}":{"patch":{"summary":"Update a webhook endpoint."},"delete":{"summary":"Disable a webhook endpoint."}},"/webhooks/{id}/test":{"post":{"summary":"Prepare a signed sample webhook payload for verification."}},"/webhooks/{id}/deliveries":{"get":{"summary":"List signed webhook delivery attempts, statuses, payloads, and retry counts."}},"/webhooks/{id}/retry":{"post":{"summary":"Queue a retry for the latest or selected webhook delivery.","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRetry"}}}}}},"/mobile/bootstrap":{"get":{"summary":"Return tenant bootstrap data for future mobile clients, including departments, sites, priorities, quick templates, and upload policy."}},"/mobile/push-tokens":{"get":{"summary":"List the current user's registered mobile or web push devices without exposing raw tokens."},"post":{"summary":"Register or refresh a mobile push token for future notification delivery.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MobilePushToken"}}}}}},"/mobile/deep-link":{"post":{"summary":"Create a stable District Resolve mobile and web deep link for a ticket, asset, room, dashboard, or ticket submission.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MobileDeepLink"}}}}}},"/ai/settings":{"get":{"summary":"Read opt-in AI provider and feature readiness settings without returning provider secrets."},"post":{"summary":"Update AI provider, feature toggles, and provider key fingerprint for an organization.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSettingsUpdate"}}}}}},"/ai/triage-preview":{"post":{"summary":"Dry-run smart triage suggestions for a ticket title and description before applying any automation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiTriagePreview"}}}}}},"/chrome-extension/tickets":{"post":{"summary":"Create a Technology ticket from a future Chrome extension with device/browser diagnostics.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChromeExtensionTicket"}}}}}},"/uploads/presign":{"post":{"summary":"Create a tenant-scoped private upload intent for local development or S3-compatible production storage.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadIntent"}}}}}},"/uploads/local":{"put":{"summary":"Local development upload target for private tenant-scoped files."}},"/v1/{path}":{"get":{"summary":"Versioned compatibility route that 307-redirects to the canonical /api route."},"post":{"summary":"Versioned compatibility route that 307-redirects to the canonical /api route."},"patch":{"summary":"Versioned compatibility route that 307-redirects to the canonical /api route."},"delete":{"summary":"Versioned compatibility route that 307-redirects to the canonical /api route."}}}}