{"openapi":"3.1.0","info":{"title":"Heartbeat API","version":"1.0.0","description":"Live metrics for every public FiveM server: the resources they run, and adoption ranked by the players each resource reaches."},"servers":[{"url":"https://heartbeat.re/api/v1"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Server":{"type":"object","properties":{"joinId":{"type":"string","examples":["j4r9zmk"]},"name":{"type":"string"},"hostname":{"type":"string"},"owner":{"type":["string","null"]},"game":{"type":"string","examples":["gta5","rdr3"]},"gameBuild":{"type":["string","null"]},"players":{"type":"integer"},"maxPlayers":{"type":"integer"},"peakPlayers":{"type":"integer"},"country":{"type":["string","null"]},"countryName":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"upvotes":{"type":"integer"},"resourceCount":{"type":["integer","null"]},"lastSeen":{"type":"string","format":"date-time"},"connectUrl":{"type":"string"}}},"Resource":{"type":"object","properties":{"name":{"type":"string","examples":["ox_lib"]},"servers":{"type":"integer"},"playerReach":{"type":"integer","description":"Live players across every server running this resource."},"populatedServers":{"type":"integer"},"playersPerServer":{"type":"number"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"docs":{"type":"string"}}}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such record","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/stats":{"get":{"summary":"Network totals","responses":{"200":{"description":"Current network-wide figures"}}}},"/stats/history":{"get":{"summary":"Totals over time","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168}}],"responses":{"200":{"description":"One point per census"}}}},"/servers":{"get":{"summary":"List and filter servers","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"sort","in":"query","schema":{"type":"string","enum":["players","peak","capacity","upvotes","resources"],"default":"players"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Name or owner"},{"name":"country","in":"query","schema":{"type":"string"},"description":"ISO-3166 alpha-2"},{"name":"game","in":"query","schema":{"type":"string","enum":["gta5","rdr3"]}},{"name":"tag","in":"query","schema":{"type":"string"}},{"name":"minPlayers","in":"query","schema":{"type":"integer"}},{"name":"crawledOnly","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"A page of servers"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/servers/{joinId}":{"get":{"summary":"One server","parameters":[{"name":"joinId","in":"path","required":true,"schema":{"type":"string"}},{"name":"history","in":"query","schema":{"type":"boolean"},"description":"Include 48h player history"}],"responses":{"200":{"description":"The server"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/servers/{joinId}/resources":{"get":{"summary":"Resources a server loads","parameters":[{"name":"joinId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Resource list with network-wide adoption"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/resources":{"get":{"summary":"Resource leaderboard","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"sort","in":"query","schema":{"type":"string","enum":["reach","servers","name"],"default":"reach"}},{"name":"q","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of resources"}}}},"/resources/{name}":{"get":{"summary":"One resource","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"history","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"The resource"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/resources/{name}/servers":{"get":{"summary":"Servers running a resource","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":200}}],"responses":{"200":{"description":"Servers, busiest first"}}}},"/regions":{"get":{"summary":"Players by country","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50}}],"responses":{"200":{"description":"Country breakdown"}}}},"/search":{"get":{"summary":"Search servers and resources","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2}},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"maximum":50}}],"responses":{"200":{"description":"Matches in both collections"}}}},"/frameworks":{"get":{"summary":"Framework market share","parameters":[{"name":"resources","in":"query","schema":{"type":"boolean"}},{"name":"resourceLimit","in":"query","schema":{"type":"integer","default":10}}],"responses":{"200":{"description":"Share by servers and players"}}}},"/resources/momentum":{"get":{"summary":"Rising and falling resources, by change in share of crawled servers","parameters":[{"name":"hours","in":"query","schema":{"type":"integer","default":24,"maximum":168}},{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Momentum in both directions"}}}},"/resources/{name}/related":{"get":{"summary":"Co-occurrence and inferred dependencies","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Ships-with, distinctive pairings and inferred dependencies"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/servers/{joinId}/similar":{"get":{"summary":"Servers with similar resource sets","parameters":[{"name":"joinId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":8,"maximum":25}}],"responses":{"200":{"description":"Peers and what they run that this server doesn't"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/watches":{"post":{"summary":"Register a Discord webhook alert (live instances only)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","target","webhookUrl"],"properties":{"kind":{"type":"string","enum":["server","resource"]},"target":{"type":"string"},"webhookUrl":{"type":"string","description":"https Discord webhook only"},"condition":{"type":"string","enum":["above","below","offline","resource_change","any"]},"threshold":{"type":"integer"},"label":{"type":"string"}}}}}},"responses":{"201":{"description":"Watch registered"}}},"get":{"summary":"List watches","responses":{"200":{"description":"Registered watches"}}},"delete":{"summary":"Delete a watch","responses":{"200":{"description":"Deleted"}}}},"/keys":{"post":{"summary":"Create an API key","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":2,"maxLength":64}}}}}},"responses":{"201":{"description":"The key, shown once"}}},"get":{"summary":"Inspect the key you send","responses":{"200":{"description":"Key metadata"}}}}}}