# Discovery API v1 The API stores public room advertisements as short-lived leases and coordinates direct UDP hole punching. It does not proxy or relay gameplay traffic. straywild continues to connect to the returned host and UDP port through ENet. All request and response bodies use `application/json`. Production clients must use HTTPS. ## `GET /health` Returns service status, package version, configured build revision, and the number of active, unexpired room leases. Deployments should set `straywild_DISCOVERY_BUILD_REVISION` to the exact Git commit they are running. The package version follows the coordinated straywild release tag. ## `GET /v1/rooms` Lists active rooms. Optional exact-match filters: - `game_version` - `protocol_version` The response contains `rooms` and the server's `ttl_seconds`. ## `POST /v1/rooms` Creates a room lease. The service derives the advertised address from the connection rather than trusting an address supplied by the game client. ```json { "room_name": "Pond Friends", "port": 7777, "current_players": 0, "max_players": 8, "game_version": "0.18.1-alpha", "protocol_version": 11 } ``` `current_players` may be zero for an empty dedicated server. A player-hosted room normally includes its host in this count. The `201` response includes the room, a secret `lease_token`, and an endpoint verification token. The host sends the verification token to the UDP rendezvous from its bound ENet socket. Rooms are excluded from public listings until the service observes that endpoint. The service applies configured global and per-observed-address active-room limits. Exceeding one returns `429 room_limit`; expired leases stop counting automatically. The discovery release accepts room advertisements only from the matching straywild game release. A mismatched `game_version` returns `409 game_version_mismatch` with `required_game_version`; the room is not created or updated. ## `PUT /v1/rooms/{room_id}` Renews and updates a room lease. Send the complete room payload and: ```text Authorization: Bearer ``` Hosts should heartbeat well before the configured TTL, initially every 15 seconds for a 45-second lease. A missing heartbeat causes automatic removal without requiring a disconnect callback. ## `DELETE /v1/rooms/{room_id}` Removes a room immediately. Requires the same bearer token. A clean host shutdown should call this, but TTL expiry remains authoritative for crashes and lost connectivity. ## `POST /v1/rooms/{room_id}/join-attempts` Creates a short-lived traversal token for a public room. The joining game sends that token to the UDP rendezvous from the same ENet socket used for the gameplay connection. ## `GET /v1/rooms/{room_id}/join-attempts` Requires the room lease bearer token. It consumes observed joining endpoints so the host can send same-socket UDP punch packets before ENet retries its connection. ## Live friend presence and invitations These endpoints are an ephemeral capability channel, not an account or social-graph service. The server does not receive player identity fingerprints or a complete friend list, writes nothing to a database, and discards presence and invitations after short timeouts. `POST /v1/presence` publishes or removes the caller's status under one or more secret write capabilities. `POST /v1/presence/query` reads the corresponding hashed channels. A published room is returned only while it remains a verified, version-compatible public room. `POST /v1/invitations/poll` marks the supplied capability inboxes as currently reachable and consumes any live invitations. `POST /v1/invitations` sends a public-room invitation to one inbox. The send fails with `409 friend_offline` and `This person needs to be online to do this.` unless that inbox was polled recently. There is no offline delivery. All four requests include the normal `game_version` and `protocol_version`. Capability values are 64 lowercase hexadecimal characters and must be exchanged by the games during an authenticated, live straywild session. ## Error shape ```json { "error": { "code": "invalid_room", "message": "port must be between 1 and 65535" } } ``` ## Trust boundary - The UDP rendezvous observation is authoritative for a room's public address and port. - `X-Forwarded-For` is honored only when the immediate peer belongs to an explicitly configured trusted proxy CIDR. - Lease tokens authorize update and deletion but are never included in public listings. - Friend capability channels are short-lived and reveal neither identity fingerprints nor a full social graph to the service. - The service is an ephemeral directory, not a source of gameplay or friendship authority.