Quickstart
From an empty account to a player talking in a channel. About ten minutes, no credit card.
1. Create a project#
- Sign up at /console/ and confirm your e-mail.
- Create an organisation (your studio) if you did not name one at sign-up.
- New project → name, plan, home region. Start on Free: 50 concurrent participants on the shared EU pool (200 during the launch offer), every SDK, no card.
The console shows the SDK key (aurx_…) exactly once. Store it in your backend's secret store. It must never ship in a game build — anyone holding it can mint tokens for your project. You can rotate it at any time.
Also note the cell endpoint under Keys & SDK, e.g. https://eu-central.cell.aurix.run. Your backend mints tokens there; browser clients use it as apiUrl.
2. Mint a token for a player#
When a player enters a match, your game server asks the cell for a session token. The token is short-lived and bound to the player id you pass.
curl -X POST "$AURIX_CELL/v1/tokens" \
-H "x-api-key: $AURIX_API_KEY" \
-H "content-type: application/json" \
-d '{
"external_id": "player-42",
"display_name": "Ann",
"channels": [
{ "ad_hoc": { "name": "match-7", "channel_type": "positional" } },
{ "ad_hoc": { "name": "match-7-red", "channel_type": "team" } }
]
}'{
"token": "eyJ…",
"user_id": "a3c1…",
"expires_at": "2026-10-21T20:15:00Z",
"channels": [
{ "channel_id": "6f0d…", "join": true, "speak": true, "receive": true, "moderate": false, "priority": false,
"ad_hoc": { "name": "match-7", "channel_type": "positional" } },
{ "channel_id": "9b21…", "join": true, "speak": true, "receive": true, "moderate": false, "priority": false,
"ad_hoc": { "name": "match-7-red", "channel_type": "team" } }
],
"endpoint": { "region": "eu_central", "node_id": "…", "ws_url": "wss://eu-central.cell.aurix.run/ws", "probe_url": "https://…", "nodes": 1, "load_factor": 0.1 },
"location_source": "none"
}Hand token, endpoint.ws_url and the channel ids to the client. If the project runs in several regions, mint through the control plane instead — POST /v1/projects/{id}/tokens on the console host with an organisation API token picks the nearest region for the player and returns the same shape. Every field is described in Player tokens. With Node, Python, Go or C# you can use the server SDKs instead of raw HTTP — see the token server examples.
3. Connect from the game#
UAurixVoiceSubsystem* Voice = GetGameInstance()->GetSubsystem<UAurixVoiceSubsystem>();
FAurixVoiceSettings S; S.WebSocketUrl = Endpoint.WsUrl; S.Token = Token;
Voice->OnSessionReady.AddDynamic(this, &AMyPC::OnVoiceReady); // join once the session is up
Voice->Connect(S);
// OnVoiceReady:
FGuid Ch; UAurixVoiceSubsystem::ParseUuid(PositionalChannelId, Ch);
int64 Req; Voice->JoinChannel(Ch, TEXT(""), Req);
Voice->StartCapture();var voice = GetComponent<AurixVoiceBehaviour>(); // microphone, playback and PTT handled for you
voice.WebSocketUrl = endpoint.ws_url; voice.Token = token;
voice.ChannelId = channels[0].channel_id;
await voice.Connect();var voice := AurixVoiceClient.new()
add_child(voice)
voice.session_ready.connect(func(_s): voice.join_channel(channels[0].channel_id))
voice.connect_to_server(endpoint.ws_url, token)import { AurixClient } from '@aurix/web-sdk';
const voice = new AurixClient({ apiUrl: 'https://eu-central.cell.aurix.run', wsUrl: endpoint.ws_url, token });
await voice.connect();
await voice.joinChannel(channels[0].channel_id);Positional channels need the player's position a few times a second (updatePosition / UpdateOwnPosition / update_transforms depending on the SDK); team channels need nothing else. Capture devices, push-to-talk, VAD and mute are covered per engine in the integration guides.
4. Watch it#
Open the project's Overview in the console: participants, participant-minutes and traffic appear within five minutes — the running hour is metered live and becomes final when it ends. Usage has the per-hour breakdown and a CSV export.
Next#
- Concepts — what a cell, a channel and a participant are, and how limits are counted.
- Spending limit — for paid plans, what happens at 100 / 105 / 110 / 120 %.
- Webhooks — get limit and node events into your own systems.
What you just built#
game client ──(1) login──▶ your backend ──(2) POST /v1/tokens, x-api-key──▶ cell
▲ │
└──(3) token + endpoint────┘
game client ──(4) QUIC / WebTransport / WebRTC / WS──▶ media node (audio never touches your backend)Your backend is the only place the SDK key lives. The token carries the endpoint, the channels and the grants, so a client build never contains a server address or a secret, and moving between regions, cells or self-hosted nodes is a change on the token server only.
Common first-run problems#
| Symptom | Cause | Fix |
|---|---|---|
401 from /v1/tokens | key pasted with whitespace, or a rotated key | copy again from Keys & SDK; rotation invalidates the old key immediately |
| token works, client never connects | corporate / campus network blocks UDP | the SDK falls back to WebRTC over TURN, then WebSocket; check the transport in the quality panel of the rooms demo |
players hear nothing in a positional channel | no update_position calls, so everyone is at the origin at far_distance | send positions ~10 Hz; test with team first |
connect refused with QUOTA_EXCEEDED | Free (50, 200 during the launch offer) / Indie (300) concurrency cap, or spending ladder step 4 | wait for someone to leave, upgrade, or raise the limit |
| second tab joins as the same player and kicks the first | same external_id | one voice user per id; use a device suffix for multi-device testing |
| no usage in Overview | first metering pass is still pending | rows appear within 5 minutes and rewrite until the hour closes |
Before you ship#
- Tokens live 60 minutes: wire the SDK's refresh hook (
refreshToken/TokenRefresher/SetToken/set_token) to your token endpoint so reconnects after an hour just work. - Set a spending limit before announcing a launch date; autoscale respects it.
- Give moderators
moderateand your event hostspriority; everything else stays default. - Put the webhook endpoint for
spend_cap.stepin your ops chat. - Read What you pay for once — it is short and it is the whole invoice.