Your game backend decides who can hear whom. Wave delivers the voice: keys, access control, WebRTC signaling and STUN. No registration โ everything is identified by a single API key.
No registration required. Paid plans are activated after payment (automated checkout is coming soon โ until then an operator activates your order). The Free plan is active immediately.
1050_Hero). This is done by your backend team โ the client cannot do it itself./voice with the key and the exact same player ID. Wave accepts it only if your backend announced this player.voice:peer-on. When they move apart โ voice:peer-off.voice:signal. The relay works only between allowed pairs.| Method | Endpoint | Description |
|---|---|---|
| GET | /api/voice/plans | List available plans and prices |
| POST | /api/voice/order | Issue a key. Body: { plan, serverIp, label }. Returns the key, the secret (once), expiry and payment status |
| GET | /api/voice/key/:id/status | Key status: active / expired, online players, traffic stats |
| GET | /voice | Ready-made voice page for the launcher: ?key=...&player=...&auto=1 |
The fastest integration: point a WebView2 / iframe / browser window at the ready-made voice page. It handles the microphone, WebRTC, nearby list and text chat for you.
| Parameter | Required | Description |
|---|---|---|
key | yes | Your API key (wg-...) |
player | yes | Player ID โ exactly the same string your game backend announces (URL-encode it) |
auto | no | 1 โ try to enable the microphone automatically after the first user gesture |
/voiceConnection handshake: auth = { role: "player", key: "wg-...", playerId: "1050_Hero" }. The player is accepted only while the game backend keeps the player announced.
| Direction | Event | Description |
|---|---|---|
| YOU โ | voice:peer-on { playerId, name } | A player entered your hearing range โ start a WebRTC call |
| YOU โ | voice:peer-off { playerId } | A player left the range โ hang up |
| YOU โ | voice:peer-name { playerId, name } | Display name update for a connected peer |
| YOU โ | voice:signal { to, data } | WebRTC signaling (offer / answer / ICE) to an allowed peer |
| YOU โ | voice:signal { from, data } | Incoming signaling from an allowed peer |
| YOU โ | chat { text } | Text message to everyone currently in range (max 500 chars) |
| YOU โ | chat { from, text } | Incoming proximity text message |
| YOU โ | voice:error { error } | Key expired / character left the game / kicked |
Full reference implementation of the call logic. The deterministic initiator rule (myId < peerId creates the offer) prevents double offers when both players appear in range at the same moment.
| Error (connect_error / voice:error) | Meaning |
|---|---|
| ERR | Invalid key โ the key does not exist |
| ERR | Key expired / Key revoked โ renew or replace the key |
| ERR | Key not paid yet โ the order is waiting for payment |
| ERR | Player not announced by game server โ the character is not in the game |
| ERR | Key player limit โ the CCU cap of the plan is reached |
| Limit | Value |
|---|---|
| Signaling messages | 30 / second per player |
| Chat messages | 5 / second, max 500 characters |
| Player ID format | AโZ aโz 0โ9 _ -, length 2โ80 |
| Online players | per plan: 30 / 50 / 100 / 500 / 1000 |
NuGet: Microsoft.Web.WebView2. The key is public and safe to ship in the launcher config. The secret must never be here.
Prefer your own infrastructure? We will deploy a dedicated Wave Voice instance on your own VPS and integrate it with your game โ you own the server, the keys and the data. Or let us run it for you.
Player not announced by game server.<characterId>_<characterName>. The launcher must build exactly the same string.