Example operations
Copy-paste examples for common Management API (studio-backend) flows, each with variables and a representative response. Field shapes are authoritative in the GraphQL reference and the Management API SDL. For the agent overview see For AI agents; for error handling see Error codes.
Responses are representative. Send
Authorization: Bearer <token>on every request (except the public marketplace reads).BigIntvalues are decimal strings;*Centsfields are minor currency units.
1. Authenticate (passwordless)
Sign-in is passwordless. Request a magic link, then complete it with the token from the emailed URL to receive an identity session token:
mutation Request($input: RequestLoginLinkInput!) {
requestLoginLink(input: $input) { sent devToken }
}
{ "input": { "email": "owner@example.com" } }
{ "data": { "requestLoginLink": { "sent": true, "devToken": null } } }
mutation Complete($input: CompleteLoginLinkInput!) {
completeLoginLink(input: $input) { token gameTokenId user { userId email } }
}
{ "input": { "token": "<one-time-token-from-the-link>" } }
{ "data": { "completeLoginLink": { "token": "ServerIssuedSessionToken", "gameTokenId": "9001", "user": { "userId": "777", "email": "owner@example.com" } } } }
Social sign-in uses
socialLoginStart→socialLoginComplete; in dev (DEV_AUTH_BYPASS=true)devLogin(input:{email})returns a session in one call andrequestLoginLinkreturnsdevTokendirectly. See Sign in (passwordless).
2. Browse the marketplace (public, no auth)
query Apps($filter: AppMarketplaceFilterInput, $limit: Int, $offset: Int) {
apps(filter: $filter, limit: $limit, offset: $offset) {
items { appId name slug }
pageInfo { totalCount limit offset }
}
}
{ "filter": { "query": "racing" }, "limit": 25, "offset": 0 }
{
"data": {
"apps": {
"items": [{ "appId": "42", "name": "Turbo Racer", "slug": "turbo-racer" }],
"pageInfo": { "totalCount": 1, "limit": 25, "offset": 0 }
}
}
}
3. Search users (super admin)
query Users($query: String, $limit: Int, $offset: Int) {
usersPaginated(query: $query, limit: $limit, offset: $offset) {
items { userId gamertag }
pageInfo { totalCount limit offset }
}
}
{ "query": "ada", "limit": 50, "offset": 0 }
{
"data": {
"usersPaginated": {
"items": [{ "userId": "777", "gamertag": "ada" }],
"pageInfo": { "totalCount": 1, "limit": 50, "offset": 0 }
}
}
}
4. Check an org wallet
query Wallet($orgId: BigInt!) {
walletBalance(orgId: $orgId) { balanceCents currency }
}
{ "orgId": "10" }
{ "data": { "walletBalance": { "balanceCents": "5000", "currency": "usd" } } }
5. Open a wallet top-up checkout
mutation TopUp($input: CreateCheckoutInput!) {
createCheckout(input: $input) { externalUrl status }
}
{
"input": {
"purpose": "ORG_WALLET_TOPUP",
"orgId": "10",
"amountCents": "5000",
"provider": "STRIPE"
}
}
{
"data": {
"createCheckout": {
"externalUrl": "https://checkout.stripe.com/c/pay/cs_test_...",
"status": "PENDING"
}
}
}
Redirect the user to externalUrl. The wallet credit reconciles via webhook, not the
redirect, and status advances to COMPLETED then. createCheckout is not
idempotent — do not blind-retry it on a network error.
6. Grant a user access to an app
mutation Grant($input: GrantAppAccessInput!) {
grantAppAccess(input: $input) { status }
}
{ "input": { "appId": "42", "userId": "777", "tierId": "5" } }
{ "data": { "grantAppAccess": { "status": "active" } } }
This is an entitlement change that propagates to the game runtime. It requires the
manage_access_tiers permission on the app's org (see the field's description in the SDL).