{"components":{"schemas":{"Attacker":{"description":"An attacker on a killmail","properties":{"alliance_id":{"description":"Alliance ID","nullable":true,"type":"integer"},"alliance_name":{"description":"Alliance name","nullable":true,"type":"string"},"character_id":{"description":"Character ID","type":"integer"},"character_name":{"description":"Character name","type":"string"},"corporation_id":{"description":"Corporation ID","type":"integer"},"corporation_name":{"description":"Corporation name","type":"string"},"damage_done":{"description":"Damage dealt","type":"integer"},"final_blow":{"description":"Dealt final blow","type":"boolean"},"ship_name":{"description":"Ship name","type":"string"},"ship_type_id":{"description":"Ship type ID","type":"integer"},"weapon_name":{"description":"Weapon name","type":"string"},"weapon_type_id":{"description":"Weapon type ID","type":"integer"}},"required":["damage_done","final_blow"],"title":"Attacker","type":"object"},"Error":{"description":"Error response","example":{"error":{"message":"Invalid system_ids parameter","subtype":"invalid_format","type":"validation_error"}},"properties":{"error":{"properties":{"details":{"description":"Additional error details","nullable":true,"type":"object"},"message":{"description":"Error message","type":"string"},"subtype":{"description":"Error subtype","type":"string"},"type":{"description":"Error type","type":"string"}},"required":["type","message"],"type":"object"}},"required":["error"],"title":"Error","type":"object"},"HealthStatus":{"description":"Health check response","properties":{"components":{"additionalProperties":{"properties":{"message":{"nullable":true,"type":"string"},"status":{"type":"string"}},"type":"object"},"description":"Individual component health","type":"object"},"status":{"description":"Overall health status","enum":["healthy","degraded","unhealthy"],"type":"string"},"timestamp":{"format":"date-time","type":"string"}},"required":["status","components","timestamp"],"title":"HealthStatus","type":"object"},"Killmail":{"description":"A complete killmail record with enriched data","example":{"attackers":[{"character_id":123456789,"character_name":"Attacker Name","final_blow":true,"ship_name":"Rattlesnake","ship_type_id":17918}],"kill_time":"2024-01-15T14:30:00Z","killmail_id":123456789,"solar_system_id":30000142,"solar_system_name":"Jita","victim":{"character_id":987654321,"character_name":"Victim Name","ship_name":"Raven","ship_type_id":670}},"properties":{"attackers":{"items":{"$ref":"#/components/schemas/Attacker"},"type":"array"},"kill_time":{"description":"Time when the kill occurred","format":"date-time","type":"string"},"killmail_id":{"description":"Unique killmail ID","type":"integer"},"solar_system_id":{"description":"EVE system ID","type":"integer"},"solar_system_name":{"description":"System name","type":"string"},"victim":{"$ref":"#/components/schemas/Victim"},"zkb":{"$ref":"#/components/schemas/ZKB"}},"required":["killmail_id","kill_time","solar_system_id","victim","attackers"],"title":"Killmail","type":"object"},"SSEEvent":{"description":"Server-Sent Event formats","oneOf":[{"properties":{"data":{"enum":["SSE stream connected"],"type":"string"},"event":{"enum":["connected"],"type":"string"}},"type":"object"},{"properties":{"data":{"$ref":"#/components/schemas/Killmail"},"event":{"enum":["killmail"],"type":"string"},"id":{"type":"string"}},"type":"object"},{"properties":{"data":{"properties":{"timestamp":{"format":"date-time","type":"string"}},"type":"object"},"event":{"enum":["heartbeat"],"type":"string"}},"type":"object"}],"title":"SSEEvent"},"Subscription":{"description":"Webhook subscription","properties":{"callback_url":{"description":"Webhook URL","type":"string"},"character_ids":{"description":"Tracked character IDs","items":{"type":"integer"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"id":{"description":"Subscription ID","type":"string"},"subscriber_id":{"description":"Subscriber identifier","type":"string"},"system_ids":{"description":"Subscribed system IDs","items":{"type":"integer"},"type":"array"}},"required":["id","subscriber_id","callback_url","created_at"],"title":"Subscription","type":"object"},"Victim":{"description":"The victim of a killmail","properties":{"alliance_id":{"description":"Alliance ID","nullable":true,"type":"integer"},"alliance_name":{"description":"Alliance name","nullable":true,"type":"string"},"character_id":{"description":"Character ID","type":"integer"},"character_name":{"description":"Character name","type":"string"},"corporation_id":{"description":"Corporation ID","type":"integer"},"corporation_name":{"description":"Corporation name","type":"string"},"damage_taken":{"description":"Total damage taken","type":"integer"},"ship_name":{"description":"Ship name","type":"string"},"ship_type_id":{"description":"Ship type ID","type":"integer"}},"required":["character_id","ship_type_id","damage_taken"],"title":"Victim","type":"object"},"ZKB":{"description":"zKillboard metadata","properties":{"awox":{"description":"Friendly fire","type":"boolean"},"fitted_value":{"description":"Fitted modules value","type":"number"},"hash":{"description":"Kill hash","type":"string"},"location_id":{"description":"Location ID","type":"integer"},"npc":{"description":"NPC kill","type":"boolean"},"points":{"description":"Kill points","type":"integer"},"solo":{"description":"Solo kill","type":"boolean"},"total_value":{"description":"Total ISK value","type":"number"}},"title":"ZKB","type":"object"}}},"info":{"description":"Real-time EVE Online killmail data service.\n\nThis API provides access to killmail data from EVE Online with various integration options:\n- REST endpoints for fetching historical data\n- Server-Sent Events (SSE) for real-time streaming\n- WebSocket connections for bidirectional communication\n- Webhook subscriptions for push notifications\n\nAll killmail data is enriched with additional information from EVE's ESI API.\n","title":"Wanderer Kills API","version":"1.0.0"},"openapi":"3.0.0","paths":{"/api/v1/*path":{"delete":{"callbacks":{},"description":"Returns a 404 error for undefined API routes","operationId":"WandererKillsWeb.KillsController.not_found (3)","parameters":[],"responses":{"404":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Not Found"}},"summary":"Handle undefined API routes","tags":[]},"get":{"callbacks":{},"description":"Returns a 404 error for undefined API routes","operationId":"WandererKillsWeb.KillsController.not_found","parameters":[],"responses":{"404":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Not Found"}},"summary":"Handle undefined API routes","tags":[]},"patch":{"callbacks":{},"description":"Returns a 404 error for undefined API routes","operationId":"WandererKillsWeb.KillsController.not_found (5)","parameters":[],"responses":{"404":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Not Found"}},"summary":"Handle undefined API routes","tags":[]},"post":{"callbacks":{},"description":"Returns a 404 error for undefined API routes","operationId":"WandererKillsWeb.KillsController.not_found (4)","parameters":[],"responses":{"404":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Not Found"}},"summary":"Handle undefined API routes","tags":[]},"put":{"callbacks":{},"description":"Returns a 404 error for undefined API routes","operationId":"WandererKillsWeb.KillsController.not_found (2)","parameters":[],"responses":{"404":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Not Found"}},"summary":"Handle undefined API routes","tags":[]}},"/api/v1/killmail/{killmail_id}":{"get":{"callbacks":{},"description":"Returns detailed information about a specific killmail","operationId":"WandererKillsWeb.KillsController.show","parameters":[{"description":"Killmail ID","example":123456789,"in":"path","name":"killmail_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.KillmailResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"},"404":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Killmail not found"}},"summary":"Get a specific killmail","tags":[]}},"/api/v1/kills/cached/{system_id}":{"get":{"callbacks":{},"description":"Returns cached killmail data for a specific system","operationId":"WandererKillsWeb.KillsController.cached","parameters":[{"description":"EVE Online system ID","example":30000142,"in":"path","name":"system_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.KillsResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"}},"summary":"Get cached kills for a system","tags":[]}},"/api/v1/kills/count/{system_id}":{"get":{"callbacks":{},"description":"Returns the total number of kills for a specific system","operationId":"WandererKillsWeb.KillsController.count","parameters":[{"description":"EVE Online system ID","example":30000142,"in":"path","name":"system_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.KillCountResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"}},"summary":"Get kill count for a system","tags":[]}},"/api/v1/kills/stream":{"get":{"callbacks":{},"description":"Real-time Server-Sent Events stream of killmail data with optional filtering.\n\nThe stream will send different types of events:\n- `connected`: Initial connection confirmation\n- `killmail`: New killmail data\n- `batch`: Historical killmails (on connection)\n- `heartbeat`: Keep-alive signal (every 30 seconds)\n- `error`: Error notifications\n","operationId":"WandererKillsWeb.KillStreamController.stream","parameters":[{"description":"Comma-separated list of system IDs to filter","example":"30000142,30000144","in":"query","name":"system_ids","required":false,"schema":{"type":"string"}},{"description":"Comma-separated character IDs to track as victim/attacker","example":"123456789,987654321","in":"query","name":"character_ids","required":false,"schema":{"type":"string"}},{"description":"Minimum ISK value threshold for killmails","example":100000000,"in":"query","name":"min_value","required":false,"schema":{"type":"number"}}],"responses":{"200":{"content":{"text/event-stream":{"schema":"Elixir.WandererKillsWeb.Schemas.SSEStream"}},"description":"SSE stream started"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"}},"summary":"Stream killmail events via SSE","tags":[]}},"/api/v1/kills/stream/cleanup":{"get":{"callbacks":{},"description":"Debug endpoint to cleanup dead SSE connections","operationId":"WandererKillsWeb.KillStreamController.cleanup","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"message":{"type":"string"}},"type":"object"}}},"description":"Success"}},"summary":"Cleanup SSE connections (Debug)","tags":[]}},"/api/v1/kills/stream/enhanced":{"get":{"callbacks":{},"description":"Enhanced Server-Sent Events stream with support for historical data preloading.\n\nPreloading behavior:\n- If `character_ids` and `preload_days` are specified: loads historical character killmails\n- If `system_ids` and `preload_days` are specified: loads historical system killmails\n- Character preloading takes precedence if both character_ids and system_ids are provided\n\nEvent types:\n- `connected`: Initial connection confirmation\n- `batch`: Historical killmail batch (when preload_days > 0)\n- `transition`: Marks switch from historical to real-time mode\n- `killmail`: Real-time killmail updates\n- `heartbeat`: Keep-alive with mode indicator\n- `error`: Error notifications\n","operationId":"WandererKillsWeb.EnhancedKillStreamController.stream","parameters":[{"description":"Comma-separated list of system IDs to filter","example":"30000142,30000144","in":"query","name":"system_ids","required":false,"schema":{"type":"string"}},{"description":"Comma-separated character IDs to track as victim/attacker","example":"123456789,987654321","in":"query","name":"character_ids","required":false,"schema":{"type":"string"}},{"description":"Minimum ISK value threshold for killmails","example":100000000,"in":"query","name":"min_value","required":false,"schema":{"type":"number"}},{"description":"Number of days of historical data to preload (max 90)","example":90,"in":"query","name":"preload_days","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"text/event-stream":{"schema":"Elixir.WandererKillsWeb.Schemas.SSEStream"}},"description":"SSE stream started"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"}},"summary":"Enhanced SSE stream with character preloading","tags":[]}},"/api/v1/kills/stream/stats":{"get":{"callbacks":{},"description":"Debug endpoint to get SSE connection statistics","operationId":"WandererKillsWeb.KillStreamController.stats","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"message":{"type":"string"},"pubsub_name":{"type":"string"}},"type":"object"}}},"description":"Success"}},"summary":"Get SSE statistics (Debug)","tags":[]}},"/api/v1/kills/stream/test":{"get":{"callbacks":{},"description":"Debug endpoint to test PubSub delivery to SSE connections","operationId":"WandererKillsWeb.KillStreamController.test_broadcast","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"killmail_id":{"type":"integer"},"message":{"type":"string"},"topics":{"items":{"type":"string"},"type":"array"}},"type":"object"}}},"description":"Success"}},"summary":"Test SSE broadcast (Debug)","tags":[]}},"/api/v1/kills/system/{system_id}":{"get":{"callbacks":{},"description":"Fetches killmail data for a specific system with optional time filtering","operationId":"WandererKillsWeb.KillsController.list","parameters":[{"description":"EVE Online system ID","example":30000142,"in":"path","name":"system_id","required":true,"schema":{"type":"integer"}},{"description":"Fetch kills from the last N hours (default: 24)","example":24,"in":"query","name":"since_hours","required":false,"schema":{"type":"integer"}},{"description":"Maximum number of kills to return","example":100,"in":"query","name":"limit","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.KillsResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"},"500":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Server error"}},"summary":"List kills for a system","tags":[]}},"/api/v1/kills/systems":{"post":{"callbacks":{},"description":"Fetches killmail data for multiple systems with optional time filtering","operationId":"WandererKillsWeb.KillsController.bulk","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"properties":{"limit":{"description":"Maximum number of kills to return per system","example":100,"type":"integer"},"since_hours":{"description":"Fetch kills from the last N hours","example":24,"type":"integer"},"system_ids":{"description":"List of EVE Online system IDs","example":[30000142,30000144],"items":{"type":"integer"},"type":"array"}},"required":["system_ids"],"type":"object"}}},"description":"Request body","required":false},"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.BulkKillsResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"},"500":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Server error"}},"summary":"Fetch kills for multiple systems","tags":[]}},"/api/v1/subscriptions":{"get":{"callbacks":{},"description":"Returns a list of all active webhook subscriptions","operationId":"WandererKillsWeb.SubscriptionController.index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.SubscriptionListResponse"}},"description":"Success"}},"summary":"List all subscriptions","tags":[]},"post":{"callbacks":{},"description":"Create a new webhook subscription for killmail notifications","operationId":"WandererKillsWeb.SubscriptionController.create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"properties":{"callback_url":{"description":"HTTP/HTTPS URL to receive webhook notifications","example":"https://example.com/webhook","format":"uri","type":"string"},"character_ids":{"description":"List of EVE Online character IDs","example":[95465499,90379338],"items":{"type":"integer"},"type":"array"},"subscriber_id":{"description":"Unique identifier for the subscriber","example":"user123","type":"string"},"system_ids":{"description":"List of EVE Online system IDs","example":[30000142,30000143],"items":{"type":"integer"},"type":"array"}},"required":["subscriber_id","callback_url"],"type":"object"}}},"description":"Request body","required":false},"responses":{"201":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.SubscriptionResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Invalid parameters"}},"summary":"Create webhook subscription","tags":[]}},"/api/v1/subscriptions/stats":{"get":{"callbacks":{},"description":"Returns aggregate information and statistics about subscriptions","operationId":"WandererKillsWeb.SubscriptionController.stats","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.SubscriptionStatsResponse"}},"description":"Success"}},"summary":"Get subscription statistics","tags":[]}},"/api/v1/subscriptions/{subscriber_id}":{"delete":{"callbacks":{},"description":"Delete all subscriptions for a specific subscriber","operationId":"WandererKillsWeb.SubscriptionController.delete","parameters":[{"description":"Subscriber ID to unsubscribe","example":"user123","in":"path","name":"subscriber_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.SubscriptionDeleteResponse"}},"description":"Success"},"400":{"content":{"application/json":{"schema":"Elixir.WandererKillsWeb.Schemas.Error"}},"description":"Partial failure"}},"summary":"Delete subscriber subscriptions","tags":[]}}},"security":[],"servers":[{"description":"Development server","url":"http://localhost:4004","variables":{}}],"tags":[]}