Files
backend/docs/openapi/visione.openapi.yaml
T

4175 lines
101 KiB
YAML

{
"components": {
"responses": {
"BadRequest": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Invalid request or business validation failure."
},
"Forbidden": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Authenticated user cannot perform this action."
},
"NotFound": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Requested resource was not found."
},
"Unauthorized": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
},
"description": "Missing or invalid bearer token."
}
},
"schemas": {
"AdminUser": {
"additionalProperties": true,
"properties": {
"banned": {
"type": "boolean"
},
"email": {
"format": "email",
"type": "string"
},
"first_name": {
"type": "string"
},
"fiscal_code": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"last_name": {
"type": "string"
},
"phone": {
"type": "string"
},
"points": {
"type": "integer"
},
"roles": {
"description": "Comma-separated role names from SQL GROUP_CONCAT.",
"type": "string"
}
},
"type": "object"
},
"Area": {
"additionalProperties": true,
"properties": {
"boundary_geojson": {
"$ref": "#/components/schemas/GeoJsonObject"
},
"description": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
}
},
"type": "object"
},
"AreaListResponse": {
"additionalProperties": false,
"properties": {
"areas": {
"items": {
"$ref": "#/components/schemas/Area"
},
"type": "array"
},
"ok": {
"type": "boolean"
}
},
"required": [
"ok",
"areas"
],
"type": "object"
},
"AssignTeamRequest": {
"additionalProperties": false,
"properties": {
"team_id": {
"format": "int64",
"type": "integer"
}
},
"required": [
"team_id"
],
"type": "object"
},
"AssignmentLinkResponse": {
"additionalProperties": false,
"properties": {
"expires_at": {
"type": "string"
},
"ok": {
"type": "boolean"
},
"url": {
"type": "string"
}
},
"required": [
"ok",
"url",
"expires_at"
],
"type": "object"
},
"Category": {
"additionalProperties": true,
"properties": {
"active": {
"type": "boolean"
},
"description": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
}
},
"type": "object"
},
"CategoryListResponse": {
"additionalProperties": false,
"properties": {
"categories": {
"items": {
"$ref": "#/components/schemas/Category"
},
"type": "array"
},
"ok": {
"type": "boolean"
}
},
"required": [
"ok",
"categories"
],
"type": "object"
},
"CreateAreaRequest": {
"additionalProperties": false,
"properties": {
"boundary_geojson": {
"$ref": "#/components/schemas/GeoJsonObject"
},
"description": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"name",
"boundary_geojson"
],
"type": "object"
},
"CreateCategoryRequest": {
"additionalProperties": false,
"properties": {
"description": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"CreateReportRequest": {
"additionalProperties": false,
"properties": {
"address": {
"type": "string"
},
"category_id": {
"format": "int64",
"type": "integer"
},
"description": {
"type": "string"
},
"latitude": {
"format": "double",
"type": "number"
},
"longitude": {
"format": "double",
"type": "number"
},
"media": {
"items": {
"format": "uri-reference",
"type": "string"
},
"type": "array"
}
},
"required": [
"category_id",
"latitude",
"longitude",
"address",
"description"
],
"type": "object"
},
"CreateReportResponse": {
"additionalProperties": false,
"properties": {
"area_id": {
"format": "int64",
"type": "integer"
},
"ok": {
"type": "boolean"
},
"report_id": {
"format": "int64",
"type": "integer"
}
},
"required": [
"ok",
"report_id"
],
"type": "object"
},
"CreateTeamRequest": {
"additionalProperties": false,
"properties": {
"area_id": {
"format": "int64",
"type": "integer"
},
"description": {
"type": "string"
},
"name": {
"type": "string"
},
"team_category_id": {
"format": "int64",
"type": "integer"
}
},
"required": [
"team_category_id",
"name"
],
"type": "object"
},
"CurrentUser": {
"additionalProperties": false,
"properties": {
"email": {
"format": "email",
"type": "string"
},
"first_name": {
"type": "string"
},
"fiscal_code": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"last_name": {
"type": "string"
},
"permissions": {
"items": {
"type": "string"
},
"type": "array"
},
"phone": {
"type": "string"
},
"points": {
"type": "integer"
},
"role": {
"type": "string"
},
"roles": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"id",
"first_name",
"last_name",
"email",
"fiscal_code",
"points",
"role",
"roles",
"permissions"
],
"type": "object"
},
"CurrentUserResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"user": {
"$ref": "#/components/schemas/CurrentUser"
}
},
"required": [
"ok",
"user"
],
"type": "object"
},
"EditUserRequest": {
"additionalProperties": false,
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"phone": {
"type": "string"
}
},
"type": "object"
},
"EmailRequest": {
"additionalProperties": false,
"properties": {
"email": {
"format": "email",
"type": "string"
}
},
"required": [
"email"
],
"type": "object"
},
"ErrorResponse": {
"additionalProperties": false,
"properties": {
"error": {
"type": "string"
},
"fields": {
"items": {
"type": "string"
},
"type": "array"
},
"message": {
"type": "string"
}
},
"required": [
"error"
],
"type": "object"
},
"FeedbackRequest": {
"additionalProperties": false,
"properties": {
"comment": {
"type": "string"
},
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer"
}
},
"required": [
"rating"
],
"type": "object"
},
"FlagRequest": {
"additionalProperties": false,
"properties": {
"details": {
"type": "string"
},
"reason": {
"maxLength": 120,
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
"FlagResponse": {
"additionalProperties": false,
"properties": {
"flag_id": {
"format": "int64",
"type": "integer"
},
"ok": {
"type": "boolean"
}
},
"required": [
"ok",
"flag_id"
],
"type": "object"
},
"GeoJsonObject": {
"additionalProperties": true,
"description": "GeoJSON polygon or multipolygon boundary.",
"type": "object"
},
"HealthResponse": {
"additionalProperties": false,
"properties": {
"service": {
"example": "visione-backend",
"type": "string"
},
"status": {
"example": "ok",
"type": "string"
}
},
"required": [
"status",
"service"
],
"type": "object"
},
"InterventionSummaryResponse": {
"additionalProperties": false,
"properties": {
"latest_messages": {
"items": {
"$ref": "#/components/schemas/Message"
},
"type": "array"
},
"media": {
"items": {
"$ref": "#/components/schemas/Media"
},
"type": "array"
},
"ok": {
"type": "boolean"
},
"summary": {
"$ref": "#/components/schemas/Report"
}
},
"required": [
"ok",
"summary",
"media",
"latest_messages"
],
"type": "object"
},
"Media": {
"additionalProperties": true,
"properties": {
"content_type": {
"type": "string"
},
"created_at": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"media_kind": {
"enum": [
"IMAGE",
"VIDEO"
],
"type": "string"
},
"original_filename": {
"type": "string"
},
"report_id": {
"format": "int64",
"type": "integer"
},
"size_bytes": {
"format": "int64",
"type": "integer"
},
"url": {
"type": "string"
}
},
"type": "object"
},
"MediaUploadRequest": {
"additionalProperties": false,
"properties": {
"files": {
"items": {
"format": "binary",
"type": "string"
},
"maxItems": 5,
"type": "array"
}
},
"required": [
"files"
],
"type": "object"
},
"MediaUploadResponse": {
"additionalProperties": false,
"properties": {
"media": {
"items": {
"$ref": "#/components/schemas/Media"
},
"type": "array"
},
"ok": {
"type": "boolean"
}
},
"required": [
"ok",
"media"
],
"type": "object"
},
"Message": {
"additionalProperties": true,
"properties": {
"body": {
"type": "string"
},
"created_at": {
"type": "string"
},
"first_name": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"last_name": {
"type": "string"
},
"report_id": {
"format": "int64",
"type": "integer"
},
"user_id": {
"format": "int64",
"type": "integer"
}
},
"type": "object"
},
"MessageListResponse": {
"additionalProperties": false,
"properties": {
"messages": {
"items": {
"$ref": "#/components/schemas/Message"
},
"type": "array"
},
"ok": {
"type": "boolean"
}
},
"required": [
"ok",
"messages"
],
"type": "object"
},
"MessageRequest": {
"additionalProperties": false,
"properties": {
"body": {
"type": "string"
}
},
"required": [
"body"
],
"type": "object"
},
"ModerationFlag": {
"additionalProperties": true,
"properties": {
"content_type": {
"enum": [
"REPORT",
"MESSAGE"
],
"type": "string"
},
"created_at": {
"type": "string"
},
"created_by_email": {
"type": "string"
},
"created_by_user_id": {
"format": "int64",
"type": "integer"
},
"details": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"message_id": {
"format": "int64",
"nullable": true,
"type": "integer"
},
"reason": {
"type": "string"
},
"report_id": {
"format": "int64",
"type": "integer"
},
"resolution_note": {
"nullable": true,
"type": "string"
},
"resolved_at": {
"nullable": true,
"type": "string"
},
"resolved_by_email": {
"nullable": true,
"type": "string"
},
"resolved_by_user_id": {
"format": "int64",
"nullable": true,
"type": "integer"
},
"status": {
"enum": [
"OPEN",
"RESOLVED",
"DISMISSED"
],
"type": "string"
}
},
"type": "object"
},
"ModerationListResponse": {
"additionalProperties": false,
"properties": {
"flags": {
"items": {
"$ref": "#/components/schemas/ModerationFlag"
},
"type": "array"
},
"ok": {
"type": "boolean"
},
"page": {
"type": "integer"
},
"per_page": {
"type": "integer"
}
},
"required": [
"ok",
"page",
"per_page",
"flags"
],
"type": "object"
},
"Notification": {
"additionalProperties": true,
"properties": {
"body": {
"type": "string"
},
"created_at": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"read_at": {
"nullable": true,
"type": "string"
},
"report_id": {
"format": "int64",
"nullable": true,
"type": "integer"
},
"title": {
"type": "string"
},
"type": {
"type": "string"
}
},
"type": "object"
},
"NotificationListResponse": {
"additionalProperties": false,
"properties": {
"notifications": {
"items": {
"$ref": "#/components/schemas/Notification"
},
"type": "array"
},
"ok": {
"type": "boolean"
},
"page": {
"type": "integer"
},
"per_page": {
"type": "integer"
}
},
"required": [
"ok",
"page",
"per_page",
"notifications"
],
"type": "object"
},
"OkResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
}
},
"required": [
"ok"
],
"type": "object"
},
"OpenApiDocument": {
"additionalProperties": true,
"description": "Generated OpenAPI 3 document.",
"type": "object"
},
"OpenDataReport": {
"additionalProperties": true,
"properties": {
"area_id": {
"format": "int64",
"nullable": true,
"type": "integer"
},
"area_name": {
"nullable": true,
"type": "string"
},
"category_id": {
"format": "int64",
"type": "integer"
},
"category_name": {
"type": "string"
},
"created_at": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"latitude": {
"type": "number"
},
"longitude": {
"type": "number"
},
"status": {
"$ref": "#/components/schemas/ReportStatus"
},
"updated_at": {
"type": "string"
}
},
"type": "object"
},
"OpenDataReportListResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"page": {
"type": "integer"
},
"per_page": {
"type": "integer"
},
"reports": {
"items": {
"$ref": "#/components/schemas/OpenDataReport"
},
"type": "array"
}
},
"required": [
"ok",
"page",
"per_page",
"reports"
],
"type": "object"
},
"OtpRequestResponse": {
"additionalProperties": false,
"properties": {
"delivery": {
"example": "mailpit",
"type": "string"
},
"expires_in_minutes": {
"type": "integer"
},
"ok": {
"type": "boolean"
}
},
"required": [
"ok",
"delivery",
"expires_in_minutes"
],
"type": "object"
},
"OverviewStatsResponse": {
"additionalProperties": false,
"properties": {
"avg_resolution_hours": {
"items": {
"additionalProperties": true,
"properties": {
"value": {
"type": "number"
}
},
"type": "object"
},
"type": "array"
},
"avg_resolution_hours_by_area": {
"items": {
"additionalProperties": true,
"properties": {
"area": {
"type": "string"
},
"value": {
"type": "number"
}
},
"type": "object"
},
"type": "array"
},
"avg_resolution_hours_by_category": {
"items": {
"additionalProperties": true,
"properties": {
"category": {
"type": "string"
},
"value": {
"type": "number"
}
},
"type": "object"
},
"type": "array"
},
"monthly_reports": {
"items": {
"additionalProperties": true,
"properties": {
"month": {
"type": "string"
},
"total": {
"type": "integer"
}
},
"type": "object"
},
"type": "array"
},
"ok": {
"type": "boolean"
},
"reports_by_area": {
"items": {
"additionalProperties": true,
"properties": {
"area": {
"type": "string"
},
"total": {
"type": "integer"
}
},
"type": "object"
},
"type": "array"
},
"reports_by_category": {
"items": {
"additionalProperties": true,
"properties": {
"category": {
"type": "string"
},
"total": {
"type": "integer"
}
},
"type": "object"
},
"type": "array"
},
"reports_by_status": {
"items": {
"additionalProperties": true,
"properties": {
"status": {
"$ref": "#/components/schemas/ReportStatus"
},
"total": {
"type": "integer"
}
},
"type": "object"
},
"type": "array"
},
"assignments_by_team": {
"items": {
"additionalProperties": true,
"properties": {
"team": {
"type": "string"
},
"total": {
"type": "integer"
}
},
"type": "object"
},
"type": "array"
},
"resolved_reports_by_team": {
"items": {
"additionalProperties": true,
"properties": {
"team": {
"type": "string"
},
"total": {
"type": "integer"
}
},
"type": "object"
},
"type": "array"
}
},
"required": [
"ok",
"reports_by_status",
"reports_by_area",
"avg_resolution_hours",
"reports_by_category",
"assignments_by_team",
"resolved_reports_by_team",
"monthly_reports",
"avg_resolution_hours_by_category",
"avg_resolution_hours_by_area"
],
"type": "object"
},
"PagedReportListResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"page": {
"type": "integer"
},
"per_page": {
"type": "integer"
},
"reports": {
"items": {
"$ref": "#/components/schemas/Report"
},
"type": "array"
}
},
"required": [
"ok",
"page",
"per_page",
"reports"
],
"type": "object"
},
"ReadyResponse": {
"additionalProperties": false,
"properties": {
"dependencies": {
"additionalProperties": false,
"properties": {
"mysql": {
"type": "boolean"
}
},
"required": [
"mysql"
],
"type": "object"
},
"errors": {
"additionalProperties": false,
"properties": {
"mysql": {
"type": "string"
}
},
"type": "object"
},
"status": {
"enum": [
"ready",
"not_ready"
],
"type": "string"
}
},
"required": [
"status",
"dependencies"
],
"type": "object"
},
"RegisterCitizenRequest": {
"additionalProperties": false,
"properties": {
"birth_date": {
"format": "date",
"type": "string"
},
"birth_place": {
"type": "string"
},
"email": {
"format": "email",
"type": "string"
},
"first_name": {
"type": "string"
},
"fiscal_code": {
"maxLength": 16,
"minLength": 16,
"type": "string"
},
"last_name": {
"type": "string"
},
"phone": {
"type": "string"
}
},
"required": [
"first_name",
"last_name",
"email",
"fiscal_code"
],
"type": "object"
},
"RegisterCitizenResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"user_id": {
"format": "int64",
"type": "integer"
}
},
"required": [
"ok",
"user_id"
],
"type": "object"
},
"Report": {
"additionalProperties": true,
"properties": {
"address": {
"type": "string"
},
"area_id": {
"format": "int64",
"type": "integer"
},
"area_name": {
"type": "string"
},
"assigned_operator_id": {
"format": "int64",
"type": "integer"
},
"category_id": {
"format": "int64",
"type": "integer"
},
"category_name": {
"type": "string"
},
"created_at": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"latitude": {
"type": "number"
},
"longitude": {
"type": "number"
},
"status": {
"$ref": "#/components/schemas/ReportStatus"
},
"updated_at": {
"type": "string"
},
"user_id": {
"format": "int64",
"type": "integer"
}
},
"required": [
"id",
"category_id",
"latitude",
"longitude",
"address",
"description",
"status"
],
"type": "object"
},
"ReportDetailResponse": {
"additionalProperties": false,
"properties": {
"history": {
"items": {
"$ref": "#/components/schemas/StatusHistoryItem"
},
"type": "array"
},
"media": {
"items": {
"$ref": "#/components/schemas/Media"
},
"type": "array"
},
"ok": {
"type": "boolean"
},
"report": {
"$ref": "#/components/schemas/Report"
}
},
"required": [
"ok",
"report",
"history",
"media"
],
"type": "object"
},
"ReportListResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"reports": {
"items": {
"$ref": "#/components/schemas/Report"
},
"type": "array"
}
},
"required": [
"ok",
"reports"
],
"type": "object"
},
"ReportStatus": {
"enum": [
"OPEN",
"UNDER_REVIEW",
"ASSIGNED",
"IN_PROGRESS",
"RESOLVED",
"REJECTED",
"CLOSED"
],
"type": "string"
},
"RewardEvent": {
"additionalProperties": true,
"properties": {
"created_at": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"points": {
"type": "integer"
},
"reason": {
"type": "string"
},
"report_id": {
"format": "int64",
"type": "integer"
}
},
"type": "object"
},
"RewardsResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"page": {
"type": "integer"
},
"per_page": {
"type": "integer"
},
"points": {
"type": "integer"
},
"reward_events": {
"items": {
"$ref": "#/components/schemas/RewardEvent"
},
"type": "array"
}
},
"required": [
"ok",
"points",
"page",
"per_page",
"reward_events"
],
"type": "object"
},
"StatusHistoryItem": {
"additionalProperties": true,
"properties": {
"changed_by_user_id": {
"format": "int64",
"type": "integer"
},
"created_at": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"new_status": {
"$ref": "#/components/schemas/ReportStatus"
},
"note": {
"type": "string"
},
"old_status": {
"$ref": "#/components/schemas/ReportStatus"
},
"report_id": {
"format": "int64",
"type": "integer"
}
},
"type": "object"
},
"Team": {
"additionalProperties": true,
"properties": {
"active": {
"type": "boolean"
},
"area_id": {
"format": "int64",
"type": "integer"
},
"area_name": {
"type": "string"
},
"category_name": {
"type": "string"
},
"description": {
"type": "string"
},
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
},
"team_category_id": {
"format": "int64",
"type": "integer"
}
},
"type": "object"
},
"TeamListResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"teams": {
"items": {
"$ref": "#/components/schemas/Team"
},
"type": "array"
}
},
"required": [
"ok",
"teams"
],
"type": "object"
},
"TeamSuggestionListResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"suggestions": {
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array"
}
},
"required": [
"ok",
"suggestions"
],
"type": "object"
},
"TokenResponse": {
"additionalProperties": false,
"properties": {
"expires_in_hours": {
"type": "integer"
},
"ok": {
"type": "boolean"
},
"token": {
"type": "string"
},
"token_type": {
"example": "Bearer",
"type": "string"
}
},
"required": [
"ok",
"token",
"token_type",
"expires_in_hours"
],
"type": "object"
},
"CieStartRequest": {
"additionalProperties": false,
"properties": {
"frontend_redirect_uri": {
"type": "string"
}
},
"required": [
"frontend_redirect_uri"
],
"type": "object"
},
"CieStartResponse": {
"additionalProperties": false,
"properties": {
"authorization_url": {
"type": "string"
},
"ok": {
"type": "boolean"
},
"state": {
"type": "string"
},
"status": {
"type": "string"
}
},
"required": [
"ok",
"authorization_url",
"state",
"status"
],
"type": "object"
},
"CieExchangeRequest": {
"additionalProperties": false,
"properties": {
"email": {
"type": "string"
},
"fiscal_code": {
"type": "string"
},
"first_name": {
"type": "string"
},
"issuer": {
"type": "string"
},
"last_name": {
"type": "string"
},
"state": {
"type": "string"
},
"subject": {
"type": "string"
}
},
"required": [
"state",
"issuer",
"subject",
"fiscal_code"
],
"type": "object"
},
"CieSessionResponse": {
"additionalProperties": false,
"properties": {
"auth": {
"additionalProperties": true,
"type": "object"
},
"ok": {
"type": "boolean"
},
"status": {
"type": "string"
},
"user_id": {
"format": "int64",
"type": "integer"
}
},
"required": [
"ok",
"status"
],
"type": "object"
},
"UpdateModerationRequest": {
"additionalProperties": false,
"properties": {
"reject_report": {
"type": "boolean"
},
"resolution_note": {
"type": "string"
},
"status": {
"enum": [
"RESOLVED",
"DISMISSED"
],
"type": "string"
}
},
"required": [
"status"
],
"type": "object"
},
"UpdateStatusRequest": {
"additionalProperties": false,
"properties": {
"note": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/ReportStatus"
}
},
"required": [
"status"
],
"type": "object"
},
"UpdateUserBanRequest": {
"additionalProperties": false,
"properties": {
"banned": {
"type": "boolean"
}
},
"required": [
"banned"
],
"type": "object"
},
"UpdateUserRolesRequest": {
"additionalProperties": false,
"properties": {
"roles": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"roles"
],
"type": "object"
},
"UserListResponse": {
"additionalProperties": false,
"properties": {
"ok": {
"type": "boolean"
},
"users": {
"items": {
"$ref": "#/components/schemas/AdminUser"
},
"type": "array"
}
},
"required": [
"ok",
"users"
],
"type": "object"
},
"VerifyOtpRequest": {
"additionalProperties": false,
"properties": {
"code": {
"type": "string"
},
"email": {
"format": "email",
"type": "string"
}
},
"required": [
"email",
"code"
],
"type": "object"
}
},
"securitySchemes": {
"bearerAuth": {
"scheme": "bearer",
"type": "http"
}
}
},
"info": {
"description": "Visione OpenAPI contract maintained manually and merged with Drogon route extraction.",
"title": "Visione API",
"version": "0.1.0"
},
"openapi": "3.0.3",
"paths": {
"/api/v1/auth/cie/exchange": {
"post": {
"description": "Completes CIE bridge exchange after Django RP verifies the identity and posts signed user claims.",
"operationId": "AuthController.completeCieLogin",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CieExchangeRequest"
}
}
},
"required": true
},
"responses": {
"302": {
"description": "Redirect to frontend callback URL with state query parameter."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"summary": "Complete CIE login",
"tags": [
"Auth"
]
}
},
"/api/v1/auth/cie/session/{id}": {
"get": {
"description": "Returns status for CIE login session started by Visione.",
"operationId": "AuthController.cieSessionStatus",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CieSessionResponse"
}
}
},
"description": "Current login session status."
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"summary": "CIE session status",
"tags": [
"Auth"
]
}
},
"/api/v1/auth/cie/start": {
"post": {
"description": "Creates a local CIE login session and returns Django RP authorization URL.",
"operationId": "AuthController.startCieLogin",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CieStartRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CieStartResponse"
}
}
},
"description": "Authorization URL and local state."
},
"400": {
"$ref": "#/components/responses/BadRequest"
}
},
"summary": "Start CIE login",
"tags": [
"Auth"
]
}
},
"/api/v1/admin/areas": {
"post": {
"description": "Creates a municipal area with GeoJSON boundary.",
"operationId": "AdminController.createArea",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateAreaRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Created area result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Create area",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/areas/{id}": {
"delete": {
"description": "Deletes an existing municipal area and clears linked report/team area references.",
"operationId": "AdminController.deleteArea",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Deleted area result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Delete area",
"tags": [
"Admin"
]
},
"patch": {
"description": "Updates an existing municipal area.",
"operationId": "AdminController.updateArea",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateAreaRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Updated area result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Update area",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/categories": {
"post": {
"description": "Creates a report category.",
"operationId": "AdminController.createCategory",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateCategoryRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Created category result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Create category",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/categories/{id}": {
"delete": {
"description": "Soft-deletes an existing report category by setting active to false.",
"operationId": "AdminController.deleteCategory",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Deleted category result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Delete category",
"tags": [
"Admin"
]
},
"patch": {
"description": "Updates an existing report category.",
"operationId": "AdminController.updateCategory",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateCategoryRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Updated category result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Update category",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/moderation": {
"get": {
"description": "Lists moderation flags for admin/operator review.",
"operationId": "AdminController.listModeration",
"parameters": [
{
"in": "query",
"name": "status",
"required": false,
"schema": {
"enum": [
"OPEN",
"RESOLVED",
"DISMISSED"
],
"type": "string"
}
},
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ModerationListResponse"
}
}
},
"description": "Paged moderation flags."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List moderation flags",
"tags": [
"Moderation"
]
}
},
"/api/v1/admin/moderation/{id}": {
"patch": {
"description": "Resolves or dismisses a moderation flag. Optionally rejects the related report.",
"operationId": "AdminController.updateModeration",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateModerationRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Moderation update result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Update moderation flag",
"tags": [
"Moderation"
]
}
},
"/api/v1/admin/stats/overview": {
"get": {
"description": "Returns report statistics for administration dashboards.",
"operationId": "AdminController.overviewStats",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OverviewStatsResponse"
}
}
},
"description": "Aggregated report statistics."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Overview stats",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/teams": {
"post": {
"description": "Creates an intervention team.",
"operationId": "AdminController.createTeam",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateTeamRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Created team result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Create team",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/teams/{id}": {
"delete": {
"description": "Soft-deletes an existing intervention team by setting active to false.",
"operationId": "AdminController.deleteTeam",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Deleted team result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Delete team",
"tags": [
"Admin"
]
},
"patch": {
"description": "Updates an existing intervention team.",
"operationId": "AdminController.updateTeam",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateTeamRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Updated team result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Update team",
"tags": [
"Admin"
]
}
},
"/api/v1/areas": {
"get": {
"description": "Lists municipal areas.",
"operationId": "PublicController.listAreas",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AreaListResponse"
}
}
},
"description": "Area list."
}
},
"summary": "List areas",
"tags": [
"Public"
]
}
},
"/api/v1/admin/users": {
"get": {
"description": "Lists platform users with role information.",
"operationId": "AdminController.listUsers",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserListResponse"
}
}
},
"description": "User list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List users",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/users/{id}/ban": {
"patch": {
"description": "Updates a user's banned flag.",
"operationId": "AdminController.updateUserBan",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateUserBanRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Ban update result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Ban or unban user",
"tags": [
"Admin"
]
}
},
"/api/v1/admin/users/{id}/roles": {
"patch": {
"description": "Replaces the roles assigned to a user.",
"operationId": "AdminController.updateUserRoles",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateUserRolesRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Role update result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Update user roles",
"tags": [
"Admin"
]
}
},
"/api/v1/auth/otp/request": {
"post": {
"description": "Sends a one-time code by email through Mailpit locally.",
"operationId": "AuthController.requestOtp",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EmailRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OtpRequestResponse"
}
}
},
"description": "OTP challenge result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
}
},
"summary": "Request OTP",
"tags": [
"Auth"
]
}
},
"/api/v1/auth/otp/verify": {
"post": {
"description": "Verifies an email OTP and creates an API token.",
"operationId": "AuthController.verifyOtp",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VerifyOtpRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenResponse"
}
}
},
"description": "Bearer token when verification succeeds."
},
"400": {
"$ref": "#/components/responses/BadRequest"
}
},
"summary": "Verify OTP",
"tags": [
"Auth"
]
}
},
"/api/v1/auth/register": {
"post": {
"description": "Creates a citizen account with personal data.",
"operationId": "AuthController.registerCitizen",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterCitizenRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterCitizenResponse"
}
}
},
"description": "Registration result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
}
},
"summary": "Register citizen",
"tags": [
"Auth"
]
}
},
"/api/v1/docs": {
"get": {
"description": "Serves a local Swagger UI page backed by openapi.json.",
"operationId": "ApiController.docs",
"parameters": [ ],
"responses": {
"200": {
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
},
"description": "HTML documentation page."
}
},
"summary": "Swagger UI",
"tags": [
"Technical"
]
}
},
"/api/v1/health": {
"get": {
"description": "Returns process health without checking dependencies.",
"operationId": "ApiController.health",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HealthResponse"
}
}
},
"description": "Service health status."
}
},
"summary": "Health check",
"tags": [
"Technical"
]
}
},
"/api/v1/me": {
"get": {
"description": "Returns the authenticated user's profile and permissions.",
"operationId": "AuthController.me",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CurrentUserResponse"
}
}
},
"description": "Authenticated user context."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Current user",
"tags": [
"Auth"
]
},
"patch": {
"description": "Updates fields of the authenticated user's profile.",
"operationId": "AuthController.editUser",
"parameters": [ ],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EditUserRequest"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "User profile updated successfully."
},
"400": {
"description": "Invalid parameter type or structural error."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Edit current user profile",
"tags": [
"Auth"
]
}
},
"/api/v1/me/rewards": {
"get": {
"description": "Returns current points and reward events for the authenticated user.",
"operationId": "UserController.rewards",
"parameters": [
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RewardsResponse"
}
}
},
"description": "Reward ledger."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Reward ledger",
"tags": [
"User"
]
}
},
"/api/v1/notifications": {
"get": {
"description": "Lists notifications for the authenticated user.",
"operationId": "UserController.listNotifications",
"parameters": [
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/NotificationListResponse"
}
}
},
"description": "Paged notification list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List notifications",
"tags": [
"User"
]
}
},
"/api/v1/notifications/{id}/read": {
"patch": {
"description": "Marks a notification as read for the authenticated user.",
"operationId": "UserController.markNotificationRead",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Notification update result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Mark notification read",
"tags": [
"User"
]
}
},
"/api/v1/notifications/read-all": {
"patch": {
"description": "Marks all notifications as read for the authenticated user.",
"operationId": "UserController.markAllNotificationsRead",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Notification update result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Mark all notifications read",
"tags": [
"User"
]
}
},
"/api/v1/open-data/reports": {
"get": {
"description": "Returns anonymized resolved/closed report data for public reuse.",
"operationId": "PublicController.openDataReports",
"parameters": [
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OpenDataReportListResponse"
}
}
},
"description": "Paged open-data report list."
}
},
"summary": "Open data reports",
"tags": [
"Public"
]
}
},
"/api/v1/openapi.json": {
"get": {
"description": "Returns the generated OpenAPI JSON document.",
"operationId": "ApiController.openApi",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OpenApiDocument"
}
}
},
"description": "OpenAPI 3 JSON document."
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"summary": "OpenAPI document",
"tags": [
"Technical"
]
}
},
"/api/v1/interventions/{id}": {
"get": {
"description": "Returns public intervention summary for external intervention teams.",
"operationId": "PublicController.interventionSummary",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InterventionSummaryResponse"
}
}
},
"description": "Public intervention summary."
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"summary": "Public intervention summary",
"tags": [
"Public"
]
}
},
"/api/v1/operator/reports/assigned": {
"get": {
"description": "Lists reports assigned to the authenticated operator.",
"operationId": "ReportController.assignedReports",
"parameters": [
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PagedReportListResponse"
}
}
},
"description": "Paged assigned report list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Assigned reports",
"tags": [
"Reports"
]
}
},
"/api/v1/operator/reports/open": {
"get": {
"description": "Lists open reports not yet taken by an operator.",
"operationId": "ReportController.openReports",
"parameters": [
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PagedReportListResponse"
}
}
},
"description": "Paged open report list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Open unassigned reports",
"tags": [
"Reports"
]
}
},
"/api/v1/operator/reports/others": {
"get": {
"description": "Lists reports assigned to another operator.",
"operationId": "ReportController.otherOperatorReports",
"parameters": [
{
"in": "query",
"name": "page",
"required": false,
"schema": {
"type": "integer"
}
},
{
"in": "query",
"name": "per_page",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PagedReportListResponse"
}
}
},
"description": "Paged report list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Other operator reports",
"tags": [
"Reports"
]
}
},
"/api/v1/operator/teams": {
"get": {
"description": "Lists active intervention teams for operators and admins.",
"operationId": "ReportController.listTeams",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TeamListResponse"
}
}
},
"description": "Team list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List teams",
"tags": [
"Reports"
]
}
},
"/api/v1/ready": {
"get": {
"description": "Checks whether MySQL is reachable.",
"operationId": "ApiController.ready",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReadyResponse"
}
}
},
"description": "Dependency readiness status."
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReadyResponse"
}
}
},
"description": "Dependency readiness failure."
}
},
"summary": "Readiness check",
"tags": [
"Technical"
]
}
},
"/api/v1/reports": {
"get": {
"description": "Lists reports visible to the authenticated user.",
"operationId": "ReportController.list",
"parameters": [
{
"in": "query",
"name": "area_id",
"required": false,
"schema": {
"format": "int64",
"type": "integer"
}
},
{
"in": "query",
"name": "category_id",
"required": false,
"schema": {
"format": "int64",
"type": "integer"
}
},
{
"in": "query",
"name": "status",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReportListResponse"
}
}
},
"description": "Report list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List reports",
"tags": [
"Reports"
]
},
"post": {
"description": "Creates a citizen urban issue report.",
"operationId": "ReportController.create",
"parameters": [ ],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateReportRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateReportResponse"
}
}
},
"description": "Created report id and inferred area."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Create report",
"tags": [
"Reports"
]
}
},
"/api/v1/report-categories": {
"get": {
"description": "Lists active report categories for authenticated users.",
"operationId": "ReportController.listCategories",
"parameters": [ ],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CategoryListResponse"
}
}
},
"description": "Report category list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List categories",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}": {
"get": {
"description": "Returns report detail, status history and media.",
"operationId": "ReportController.detail",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReportDetailResponse"
}
}
},
"description": "Report detail."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Report detail",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/intervention-link": {
"delete": {
"description": "Revokes current public intervention link for assigned team.",
"operationId": "ReportController.revokeInterventionLink",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Link revocation result."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Revoke intervention link",
"tags": [
"Reports"
]
},
"post": {
"description": "Creates or rotates public intervention link for external intervention team.",
"operationId": "ReportController.createInterventionLink",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AssignmentLinkResponse"
}
}
},
"description": "Generated public link."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"409": {
"$ref": "#/components/responses/Conflict"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Create intervention link",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/assignments": {
"post": {
"description": "Assigns an intervention team to a report.",
"operationId": "ReportController.assignTeam",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AssignTeamRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Assignment result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Assign team",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/feedback": {
"post": {
"description": "Adds citizen feedback after report resolution.",
"operationId": "ReportController.addFeedback",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FeedbackRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Feedback result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Add feedback",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/flags": {
"post": {
"description": "Creates a moderation flag for a report by assigned operator only.",
"operationId": "ReportController.flagReport",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FlagRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FlagResponse"
}
}
},
"description": "Created moderation flag."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Flag report",
"tags": [
"Moderation"
]
}
},
"/api/v1/reports/{id}/intervention-summary": {
"get": {
"description": "Returns operator-facing report data, media and the latest messages for intervention planning.",
"operationId": "ReportController.interventionSummary",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InterventionSummaryResponse"
}
}
},
"description": "Intervention summary."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Intervention summary",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/team-suggestions": {
"get": {
"description": "Suggests compatible teams for report category and area.",
"operationId": "ReportController.teamSuggestions",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TeamSuggestionListResponse"
}
}
},
"description": "Suggested teams."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Team suggestions",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/media": {
"post": {
"description": "Uploads report images or videos as multipart files.",
"operationId": "ReportController.uploadMedia",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/MediaUploadRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MediaUploadResponse"
}
}
},
"description": "Uploaded media list."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Upload media",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/messages": {
"get": {
"description": "Lists messages for a report conversation.",
"operationId": "ReportController.listMessages",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MessageListResponse"
}
}
},
"description": "Message list."
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "List messages",
"tags": [
"Reports"
]
},
"post": {
"description": "Adds a citizen/operator message to a report.",
"operationId": "ReportController.addMessage",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MessageRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Message creation result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Add message",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/messages/{message_id}/flags": {
"post": {
"description": "Creates a moderation flag for a report message by assigned operator only.",
"operationId": "ReportController.flagMessage",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
},
{
"in": "path",
"name": "message_id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FlagRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FlagResponse"
}
}
},
"description": "Created moderation flag."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Flag message",
"tags": [
"Moderation"
]
}
},
"/api/v1/reports/{id}/status": {
"patch": {
"description": "Updates a report status following allowed transitions.",
"operationId": "ReportController.updateStatus",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateStatusRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Status update result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Update report status",
"tags": [
"Reports"
]
}
},
"/api/v1/reports/{id}/take": {
"post": {
"description": "Assigns an open report to current non-admin operator.",
"operationId": "ReportController.takeReport",
"parameters": [
{
"in": "path",
"name": "id",
"required": true,
"schema": {
"format": "int64",
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
},
"description": "Take report result."
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
}
},
"security": [
{
"bearerAuth": [ ]
}
],
"summary": "Take report",
"tags": [
"Reports"
]
}
}
},
"servers": [
{
"url": "http://localhost:5555"
}
]
}