{"components":{"schemas":{"Announcement":{"properties":{"id":{"type":"integer"},"message":{"nullable":true,"type":"string"},"published_at":{"format":"date-time","nullable":true,"type":"string"},"summary":{"type":"string"},"tag":{"nullable":true,"type":"string"},"title":{"type":"string"}},"type":"object"},"Error":{"properties":{"error":{"properties":{"code":{"example":"not_found","type":"string"},"message":{"type":"string"}},"required":["code","message"],"type":"object"}},"required":["error"],"type":"object"},"Game":{"properties":{"banner":{"nullable":true,"type":"string"},"category":{"nullable":true,"type":"string"},"cover":{"nullable":true,"type":"string"},"description":{"nullable":true,"type":"string"},"icon":{"nullable":true,"type":"string"},"plans":{"items":{"properties":{"features":{"items":{"type":"string"},"type":"array"},"period":{"example":"month","type":"string"},"popular":{"type":"boolean"},"price":{"type":"string"},"stripeId":{"nullable":true,"type":"string"},"subtitle":{"type":"string"},"title":{"type":"string"}},"type":"object"},"type":"array"},"priceFrom":{"nullable":true,"type":"string"},"pricingBackground":{"nullable":true,"type":"string"},"shortDesc":{"nullable":true,"type":"string"},"slug":{"type":"string"},"title":{"type":"string"}},"type":"object"},"Me":{"properties":{"admin":{"type":"boolean"},"discord_avatar_url":{"nullable":true,"type":"string"},"discord_id":{"nullable":true,"type":"string"},"discord_username":{"nullable":true,"type":"string"},"email":{"type":"string"},"first_name":{"nullable":true,"type":"string"},"id":{"type":"integer"},"last_name":{"nullable":true,"type":"string"},"nickname":{"nullable":true,"type":"string"}},"type":"object"},"Plan":{"properties":{"features":{"items":{"type":"string"},"type":"array"},"period":{"example":"month","type":"string"},"popular":{"type":"boolean"},"price":{"type":"string"},"stripeId":{"nullable":true,"type":"string"},"subtitle":{"type":"string"},"title":{"type":"string"}},"type":"object"},"PowerRequest":{"properties":{"signal":{"description":"Power signal. `kill` is not permitted via the public API.","enum":["start","stop","restart"],"type":"string"}},"required":["signal"],"type":"object"},"PowerResult":{"properties":{"server":{"type":"string"},"signal":{"enum":["start","stop","restart"],"type":"string"},"status":{"example":"accepted","type":"string"}},"type":"object"},"Server":{"properties":{"created_at":{"nullable":true,"type":"string"},"description":{"type":"string"},"feature_limits":{"type":"object"},"id":{"type":"integer"},"identifier":{"type":"string"},"is_suspended":{"type":"boolean"},"limits":{"type":"object"},"name":{"type":"string"},"panel_url":{"nullable":true,"type":"string"},"type":{"example":"pterodactyl","type":"string"},"updated_at":{"nullable":true,"type":"string"},"uuid":{"type":"string"}},"type":"object"},"Subscription":{"description":"Conservative, non-sensitive projection. Stripe identifiers, customer ids, price ids and internal server references are deliberately omitted.","properties":{"reference":{"description":"Opaque, non-reversible reference for this subscription.","type":"string"}},"type":"object"},"Ticket":{"properties":{"created_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"type":"integer"},"status":{"type":"string"},"subject":{"type":"string"},"updated_at":{"format":"date-time","nullable":true,"type":"string"}},"type":"object"},"TicketCreateRequest":{"properties":{"message":{"description":"The opening message body.","type":"string"},"service_name":{"nullable":true,"type":"string"},"service_reference":{"nullable":true,"type":"string"},"service_type":{"nullable":true,"type":"string"},"title":{"description":"Ticket subject/title. (`subject` is accepted as an alias.)","type":"string"}},"required":["title","message"],"type":"object"},"TicketCreated":{"properties":{"id":{"type":"integer"},"status":{"example":"New","type":"string"},"subject":{"type":"string"}},"type":"object"},"TicketReplyRequest":{"properties":{"message":{"description":"The reply body.","type":"string"}},"required":["message"],"type":"object"}},"securitySchemes":{"apiKeyHeader":{"description":"Send your API key in the `X-API-Key` header.","in":"header","name":"X-API-Key","type":"apiKey"},"bearerApiKey":{"description":"Send your API key as `Authorization: Bearer gv_...`.","scheme":"bearer","type":"http"}}},"info":{"description":"Versioned, read-only public API for the GameVerse platform. Authenticate with an API key (created in your account settings) via either the `Authorization: Bearer gv_...` header or the `X-API-Key` header. Each key is rate limited to 120 requests per minute. Errors use the envelope `{\"error\": {\"code\", \"message\"}}`.","title":"GameVerse Public API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/announcements":{"get":{"description":"Requires the `read:catalog` scope.","operationId":"listAnnouncements","parameters":[{"in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer"}},{"in":"query","name":"per_page","required":false,"schema":{"default":20,"maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"announcements":{"items":{"$ref":"#/components/schemas/Announcement"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"}},"type":"object"}}},"description":"Published, public-safe announcements."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"List published announcements","tags":["catalog"]}},"/catalog/games":{"get":{"description":"Requires the `read:catalog` scope.","operationId":"listCatalogGames","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"games":{"items":{"$ref":"#/components/schemas/Game"},"type":"array"}},"type":"object"}}},"description":"Active games with their plans."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"List active games with pricing plans","tags":["catalog"]}},"/catalog/games/{slug}":{"get":{"description":"Requires the `read:catalog` scope.","operationId":"getCatalogGame","parameters":[{"in":"path","name":"slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"game":{"$ref":"#/components/schemas/Game"}},"type":"object"}}},"description":"The requested game."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Game not found."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"Get a single game with pricing plans","tags":["catalog"]}},"/me":{"get":{"description":"Requires the `read:account` scope.","operationId":"getMe","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"user":{"$ref":"#/components/schemas/Me"}},"type":"object"}}},"description":"The key owner's basic profile."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"User not found."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"Get the authenticated key owner's profile","tags":["account"]}},"/openapi.json":{"get":{"operationId":"getOpenApi","responses":{"200":{"content":{"application/json":{"schema":{"type":"object"}}},"description":"The OpenAPI 3.1 document."}},"security":[],"summary":"This OpenAPI document","tags":["meta"]}},"/servers":{"get":{"description":"Requires the `read:account` scope.","operationId":"listServers","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"servers":{"items":{"$ref":"#/components/schemas/Server"},"type":"array"},"summary":{"properties":{"total":{"type":"integer"}},"type":"object"}},"type":"object"}}},"description":"The key owner's servers."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Upstream provisioning service failure."}},"summary":"List the key owner's game servers","tags":["account"]}},"/servers/{server_identifier}/power":{"post":{"description":"Requires the `write:servers` scope. Sends `start`, `stop` or `restart` to a server you own. `kill` is rejected. You may only act on servers you own; any other identifier returns 404.","operationId":"serverPower","parameters":[{"description":"The server's client identifier (short UUID).","in":"path","name":"server_identifier","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerRequest"}}},"description":"","required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerResult"}}},"description":"The power signal was accepted by the panel."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid power signal."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Server not found / not owned by the caller."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The panel rejected the request or is unavailable (e.g. the configured client API key is invalid)."}},"summary":"Send a power signal to one of your servers","tags":["servers"]}},"/subscriptions":{"get":{"description":"Requires the `read:account` scope. Returns only a conservative, non-sensitive projection \u2014 no Stripe ids, customer ids, price ids or internal server references.","operationId":"listSubscriptions","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"subscriptions":{"items":{"$ref":"#/components/schemas/Subscription"},"type":"array"},"summary":{"properties":{"total":{"type":"integer"}},"type":"object"}},"type":"object"}}},"description":"The key owner's subscriptions (non-sensitive subset)."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"List the key owner's subscriptions (minimal projection)","tags":["account"]}},"/tickets":{"get":{"description":"Requires the `read:account` scope.","operationId":"listTickets","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"tickets":{"items":{"$ref":"#/components/schemas/Ticket"},"type":"array"}},"type":"object"}}},"description":"The key owner's tickets."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"List the key owner's support tickets","tags":["account"]},"post":{"description":"Requires the `write:tickets` scope. Creates a ticket owned by the key owner.","operationId":"createTicket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketCreateRequest"}}},"description":"","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"ticket":{"$ref":"#/components/schemas/TicketCreated"}},"type":"object"}}},"description":"The created ticket."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing title or message."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"Create a support ticket","tags":["tickets"]}},"/tickets/{ticket_id}/reply":{"post":{"description":"Requires the `write:tickets` scope. Adds a reply to a ticket you own; replying to another user's ticket returns 404. Closed/archived tickets return 400.","operationId":"replyTicket","parameters":[{"in":"path","name":"ticket_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketReplyRequest"}}},"description":"","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"status":{"example":"Active","type":"string"},"ticket_id":{"type":"integer"}},"type":"object"}}},"description":"The reply was recorded."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Empty message or a closed ticket."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The API key lacks the required scope."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Ticket not found / not owned by the caller."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Internal error."}},"summary":"Reply to one of your own support tickets","tags":["tickets"]}}},"security":[{"bearerApiKey":[]},{"apiKeyHeader":[]}],"servers":[{"url":"/api/v1"}],"tags":[{"description":"Public game catalog and announcements.","name":"catalog"},{"description":"The authenticated key owner's own data.","name":"account"},{"description":"Create and reply to your own support tickets.","name":"tickets"},{"description":"Manage your own game servers.","name":"servers"},{"description":"API metadata.","name":"meta"}]}
