Discovery Overview

What Discovery is: apps, public IDs, heartbeat tokens, token scopes, and how the service behaves.

Discovery gives your players a live server list. Game clients read a public, unauthenticated list; your servers get onto it in one of two ways, depending on where they are hosted. Servers hosted on PingCore connect automatically through a fleet, with no code on your side. Servers hosted anywhere else send an HTTP heartbeat every 30 seconds (see Sending Heartbeats). Discovery is a standalone product: the heartbeat path works even if you host nothing else on PingCore.

You manage Discovery in your workspace. In the sidebar, click Discovery. Viewing requires the discovery.view permission; creating apps, changing settings, and issuing tokens require discovery.manage.

Discovery apps

A Discovery app is your tenant on the Discovery service. One app has one server list, its own heartbeat tokens, and its own settings. Create one per game (or per environment, if you want production and staging fully separated).

To create an app, click Add App, enter an App Name, choose a Registration mode (see below), and choose a Verification mode (see Reachability Verification). You can change both later.

Each app also has:

  • Linked Game (optional): provenance only. Linking a game does not change how heartbeats or the server list behave.

  • App enabled switch: disabling rejects new heartbeats and stops serving the server list.

  • Concurrent Server Limit: how many servers may be live at once. The limit exists to stop a leaked token from flooding the service with fake servers; it is not a cap on normal use. Once reached, existing servers keep reporting normally and only brand-new ones are refused. Contact support to raise it.

Choosing a registration mode

The Registration setting is the app's trust model for heartbeat tokens. It decides whether the token itself must stay secret.

  • Private (the default): your servers are machines you operate, and the heartbeat token is a secret they hold. Keep tokens on your servers and backends, never in a game client. Anyone holding a token can register servers on your list, so token secrecy is what protects the list. If you also run No verification, treat that secrecy seriously: a leaked token would let anyone list arbitrary endpoints to your players.

  • Open: for client-hosted games, where the shipped game itself runs the server (listen servers, player-hosted sessions). The token has to ship inside your game binary, so it is public by design; anyone can extract it, and that is fine. This is the model Steam uses for anonymous game server registration, and the old Quake and Source master servers before it. Instead of token secrecy, the list is protected by two enforced mechanisms:

    • Mandatory endpoint verification: the Verification setting is locked to UDP echo challenge. A server only reaches the list once it proves it controls the endpoint it advertises. See Reachability Verification.

    • A per-source-IP server limit: each source IP may register a bounded number of servers on the app (default 10, raisable via Max servers per source IP on the app page). See Sending Heartbeats.

Switching an existing app to Open locks its verification mode to the UDP echo challenge automatically. Like every app setting, the change reaches the Discovery service within about a minute.

Public ID vs tokens

The two credentials play different roles, so it matters which one goes where.

  • The public ID (prefix dscp_) identifies your app in the client-facing server list URL: /v1/apps/{publicId}/servers. It is public by design and safe to ship inside your game client. It grants no write access to anything.

  • A heartbeat token (prefix dsc_) is a bearer credential presented to the service: Authorization: Bearer dsc_.... On a private app it is a secret and belongs on your servers and backends, never in a game client. On an open app it ships inside the game binary and is not a secret (see Choosing a registration mode above); it still routes heartbeats to the right app and can still be rotated.

The app page shows the Public Server List URL with a copy button. That URL also tells you the service base URL used by every endpoint in these docs (for example https://discovery.pingcore.io).

Token scopes

Every token has a scope, chosen when you issue it. On the app page, under Heartbeat Tokens, enter a label, pick a scope, and click Issue Token. The token is shown exactly once: copy it immediately, every later view is masked.

  • Heartbeat: ingest. Sending heartbeats, delisting servers, verifying reservations, and reading fleet state. This is what your game servers use.

  • Allocate: matchmaking. Allocations, tickets, joinable-session records, reservations made from your backend, and the desired-capacity hint. This is what your matchmaker backend uses.

  • Both: full access.

Endpoints by credential

  • No credential (safe to call from a shipped client): the public server list GET /v1/apps/{publicId}/servers, the location list GET /v1/locations, anonymous player-token issuance POST /v1/apps/{publicId}/player-tokens, and GET /openapi.json.

  • Heartbeat scope: POST /v1/heartbeat, delisting, GET /v1/apps/{publicId}/fleet-state, GET /v1/apps/{publicId}/matchmaking-stats, and GET /v1/reservations/verify/{reservationId}.

  • Allocate scope: POST /v1/apps/{publicId}/allocations and its GET/DELETE, PUT /v1/apps/{publicId}/desired-capacity, and the joinable-session record on a server, POST, GET, and DELETE /v1/apps/{publicId}/servers/{serverId}/joinable-session.

  • Allocate scope or a player token: the reservation routes (reserve on a server, quick-join, GET/DELETE a reservation) and the ticket routes (POST /v1/apps/{publicId}/tickets, GET/DELETE /v1/apps/{publicId}/tickets/{ticketId}). A player token acts within the player bounds described on Choosing How Players Connect.

  • Any active token of the app on a private app, Allocate on an open-registration app: the matchmaking inspector, GET /v1/apps/{publicId}/matchmaking/queues, .../matchmaking/tickets, and .../matchmaking/matches. An open app's heartbeat token ships inside the game binary, so it cannot read the queue.

For external heartbeat integrations, issue one token per environment so you can revoke a leaked token without taking everything offline. Servers hosted on PingCore do not choose a token: their fleet agents use the app's oldest active ingest token. Revoking a token disconnects any agent still using it within about a minute; the agents pick up the replacement token automatically within a few minutes, after a brief reconnection gap. No restart is needed. A token used against the wrong surface gets a 403 with a message naming the missing scope.

Status codes

Discovery keeps its error responses distinct so you can diagnose problems from the status code alone:

  • 401: the bearer token is missing or unknown.

  • 403: the token is known but not usable here. It was revoked, the app is disabled, or the token lacks the required scope.

  • 503: the service is degraded (it is starting up and has not loaded its registry yet). Retry shortly; the token itself may be valid.

Treat 401 and 403 as configuration problems on your side; treat 503 as transient.

The revocation window

Revoking a token, disabling an app, or changing app settings takes effect on the Discovery service within about a minute. The service pulls its registry from the platform on a sync interval rather than checking every request, which keeps your heartbeats independent of platform availability. The delay is expected behaviour. Plan token rotation with it in mind: issue the new token, roll it out to your external integrations, then revoke the old one. For servers hosted on PingCore, fleet agents use the app's oldest active ingest token; after you revoke the old token they reconnect with the new one automatically within a few minutes, with a brief reconnection gap in between. No restart is needed. While the agents reconnect, a fleet briefly reads as under capacity, so the autoscaler may add servers transiently; if that matters, rotate during a low-traffic window.

What Discovery stores

Only live state. A server exists in Discovery for as long as it keeps heartbeating (plus a 90 second grace window). Discovery keeps no analytics, and the only history is a diagnostic list of the last 50 matchmaking matches per app, which expires after 24 hours. If your servers stop reporting, the list empties on its own and there is nothing to clean up.

API reference

The service publishes its full OpenAPI 3.1 document at GET /openapi.json on the same base URL as every other endpoint (for example https://discovery.pingcore.io/openapi.json). It is public, carries no secrets, and loads into Swagger UI, Postman, or a code generator directly. The same document powers the API Reference section of this portal. The pages in this category explain the workflows; the spec is the field-by-field contract for every endpoint, parameter, and response shape.

Next steps