{
  "openapi": "3.1.0",
  "info": {
    "title": "WOIZZ Public API",
    "version": "0.1.0",
    "description": "Public, secret-free API contract for WOIZZ live-event discovery, public intake, account/media capability checks, source provenance and approved partner newswire integrations. Preserve source attribution when republishing events."
  },
  "servers": [
    {
      "url": "https://woizz.app",
      "description": "WOIZZ production"
    }
  ],
  "tags": [
    {
      "name": "Readiness",
      "description": "Secret-free service and launch capability status."
    },
    {
      "name": "Public live events",
      "description": "Cacheable public event projections for maps, previews and discovery."
    },
    {
      "name": "Public intake",
      "description": "Public contact and event report intake contracts with bounded validation and fail-closed responses."
    },
    {
      "name": "Account capability",
      "description": "Provider-neutral account status and bearer-session boundaries."
    },
    {
      "name": "Media upload capability",
      "description": "Provider-neutral media upload readiness and authenticated sandbox upload boundaries."
    },
    {
      "name": "Source registry",
      "description": "Public provenance registry for official/system feed sources and candidate-only references."
    },
    {
      "name": "Partner newswire",
      "description": "Protected JSON and RSS exports for approved media partners."
    }
  ],
  "paths": {
    "/api/live-events": {
      "get": {
        "tags": [
          "Public live events"
        ],
        "summary": "List recent public live events",
        "description": "Returns a bounded public projection of live or verified WOIZZ events. The response may include official/system source fields including external_source_attribution and sanitized media evidence metadata when available.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 25,
              "default": 25
            },
            "description": "Maximum number of events to return."
          }
        ],
        "responses": {
          "200": {
            "description": "Recent public events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "events"
                  ],
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LiveEvent"
                      }
                    }
                  }
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/external-feed-sources": {
      "get": {
        "tags": [
          "Source registry"
        ],
        "summary": "List public source registry entries",
        "description": "Returns the public source registry used for provenance checks. Active official/system sources are separated from candidate-only references that are not scraped as live events.",
        "responses": {
          "200": {
            "description": "Public source registry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "sources",
                    "policy"
                  ],
                  "properties": {
                    "sources": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ExternalFeedSource"
                      }
                    },
                    "policy": {
                      "$ref": "#/components/schemas/SourcePolicy"
                    }
                  }
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/partner-newswire": {
      "get": {
        "tags": [
          "Partner newswire"
        ],
        "summary": "Export approved partner newswire events",
        "description": "Protected server-to-server feed for approved media partners. JSON is intended for newsroom systems; RSS is intended for feed readers and lightweight syndication. Header-based authentication is preferred because query tokens can be logged by intermediaries.",
        "security": [
          {
            "partnerBearer": []
          },
          {
            "partnerTokenHeader": []
          },
          {
            "partnerTokenQuery": []
          }
        ],
        "parameters": [
          {
            "name": "partner",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "partner",
              "maxLength": 40,
              "pattern": "^[a-z0-9_-]+$"
            },
            "description": "Partner slug used for generated feed metadata."
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "rss"
              ],
              "default": "json"
            },
            "description": "Response format."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            },
            "description": "Maximum number of events to return."
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 168,
              "default": 24
            },
            "description": "Lookback window in hours."
          }
        ],
        "responses": {
          "200": {
            "description": "Newswire events in the selected format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerNewswirePayload"
                }
              },
              "application/rss+xml": {
                "schema": {
                  "type": "string",
                  "description": "RSS 2.0 document with WOIZZ extension fields for status, severity, coordinates, confirmations and source attribution."
                }
              }
            }
          },
          "401": {
            "description": "Partner feed token missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/readiness": {
      "get": {
        "tags": [
          "Readiness"
        ],
        "summary": "Check Plan A API readiness",
        "description": "Returns secret-free service readiness. Use db=1 to include a database ping and ops=1 to include operator-token posture plus account/media launch capability states without returning secret values.",
        "parameters": [
          {
            "name": "db",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Include database ping state."
          },
          {
            "name": "ops",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Include full operator and launch capability posture."
          }
        ],
        "responses": {
          "200": {
            "description": "API is ready for requested checks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "503": {
            "description": "One or more requested readiness checks is missing or failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/contact-requests": {
      "post": {
        "tags": [
          "Public intake"
        ],
        "summary": "Submit a public contact request",
        "description": "Stores a bounded public contact, privacy, legal, partner, support or deletion request. Raw IP addresses are not returned and backend details stay hidden on failure.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequestInput"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Contact request accepted for review.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactRequestAccepted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/event-reports": {
      "post": {
        "tags": [
          "Public intake"
        ],
        "summary": "Submit a public event report",
        "description": "Queues a bounded public event report for review. Coordinates are validated and may be reduced according to geoPrecision before storage.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventReportInput"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Event report accepted for review.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventReportAccepted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/account-capability": {
      "get": {
        "tags": [
          "Account capability"
        ],
        "summary": "Read public account capability posture",
        "description": "Returns whether account controls should be opened. In current launch mode this endpoint is intentionally public and fail-closed while Google, email, magic-link and TOTP controls stay hidden until provider UX is opened.",
        "responses": {
          "200": {
            "description": "Account capability posture.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCapabilityResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/account-session": {
      "get": {
        "tags": [
          "Account capability"
        ],
        "summary": "Verify a signed-in account session",
        "description": "Verifies a configured provider bearer session and returns only sanitized session posture. Raw subject ids and tokens are not returned.",
        "security": [
          {
            "accountBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Session verified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountSessionResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/account-profile": {
      "get": {
        "tags": [
          "Account capability"
        ],
        "summary": "Read sanitized account profile posture",
        "description": "Returns a hashed account reference, provider, tier and capability flags for a verified bearer session. Raw subject ids and tokens are not returned.",
        "security": [
          {
            "accountBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sanitized account profile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountProfileResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/media-upload-capability": {
      "get": {
        "tags": [
          "Media upload capability"
        ],
        "summary": "Read public media upload capability posture",
        "description": "Returns photo/video attachment readiness, accepted media types and bounded size limits without returning storage credentials or backend provider details beyond the public provider state.",
        "responses": {
          "200": {
            "description": "Media upload capability posture.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaUploadCapabilityResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/api/media-upload-issue": {
      "post": {
        "tags": [
          "Media upload capability"
        ],
        "summary": "Issue a short-lived media upload action",
        "description": "Requires a media-eligible bearer session. Returns a short-lived upload action from the server-side storage proxy without exposing storage credentials.",
        "security": [
          {
            "accountBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MediaUploadIssueInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload action issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaUploadIssueResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/media-upload-finalize": {
      "post": {
        "tags": [
          "Media upload capability"
        ],
        "summary": "Finalize uploaded media metadata",
        "description": "Requires a media-eligible bearer session. Finalizes the server-side storage object and stores sanitized media metadata for review/public evidence after publication.",
        "security": [
          {
            "accountBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MediaUploadFinalizeInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload finalized and metadata stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaUploadFinalizeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "partnerBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Approved partner token. Share credentials out-of-band and rotate them if exposed."
      },
      "partnerTokenHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-WOIZZ-Partner-Token",
        "description": "Alternative approved partner token header."
      },
      "partnerTokenQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "access_token",
        "description": "Fallback for RSS clients that cannot set headers. Header-based access is preferred."
      },
      "accountBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Signed-in session token from the configured account provider. Tokens stay in clients or server runtime and are not documented with sample values."
      }
    },
    "responses": {
      "MethodNotAllowed": {
        "description": "HTTP method is not supported.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unavailable": {
        "description": "The feed is temporarily unavailable and fails closed without exposing provider details.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Payload validation failed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Request limit reached for the current window.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Signed-in account session is missing or invalid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The signed-in account is not eligible for this action.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotImplemented": {
        "description": "The selected account provider is not available for this endpoint yet.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UpstreamUnavailable": {
        "description": "The upstream storage or database action failed closed without exposing provider details.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": false
          }
        },
        "additionalProperties": true
      },
      "LiveEvent": {
        "type": "object",
        "required": [
          "id",
          "category",
          "description",
          "lat",
          "lng",
          "status",
          "severity",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "lat": {
            "type": "number"
          },
          "lng": {
            "type": "number"
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "verified"
            ]
          },
          "severity": {
            "type": "integer",
            "minimum": 1
          },
          "upvotes": {
            "type": "integer"
          },
          "confirmation_count": {
            "type": "integer"
          },
          "external_source_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Official/system source id when available."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Source-native id when available."
          },
          "external_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "external_source_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "external_source_attribution": {
            "type": [
              "string",
              "null"
            ],
            "description": "Attribution text that must be preserved when republishing."
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventEvidence"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "EventEvidence": {
        "type": "object",
        "required": [
          "kind",
          "label",
          "url",
          "source"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          },
          "label": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "thumbnailUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "source": {
            "type": "string",
            "description": "Public storage/evidence source label."
          }
        },
        "additionalProperties": true
      },
      "ExternalFeedSource": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "kind",
          "apiEndpoint",
          "attribution",
          "category",
          "subcategory",
          "ingestion",
          "note"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "requires_optional_key",
              "candidate_only"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "official_api",
              "official_reference",
              "public_archive"
            ]
          },
          "apiEndpoint": {
            "type": "string",
            "format": "uri"
          },
          "attribution": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "nature",
              "safety",
              "environment",
              "social",
              "anomaly"
            ]
          },
          "subcategory": {
            "type": "string"
          },
          "ingestion": {
            "type": "string",
            "enum": [
              "automated",
              "configured_only",
              "manual_review_only"
            ]
          },
          "note": {
            "type": "string"
          }
        }
      },
      "SourcePolicy": {
        "type": "object",
        "required": [
          "attributionRequired",
          "provenanceFields"
        ],
        "properties": {
          "attributionRequired": {
            "type": "boolean",
            "const": true
          },
          "automatedSourceIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "configuredSourceIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "candidateOnlySourceIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "candidateOnlyBoundary": {
            "type": "string"
          },
          "provenanceFields": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "external_source_id",
                "external_id",
                "external_url",
                "external_source_attribution"
              ]
            }
          }
        },
        "additionalProperties": true
      },
      "PartnerNewswirePayload": {
        "type": "object",
        "required": [
          "ok",
          "partner",
          "generatedAt",
          "documentationUrl",
          "sourceRegistryUrl",
          "license",
          "attributionRequired",
          "events"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "partner": {
            "type": "string"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "documentationUrl": {
            "type": "string",
            "format": "uri"
          },
          "sourceRegistryUrl": {
            "type": "string",
            "format": "uri"
          },
          "license": {
            "type": "string",
            "description": "Source attribution must be preserved."
          },
          "attributionRequired": {
            "type": "boolean",
            "const": true
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PartnerNewswireEvent"
            }
          }
        }
      },
      "PartnerNewswireEvent": {
        "type": "object",
        "required": [
          "id",
          "url",
          "category",
          "status",
          "description",
          "severity",
          "location",
          "confidence",
          "source",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical public WOIZZ event detail URL using the /event/{id} route."
          },
          "category": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "verified"
            ]
          },
          "description": {
            "type": "string"
          },
          "severity": {
            "type": "integer",
            "minimum": 1
          },
          "location": {
            "type": "object",
            "required": [
              "lat",
              "lng"
            ],
            "properties": {
              "lat": {
                "type": "number"
              },
              "lng": {
                "type": "number"
              }
            }
          },
          "confidence": {
            "type": "object",
            "required": [
              "upvotes",
              "confirmations"
            ],
            "properties": {
              "upvotes": {
                "type": "integer"
              },
              "confirmations": {
                "type": "integer"
              }
            }
          },
          "source": {
            "$ref": "#/components/schemas/NewswireSource"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "NewswireSource": {
        "type": "object",
        "required": [
          "id",
          "externalId",
          "name",
          "url",
          "attribution"
        ],
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalId": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "attribution": {
            "type": [
              "string",
              "null"
            ],
            "description": "Attribution text that must be preserved when republishing."
          }
        }
      },
      "ReadinessResponse": {
        "type": "object",
        "required": [
          "ok",
          "service",
          "checks",
          "timestamp"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "service": {
            "type": "string",
            "const": "woizz-api"
          },
          "checks": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "enum": [
                "configured",
                "failed",
                "missing",
                "ok",
                "skipped"
              ]
            }
          },
          "launchReady": {
            "type": "boolean"
          },
          "launchChecks": {
            "type": "object",
            "properties": {
              "accountCapability": {
                "$ref": "#/components/schemas/LaunchCapabilityCheck"
              },
              "mediaUploadCapability": {
                "$ref": "#/components/schemas/LaunchCapabilityCheck"
              }
            },
            "additionalProperties": false
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": true
      },
      "LaunchCapabilityCheck": {
        "type": "object",
        "required": [
          "state",
          "provider",
          "reason",
          "endpointReady"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "missing",
              "pending",
              "ready",
              "unsupported"
            ]
          },
          "provider": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "endpointReady": {
            "type": "boolean"
          }
        }
      },
      "ContactRequestInput": {
        "type": "object",
        "required": [
          "topic",
          "name",
          "replyChannel",
          "message"
        ],
        "properties": {
          "topic": {
            "type": "string",
            "enum": [
              "legal",
              "privacy",
              "partner",
              "support",
              "deletion"
            ]
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "replyChannel": {
            "type": "string",
            "minLength": 1,
            "maxLength": 180
          },
          "message": {
            "type": "string",
            "minLength": 12,
            "maxLength": 1200
          },
          "pagePath": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 240
          },
          "userAgent": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 240
          }
        },
        "additionalProperties": false
      },
      "ContactRequestAccepted": {
        "type": "object",
        "required": [
          "ok",
          "request"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "request": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "additionalProperties": true
          }
        }
      },
      "EventReportInput": {
        "type": "object",
        "required": [
          "category",
          "description",
          "lat",
          "lng",
          "geoPrecision"
        ],
        "properties": {
          "category": {
            "type": "string",
            "enum": [
              "nature",
              "safety",
              "environment",
              "social",
              "infrastructure",
              "anomaly",
              "other"
            ]
          },
          "subcategory": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 80
          },
          "description": {
            "type": "string",
            "minLength": 12,
            "maxLength": 2000
          },
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lng": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "geoPrecision": {
            "type": "string",
            "enum": [
              "exact",
              "reduced",
              "anonymous",
              "city"
            ]
          },
          "isAnonymous": {
            "type": "boolean"
          },
          "severity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 10
          },
          "pagePath": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 240
          },
          "userAgent": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 240
          }
        },
        "additionalProperties": false
      },
      "EventReportAccepted": {
        "type": "object",
        "required": [
          "ok",
          "report"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "report": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "additionalProperties": true
          }
        }
      },
      "AccountCapabilityResponse": {
        "type": "object",
        "required": [
          "ok",
          "available",
          "provider",
          "reason",
          "message",
          "providers",
          "accountEndpointReady",
          "sessionEndpointReady"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean",
            "const": false
          },
          "provider": {
            "type": "string",
            "enum": [
              "none",
              "custom_oidc",
              "auth0",
              "clerk",
              "unsupported"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "auth_provider_not_configured",
              "auth_secret_missing",
              "account_endpoint_not_implemented",
              "unsupported_auth_provider"
            ]
          },
          "message": {
            "type": "string"
          },
          "providers": {
            "type": "object",
            "properties": {
              "google": {
                "type": "string"
              },
              "emailPassword": {
                "type": "string"
              },
              "magicLink": {
                "type": "string"
              },
              "totp": {
                "type": "string"
              }
            },
            "additionalProperties": false
          },
          "accountEndpointReady": {
            "type": "boolean"
          },
          "sessionEndpointReady": {
            "type": "boolean"
          }
        }
      },
      "AccountSessionResponse": {
        "type": "object",
        "required": [
          "ok",
          "authenticated",
          "provider",
          "sessionEndpointReady"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "authenticated": {
            "type": "boolean"
          },
          "provider": {
            "type": "string"
          },
          "sessionEndpointReady": {
            "type": "boolean"
          },
          "tier": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "media",
              "b2b",
              "system"
            ]
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "AccountProfileResponse": {
        "type": "object",
        "required": [
          "ok",
          "authenticated"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "authenticated": {
            "type": "boolean"
          },
          "account": {
            "type": "object",
            "properties": {
              "ref": {
                "type": "string"
              },
              "provider": {
                "type": "string"
              },
              "tier": {
                "type": "string",
                "enum": [
                  "free",
                  "pro",
                  "media",
                  "b2b",
                  "system"
                ]
              }
            },
            "additionalProperties": false
          },
          "capabilities": {
            "type": "object",
            "properties": {
              "alerts": {
                "type": "boolean"
              },
              "mediaUpload": {
                "type": "boolean"
              },
              "reportHistory": {
                "type": "boolean"
              }
            },
            "additionalProperties": false
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "MediaUploadCapabilityResponse": {
        "type": "object",
        "required": [
          "ok",
          "available",
          "provider",
          "reason",
          "message",
          "acceptedMediaTypes",
          "maxAttachmentsPerReport",
          "maxImageMb",
          "maxVideoMb",
          "uploadEndpointReady"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean"
          },
          "provider": {
            "type": "string",
            "enum": [
              "none",
              "vercel_blob",
              "cloudflare_r2",
              "sandbox_server",
              "unsupported"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "storage_provider_not_configured",
              "storage_secret_missing",
              "account_provider_not_configured",
              "ready",
              "unsupported_storage_provider"
            ]
          },
          "message": {
            "type": "string"
          },
          "acceptedMediaTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "image",
                "video"
              ]
            }
          },
          "maxAttachmentsPerReport": {
            "type": "integer",
            "minimum": 1,
            "maximum": 4
          },
          "maxImageMb": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50
          },
          "maxVideoMb": {
            "type": "integer",
            "minimum": 10,
            "maximum": 2048
          },
          "uploadEndpointReady": {
            "type": "boolean"
          }
        }
      },
      "MediaUploadIssueInput": {
        "type": "object",
        "required": [
          "fileName",
          "contentType",
          "mediaType",
          "sizeBytes"
        ],
        "properties": {
          "fileName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 180
          },
          "contentType": {
            "type": "string",
            "enum": [
              "image/jpeg",
              "image/png",
              "image/webp",
              "video/mp4",
              "video/quicktime",
              "video/webm"
            ]
          },
          "mediaType": {
            "type": "string",
            "enum": [
              "image",
              "video"
            ]
          },
          "reportId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 80
          },
          "sizeBytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2147483648
          }
        },
        "additionalProperties": false
      },
      "MediaUploadIssueResponse": {
        "type": "object",
        "required": [
          "ok",
          "uploadId",
          "objectKey",
          "uploadUrl",
          "uploadMethod",
          "uploadHeaders"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "uploadId": {
            "type": "string"
          },
          "objectKey": {
            "type": "string"
          },
          "uploadUrl": {
            "type": "string",
            "format": "uri"
          },
          "uploadMethod": {
            "type": "string",
            "enum": [
              "PUT",
              "POST"
            ]
          },
          "uploadHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "publicUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "MediaUploadFinalizeInput": {
        "type": "object",
        "required": [
          "uploadId",
          "objectKey"
        ],
        "properties": {
          "uploadId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "objectKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 240
          },
          "reportId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 80
          }
        },
        "additionalProperties": false
      },
      "MediaUploadFinalizeResponse": {
        "type": "object",
        "required": [
          "ok",
          "uploadId",
          "objectKey"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "uploadId": {
            "type": "string"
          },
          "objectKey": {
            "type": "string"
          },
          "publicUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "thumbnailUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "sha256": {
            "type": [
              "string",
              "null"
            ]
          },
          "mediaType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "image",
              "video",
              null
            ]
          },
          "durationSeconds": {
            "type": [
              "number",
              "null"
            ]
          },
          "sizeBytes": {
            "type": [
              "number",
              "null"
            ]
          },
          "media": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          }
        }
      }
    }
  }
}
