Heartbeat.re
186,308

Heartbeat API · v1

Every FiveM server and resource, over HTTP

The same data behind this site, as JSON: 34,951 servers, 1,254,808 distinct resources, and the adoption figures ranking them. Built for Discord bots, server dashboards and anyone deciding which script to ship.

Quickstart

Every endpoint lives under https://heartbeat.re/api/v1 and needs a key. Here is the smallest useful call.

curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  https://heartbeat.re/api/v1/stats

Authentication

Send your key as a bearer token. An X-API-Key header works identically if that suits your client better. A ?api_key= query parameter is accepted as a last resort for clients that cannot set headers, avoid it where you can, since query strings land in access logs and browser history.

Authorization: Bearer hb_live_eyJ2IjoxLCJpZCI6…

Rate limits

Free keys allow 60 requests a minute. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 adds Retry-After. Counting is per-instance and best-effort rather than globally exact, treat the published number as the contract, not the enforcement.

Response shape

Results are always under data. Lists add meta for paging. Every response carries a snapshot block telling you how fresh the figures are and whether the instance is ingesting live or serving a frozen copy, poll-driven consumers should read it rather than assume.

{
  "data": [ … ],
  "meta":     { "total": 36958, "limit": 50, "offset": 0, "hasMore": true },
  "snapshot": { "live": false, "capturedAt": "2026-08-12T19:14:02.000Z" }
}

Endpoints

Fifteen endpoints covering raw data, derived analysis and alerting. All of them accept CORS from any origin.

GET

/stats

Network totals: players, servers, capacity, crawl coverage, and 24-hour change. The cheapest call, and the one most bots want.

curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  https://heartbeat.re/api/v1/stats

Response

{
  "data": {
    "players": 186308,
    "servers": 34951,
    "populatedServers": 8599,
    "slotsFilledPercent": 5.93,
    "distinctResources": 1254808,
    "coverage": { "serversCrawled": 46798, "serversTotal": 34951, "percent": 36.2 },
    "change": { "playersPercent": 0.7, "serversPercent": 0.1 }
  }
}
GET

/stats/history

Network totals over time, one point per census (roughly every five minutes).

ParameterTypeDescription
hoursintegerWindow to return, 1–168.(default 24)
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/stats/history?hours=48"
GET

/servers

List and filter servers. Combine filters freely, this is how you answer questions like 'the busiest German roleplay servers running more than 100 resources'.

ParameterTypeDescription
limitintegerRows to return, 1–200.(default 50)
offsetintegerRows to skip, for paging.(default 0)
sortstringplayers · peak · capacity · upvotes · resources(default players)
qstringMatch server name or owner.
countrystringISO-3166 alpha-2, e.g. DE.
gamestringgta5 or rdr3.
tagstringExact tag match, e.g. roleplay.
minPlayersintegerOnly servers at or above this player count.
crawledOnlybooleanOnly servers whose resources are indexed.
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/servers?country=DE&tag=roleplay&minPlayers=50&limit=10"

Response

{
  "data": [
    {
      "joinId": "j4r9zmk",
      "name": "KROWN",
      "players": 1846,
      "maxPlayers": 2048,
      "country": "TH",
      "countryName": "Thailand",
      "tags": ["roleplay", "economy"],
      "resourceCount": 218,
      "connectUrl": "https://cfx.re/join/j4r9zmk"
    }
  ],
  "meta": { "total": 412, "limit": 10, "offset": 0, "hasMore": true }
}
GET

/servers/{joinId}

A single server by its Cfx join id, the code in a cfx.re/join link.

ParameterTypeDescription
historybooleanInclude 48 hours of player counts.
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/servers/j4r9zmk?history=true"
GET

/servers/{joinId}/resources

Every resource a server loads, each annotated with how widely it is used across the network, so you can tell its bespoke code from the community standards.

curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  https://heartbeat.re/api/v1/servers/j4r9zmk/resources

Response

{
  "data": {
    "joinId": "j4r9zmk",
    "count": 218,
    "resources": [
      { "name": "ox_lib",   "servers": 3299, "playerReach": 108736, "playersPerServer": 33 },
      { "name": "sd-mdt",   "servers": 12,   "playerReach": 840,    "playersPerServer": 70 }
    ]
  }
}
GET

/resources

The resource leaderboard. Ranked by player reach, total live players across every server running it, rather than raw installs, because a script on 400 empty servers reaches nobody.

ParameterTypeDescription
limitintegerRows to return, 1–200.(default 50)
offsetintegerRows to skip, for paging.(default 0)
sortstringreach · servers · name(default reach)
qstringMatch the resource name.
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/resources?sort=reach&limit=5"

Response

{
  "data": [
    { "name": "hardcap",   "servers": 7123, "playerReach": 134810, "populatedServers": 4957 },
    { "name": "oxmysql",   "servers": 6902, "playerReach": 129440, "populatedServers": 4801 }
  ],
  "meta": { "total": 417858, "limit": 5, "offset": 0, "hasMore": true }
}
GET

/resources/{name}

One resource, with optional weekly adoption history. URL-encode names containing slashes or spaces.

ParameterTypeDescription
historybooleanInclude 7 days of adoption points.
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/resources/ox_lib?history=true"
GET

/resources/{name}/servers

Servers known to run a resource, busiest first. Useful for 'who actually uses this script, and how big are they?'

ParameterTypeDescription
limitintegerServers to return, 1–200.(default 50)
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/resources/ox_lib/servers?limit=20"
GET

/regions

Players and servers grouped by the region each server advertises, with each country's share of the network.

ParameterTypeDescription
limitintegerCountries to return.(default 50)
curl -H "Authorization: Bearer $HEARTBEAT_KEY" \
  "https://heartbeat.re/api/v1/regions?limit=10"
GET

/frameworks

Framework market share across crawled servers, ESX, QBCore, Qbox, vRP and standalone, with players-per-server. Pass resources=true for each framework's own top-resource leaderboard, which is a very different list from the global one.

ParameterTypeDescription
resourcesbooleanInclude each framework's top resources.
resourceLimitintegerResources per framework, 1-50.(default 10)
curl -H "Authorization: Bearer $HEARTBEAT_KEY"   "https://heartbeat.re/api/v1/frameworks?resources=true"

Response

{
  "data": [
    { "id": "esx",  "label": "ESX",  "servers": 4897, "players": 46797, "playersPerServer": 9.6 },
    { "id": "vrp",  "label": "vRP",  "servers": 1049, "players": 25959, "playersPerServer": 24.7 }
  ]
}
GET

/resources/momentum

Rising and falling resources. Ranked by change in share of crawled servers, not raw install count, while the crawler is still sweeping, absolute counts climb for everything at once, so a raw-count ranking would measure our coverage rather than actual adoption.

ParameterTypeDescription
hoursintegerWindow, 1-168.(default 24)
limitintegerRows per direction.(default 20)
curl -H "Authorization: Bearer $HEARTBEAT_KEY"   "https://heartbeat.re/api/v1/resources/momentum?hours=48"
GET

/servers/{joinId}/similar

Servers with the most overlapping resource sets (Jaccard similarity), plus the resources those peers run that this server doesn't, the practical version of 'what is everyone like me installing?'

ParameterTypeDescription
limitintegerPeers to return, 1-25.(default 8)
curl -H "Authorization: Bearer $HEARTBEAT_KEY"   https://heartbeat.re/api/v1/servers/j4r9zmk/similar
POST

/watches

Register a Discord webhook alert on a server or resource. Only https Discord webhook URLs are accepted, and alerts fire on threshold crossings with a 15-minute cooldown. Requires an instance running the ingest worker, a read-only snapshot refuses rather than accepting a watch it can never deliver.

curl -X POST https://heartbeat.re/api/v1/watches   -H "Authorization: Bearer $HEARTBEAT_KEY"   -H "Content-Type: application/json"   -d '{
    "kind": "server",
    "target": "j4r9zmk",
    "condition": "below",
    "threshold": 100,
    "webhookUrl": "https://discord.com/api/webhooks/…"
  }'
POST

/keys

Create a key programmatically. No authentication required, limited to 5 per hour per IP. The key is returned once and never again.

curl -X POST https://heartbeat.re/api/v1/keys \
  -H "Content-Type: application/json" \
  -d '{"name":"my-discord-bot"}'

Response

{
  "data": {
    "key": "hb_live_eyJ2IjoxLCJpZCI6…",
    "keyId": "a1b2c3d4e5f6",
    "tier": "free",
    "rateLimitPerMinute": 60,
    "notice": "Store this key now, it is not recoverable and is shown only once."
  }
}

Errors

Failures return a matching HTTP status and a stable error.code, branch on the code, not the message, which may be reworded.

StatusCodeMeaning
400bad_requestA parameter is missing or malformed.
401missing_keyNo key was sent.
401invalid_keyThe key failed signature verification.
403revoked_keyThe key was valid but has been revoked.
404not_foundNo server or resource by that identifier.
429rate_limitedToo many requests. See Retry-After.
500server_errorSomething broke on our side.
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit of 60 requests/minute exceeded.",
    "docs": "https://heartbeat.re/docs#rate_limited"
  }
}

What the numbers do and don't mean

  • Player counts are self-reported. They come from each server's own listing. Nothing here independently verifies them.
  • Resource coverage is partial and growing. The bulk server list omits resource data, so it is gathered one server at a time, most-populated first. /stats reports exact coverage, read it before treating an install count as complete.
  • Resource rankings are already aggregates. A resource's servers and playerReach cover the whole crawled network, but /resources/{name}/servers lists only the busiest installs.
  • Check the snapshot block. When snapshot.live is false the instance is serving a frozen copy, and capturedAt tells you from when.

Data comes from the public Cfx.re server list. Heartbeat is not affiliated with Cfx.re or Rockstar Games.