SimTX API/Game tickets: Difference between revisions
Clanker moved page SimTX API/Game tickets to SimTX API v24/Game tickets: Archive the v24 protocol reference Tag: New redirect |
Reconcile with the frozen v25 schema: default antenna and rig |
||
| (2 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
# | {{SimTX API navigation}} | ||
A '''game ticket''' is a short-lived, single-use credential that a client presents to a game server in the [[SimTX API/Packets/ClientHello|ClientHello]]. Tickets keep reusable credentials away from game servers: the server only ever sees a ticket that is worthless sixty seconds later. A ticket can also be '''bound to a station''', which is how a receiver or transmitter session gets the right to use one of the account's persistent [[SimTX API/Stations|stations]]. | |||
Anonymous ad-hoc receivers and anonymous control connections do not need a ticket. | |||
== Request == | |||
<code>POST /api/v1/game-tickets</code> | |||
Requires a bearer credential. Rate limit: 120 requests per minute per IP address. | |||
<syntaxhighlight lang="json"> | |||
{ | |||
"serverId": "argon", | |||
"role": "tx-audio", | |||
"stationId": "3f2504e0-4f89-41d3-9a0c-0305e82c3301", | |||
"antennaId": "9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f" | |||
} | |||
</syntaxhighlight> | |||
{| class="wikitable" | |||
! Field !! Type !! Required !! Description | |||
|- | |||
| <code>serverId</code> || string || Yes || A <code>serverId</code> from the [[SimTX API/Server directory|server directory]]. | |||
|- | |||
| <code>role</code> || string || Yes || The protocol role the ticket will be used for. See [[#Roles|Roles]]. | |||
|- | |||
| <code>stationId</code> || string (UUID) || No || Bind the ticket to a persistent station. Transmitter roles need a station the account owns; <code>receiver</code> also accepts another account's PUBLIC station. | |||
|- | |||
| <code>antennaId</code> || string (UUID) || No || The station's antenna. Default: its first antenna by ordinal. | |||
|- | |||
| <code>rigId</code> || string (UUID) || No || The station's rig. Default: its first rig by ordinal, or none when the station has no rigs. | |||
|} | |||
=== Roles === | |||
The ticket is bound to one role. The role string in the request must correspond to the role sent in the hello. | |||
{| class="wikitable" | |||
! Ticket <code>role</code> !! Hello <code>role</code> !! Permission required to obtain the ticket !! Station binding | |||
|- | |||
| <code>receiver</code> || <code>ROLE_RECEIVER</code> (1) || None || Optional | |||
|- | |||
| <code>tx-audio</code> || <code>ROLE_TX_AUDIO</code> (2) || <code>game.transmit</code> || Optional; transmitting through a station needs it | |||
|- | |||
| <code>tx-generated</code> || <code>ROLE_TX_GENERATED</code> (3) || <code>game.transmit</code> || Optional; transmitting through a station needs it | |||
|- | |||
| <code>control</code> || <code>ROLE_CONTROL</code> (4) || <code>catalog.publish</code> || Not allowed | |||
|- | |||
| <code>moderation</code> || <code>ROLE_MODERATION</code> (5) || <code>moderation.manage</code> || Not allowed | |||
|} | |||
An authenticated <code>control</code> connection is only needed to publish to or delete from the [[SimTX API/Extension catalog protocol|extension catalog]] and to monitor one's own transmitters. Reading the station list, maps, ephemerides, passes and the catalog works anonymously. | |||
The permission check uses the intersection of the credential's scopes and the account's effective permissions on that server. A credential created with scope <code>catalog.publish</code> cannot obtain a <code>tx-audio</code> ticket, even if the account itself may transmit. | |||
== Response == | |||
<code>201 Created</code>: | |||
<syntaxhighlight lang="json"> | |||
{ | |||
"ticket": "stx_gt1_7e21...", | |||
"expiresAt": "2026-10-24T12:01:00Z", | |||
"station": { | |||
"stationId": "3f2504e0-4f89-41d3-9a0c-0305e82c3301", | |||
"antennaId": "9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f", | |||
"rigId": "c41d7a52-0e3b-4f6a-9c8d-1b2a3c4d5e6f", | |||
"revision": 7, | |||
"access": "OWNER" | |||
} | |||
} | |||
</syntaxhighlight> | |||
{| class="wikitable" | |||
! Field !! Type !! Description | |||
|- | |||
| <code>ticket</code> || string || The ticket. Place it in <code>ClientHello.credential</code> with <code>auth = AUTH_KIND_GAME_TICKET</code>. | |||
|- | |||
| <code>expiresAt</code> || string || Expiry time, 60 seconds after issue. | |||
|- | |||
| <code>station</code> || object || Only for station-bound tickets: what was bound. | |||
|- | |||
| <code>station.stationId</code> || string || The station. | |||
|- | |||
| <code>station.antennaId</code> || string || The bound antenna, also when the request named none. | |||
|- | |||
| <code>station.rigId</code> || string || The bound rig. Omitted when none is bound. | |||
|- | |||
| <code>station.revision</code> || integer || The station's revision when the ticket was minted. | |||
|- | |||
| <code>station.access</code> || string || <code>OWNER</code> (transmit and receive) or <code>LISTENER</code> (receive only, on another account's PUBLIC station). | |||
|} | |||
== Station-bound sessions == | |||
A session started with a station-bound ticket must send a [[SimTX API/Data types#StationBinding|StationBinding]] for the same station, antenna and rig in its [[SimTX API/Packets/ReceiverStart|ReceiverStart]] or [[SimTX API/Packets/TransmitterStart|TransmitterStart]]. Copy the ids from the <code>station</code> object; an empty antenna or rig id in the binding selects the station's first antenna or rig, or the one the ticket was minted for. A binding that does not match, or an ad-hoc site sent with a station-bound ticket, is refused with <code>ERROR_CODE_FORBIDDEN</code>. See [[SimTX API/Stations#Binding a session|Binding a session]]. | |||
The station snapshot the game server uses is taken when the ticket is consumed. A ticket minted for a station without rigs gets the station's first rig if one was added before the ticket was used. | |||
== Rules == | |||
* A ticket is valid for '''60 seconds''' and can be used '''once'''. | |||
* It is bound to the requested <code>serverId</code> and <code>role</code>, and to the station if one was given. Presenting it to another server or with another role fails with <code>HELLO_STATUS_CREDENTIAL_INVALID</code>. | |||
* Fetch a new ticket for every connection, including every reconnect. Do not fetch tickets in advance. | |||
* Station-bound tickets are issued only for servers that advertise the feature <code>stations.v1</code>. | |||
* A ticket does not carry the user's identity in readable form. The server resolves it and returns the account in the [[SimTX API/Packets/ServerHello|ServerHello]]. | |||
== Errors == | |||
{| class="wikitable" | |||
! HTTP !! <code>code</code> !! Cause | |||
|- | |||
| 400 || <code>ticket_request_invalid</code> || The <code>message</code> distinguishes: ''serverId and role are required''; ''unknown protocol role''; ''unknown, disabled, or offline server''; ''credential is not authorized for the requested protocol role'' (the credential's scopes or the account's permissions lack the role's permission). With station fields: ''antennaId and rigId need a stationId''; ''station binding is only available for transmitter and receiver roles''. | |||
|- | |||
| 404 || <code>station_not_found</code> || Unknown station. | |||
|- | |||
| 403 || <code>station_forbidden</code> || A transmitter role on a station the account does not own, or <code>receiver</code> on another account's UNLISTED station. | |||
|- | |||
| 409 || <code>station_inactive</code> || The station is deleted or deorbited. | |||
|- | |||
| 409 || <code>station_binding_unsupported</code> || That server does not advertise the feature <code>stations.v1</code>. | |||
|- | |||
| 400 || <code>antenna_not_found</code>, <code>rig_not_found</code> || The antenna or rig does not belong to the station. | |||
|} | |||
<code>401 credential_missing</code> and <code>401 credential_invalid</code> apply as for every authenticated endpoint. | |||
== Example == | |||
<syntaxhighlight lang="bash"> | |||
curl -s -X POST https://auth.simtx.net/api/v1/game-tickets \ | |||
-H "Authorization: Bearer $SIMTX_TOKEN" \ | |||
-H 'Content-Type: application/json' \ | |||
-d '{"serverId":"argon","role":"receiver","stationId":"3f2504e0-4f89-41d3-9a0c-0305e82c3301"}' | |||
</syntaxhighlight> | |||
{{SimTX API navbox}} | |||
[[Category:SimTX API]] | |||
[[Category:SimTX API account service]] | |||
Latest revision as of 17:26, 24 October 2026
A game ticket is a short-lived, single-use credential that a client presents to a game server in the ClientHello. Tickets keep reusable credentials away from game servers: the server only ever sees a ticket that is worthless sixty seconds later. A ticket can also be bound to a station, which is how a receiver or transmitter session gets the right to use one of the account's persistent stations.
Anonymous ad-hoc receivers and anonymous control connections do not need a ticket.
Request[edit | edit source]
POST /api/v1/game-tickets
Requires a bearer credential. Rate limit: 120 requests per minute per IP address.
{
"serverId": "argon",
"role": "tx-audio",
"stationId": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"antennaId": "9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f"
}
| Field | Type | Required | Description |
|---|---|---|---|
serverId |
string | Yes | A serverId from the server directory.
|
role |
string | Yes | The protocol role the ticket will be used for. See Roles. |
stationId |
string (UUID) | No | Bind the ticket to a persistent station. Transmitter roles need a station the account owns; receiver also accepts another account's PUBLIC station.
|
antennaId |
string (UUID) | No | The station's antenna. Default: its first antenna by ordinal. |
rigId |
string (UUID) | No | The station's rig. Default: its first rig by ordinal, or none when the station has no rigs. |
Roles[edit | edit source]
The ticket is bound to one role. The role string in the request must correspond to the role sent in the hello.
Ticket role |
Hello role |
Permission required to obtain the ticket | Station binding |
|---|---|---|---|
receiver |
ROLE_RECEIVER (1) |
None | Optional |
tx-audio |
ROLE_TX_AUDIO (2) |
game.transmit |
Optional; transmitting through a station needs it |
tx-generated |
ROLE_TX_GENERATED (3) |
game.transmit |
Optional; transmitting through a station needs it |
control |
ROLE_CONTROL (4) |
catalog.publish |
Not allowed |
moderation |
ROLE_MODERATION (5) |
moderation.manage |
Not allowed |
An authenticated control connection is only needed to publish to or delete from the extension catalog and to monitor one's own transmitters. Reading the station list, maps, ephemerides, passes and the catalog works anonymously.
The permission check uses the intersection of the credential's scopes and the account's effective permissions on that server. A credential created with scope catalog.publish cannot obtain a tx-audio ticket, even if the account itself may transmit.
Response[edit | edit source]
201 Created:
{
"ticket": "stx_gt1_7e21...",
"expiresAt": "2026-10-24T12:01:00Z",
"station": {
"stationId": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"antennaId": "9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f",
"rigId": "c41d7a52-0e3b-4f6a-9c8d-1b2a3c4d5e6f",
"revision": 7,
"access": "OWNER"
}
}
| Field | Type | Description |
|---|---|---|
ticket |
string | The ticket. Place it in ClientHello.credential with auth = AUTH_KIND_GAME_TICKET.
|
expiresAt |
string | Expiry time, 60 seconds after issue. |
station |
object | Only for station-bound tickets: what was bound. |
station.stationId |
string | The station. |
station.antennaId |
string | The bound antenna, also when the request named none. |
station.rigId |
string | The bound rig. Omitted when none is bound. |
station.revision |
integer | The station's revision when the ticket was minted. |
station.access |
string | OWNER (transmit and receive) or LISTENER (receive only, on another account's PUBLIC station).
|
Station-bound sessions[edit | edit source]
A session started with a station-bound ticket must send a StationBinding for the same station, antenna and rig in its ReceiverStart or TransmitterStart. Copy the ids from the station object; an empty antenna or rig id in the binding selects the station's first antenna or rig, or the one the ticket was minted for. A binding that does not match, or an ad-hoc site sent with a station-bound ticket, is refused with ERROR_CODE_FORBIDDEN. See Binding a session.
The station snapshot the game server uses is taken when the ticket is consumed. A ticket minted for a station without rigs gets the station's first rig if one was added before the ticket was used.
Rules[edit | edit source]
- A ticket is valid for 60 seconds and can be used once.
- It is bound to the requested
serverIdandrole, and to the station if one was given. Presenting it to another server or with another role fails withHELLO_STATUS_CREDENTIAL_INVALID. - Fetch a new ticket for every connection, including every reconnect. Do not fetch tickets in advance.
- Station-bound tickets are issued only for servers that advertise the feature
stations.v1. - A ticket does not carry the user's identity in readable form. The server resolves it and returns the account in the ServerHello.
Errors[edit | edit source]
| HTTP | code |
Cause |
|---|---|---|
| 400 | ticket_request_invalid |
The message distinguishes: serverId and role are required; unknown protocol role; unknown, disabled, or offline server; credential is not authorized for the requested protocol role (the credential's scopes or the account's permissions lack the role's permission). With station fields: antennaId and rigId need a stationId; station binding is only available for transmitter and receiver roles.
|
| 404 | station_not_found |
Unknown station. |
| 403 | station_forbidden |
A transmitter role on a station the account does not own, or receiver on another account's UNLISTED station.
|
| 409 | station_inactive |
The station is deleted or deorbited. |
| 409 | station_binding_unsupported |
That server does not advertise the feature stations.v1.
|
| 400 | antenna_not_found, rig_not_found |
The antenna or rig does not belong to the station. |
401 credential_missing and 401 credential_invalid apply as for every authenticated endpoint.
Example[edit | edit source]
curl -s -X POST https://auth.simtx.net/api/v1/game-tickets \
-H "Authorization: Bearer $SIMTX_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"serverId":"argon","role":"receiver","stationId":"3f2504e0-4f89-41d3-9a0c-0305e82c3301"}'