Skip to content

Exchange a Steam Web API auth ticket for application tokens.

POST
/direct-issue/steam-ticket
curl --request POST \
--url https://native-api.sudomimus.com/direct-issue/steam-ticket \
--header 'Content-Type: application/json' \
--data '{ "applicationAnchor": "example", "steamTicketHex": "example", "steamAppId": 1, "agreementAcceptance": { "revision": 1, "locale": "en-US", "contentSha256": "example", "confirmed": true } }'

The client SDK calls ISteamUser::GetAuthTicketForWebApi("sudomimus") (the identity string MUST be exactly "sudomimus"), waits for the GetTicketForWebApiResponse_t callback, hex-encodes the returned bytes, and submits them with the application anchor and Steam App ID. The ticket must satisfy the application’s configured rules and is single-use for this exchange. Verify the returned tokens through the application’s Session JWKS. If the account has not accepted the current basic terms, the response includes the exact bilingual text and hashes. Render one locale in the native client and obtain a separate affirmative confirmation. Acquire a fresh Steam ticket and retry with agreementAcceptance bound to the displayed revision, locale, and hash.

Media typeapplication/json
object
applicationAnchor
required

Public anchor identifying the integrating application.

string
steamTicketHex
required

Hex-encoded Steam Web API auth ticket bytes returned from ISteamUser::GetAuthTicketForWebApi("sudomimus"). Hexadecimal characters are case-insensitive.

string
>= 2 characters <= 5120 characters /^(?:[0-9a-fA-F]{2}){1,2560}$/
steamAppId
required

Steam App ID under which the ticket was generated. Must be allow-listed by the application’s STEAM_TICKET authentication rule. Steam binds tickets to their issuing App ID; passing a different value fails verification.

integer format: int64
>= 1
agreementAcceptance

Present only after the native client displayed the complete versioned basic terms and received an affirmative confirmation. A prior LegalAgreementRequired response supplies the text and digest. Use a new Steam ticket for this retry.

object
revision
required
integer
>= 1
locale
required
string
Allowed values: en-US zh-CN
contentSha256
required
string
/^[a-f0-9]{64}$/
confirmed
required
boolean

Tokens issued.

Media typeapplication/json
object
claims
required

Per-claim view across the five shareable claims, carried on both the 200 (why is a claim absent from the minted token) and the claim-gate 403 (what is still owed).

object
email
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
firstName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
lastName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
staticAvatar
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
animatedAvatar
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
applicationAnchor
required
string
accessToken
required

Short-lived access token (JWT). Payload sub is the pairwise sector subject, sid identifies the session, and jti identifies this token instance. It contains no profile claims or raw account identifier; use Session API /userinfo for current shared identity data.

string
refreshToken
required

Long-lived refresh token JWT with stable payload sid, version identifier jti, and positive rotationVersion. It contains no user identifier. Use Session API /refresh to obtain a new access token without re-acquiring a Steam ticket.

string
Example
{
"claims": {
"email": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"firstName": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"lastName": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"staticAvatar": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"animatedAvatar": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
}
}
}
Cache-Control
string
Allowed values: no-store

Prevent storage of the credential-bearing response.

Pragma
string
Allowed values: no-cache

Legacy cache instruction retained for credential responses.

Malformed request (e.g. invalid steamAppId).

Media typeapplication/json

Error response body. Known failures may include a stable reason. Some failures are status-only and have an empty body. A missing, malformed, or structurally invalid JSON body returns InvalidBody.

object
reason

Stable machine-readable reason code.

string
Examplegenerated
{
"reason": "example"
}

Steam rejected the ticket.

Media typeapplication/json

Error response body. Known failures may include a stable reason. Some failures are status-only and have an empty body. A missing, malformed, or structurally invalid JSON body returns InvalidBody.

object
reason

Stable machine-readable reason code.

string
Examplegenerated
{
"reason": "example"
}

The attempt was refused. The response reason distinguishes:

  • Layer1Denied, Layer2Denied, Layer3Denied — application policy rejected the attempt.
  • ApplicationNotActive — the application is unavailable.
  • AccountDisabled or AccountDeleted — the account is unavailable for issuance.
  • EmailDomainBlocked, EmailDomainRequiresSso, or SsoAuthorityConflict — email-domain policy prevents issuance.
  • ClaimConsentRequired or RequiredClaimDataMissing — browser interaction is required before direct issuance can continue.
  • LegalAgreementRequired — the native client must display and confirm the exact basic terms before retrying.

Claim-gate responses also include claims and an errand browser handoff. Open errand.url, wait or poll its status, then acquire a fresh Steam ticket and retry once after completion.

Media typeapplication/json

403 body. For the claim-gate reasons (ClaimConsentRequired, RequiredClaimDataMissing) the claims view and the errand handoff are present. For LegalAgreementRequired, agreement contains the complete versioned basic terms for Steam native presentation, or termsUrl identifies the version to accept during browser sign-in for provisioned AccessKey and PublicKey credentials.

object
reason
required

Stable machine-readable reason code.

string
requiredRevision
integer
>= 1
termsUrl
string format: uri
confirmation
string
claims

Per-claim view across the five shareable claims, carried on both the 200 (why is a claim absent from the minted token) and the claim-gate 403 (what is still owed).

object
email
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
firstName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
lastName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
staticAvatar
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
animatedAvatar
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC_ONLY always emits the generated placeholder and never asks for real data. SYNTHETIC_FALLBACK guarantees the claim is present but uses a generated placeholder (a stand-in name, a proxy email, or a generated avatar) when the user has not shared real data. Unlike REQUIRED, neither synthetic mode blocks issuance or raises an errand.

string
Allowed values: SYNTHETIC_ONLY OFF OPTIONAL REQUIRED SYNTHETIC_FALLBACK
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
errand

The browser side-trip that unblocks a claim-gated direct-issue: a short-lived, single-use bearer URL where the user authenticates when required, completes missing data, and manages consent. Open the URL and let the browser page guide the user.

object
errandKey
required

Bearer key (ernd_…); also the status-poll path key.

string
url
required

Open this in the user’s system browser.

string format: uri
expiresAt
required
string format: date-time
agreement
object
documentType
required
string
Allowed value: BASIC_TERMS
requiredRevision
required
integer
>= 1
requiredAcceptanceEpoch
required
integer
>= 1
locales
required
object
en-US
required
object
contentSha256
required
string
/^[a-f0-9]{64}$/
versionUrl
required
string format: uri
document
required
object
schemaVersion
required
integer
Allowed value: 1
title
required
string
sections
required
Array<object>
object
heading
required
string
paragraphs
required
Array<string>
>= 1 items
link
object
label
required
string
url
required
string format: uri
zh-CN
required
object
contentSha256
required
string
/^[a-f0-9]{64}$/
versionUrl
required
string format: uri
document
required
object
schemaVersion
required
integer
Allowed value: 1
title
required
string
sections
required
Array<object>
object
heading
required
string
paragraphs
required
Array<string>
>= 1 items
link
object
label
required
string
url
required
string format: uri
Example
{
"claims": {
"email": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"firstName": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"lastName": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"staticAvatar": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
},
"animatedAvatar": {
"requirement": "SYNTHETIC_ONLY",
"state": "UNKNOWN"
}
},
"agreement": {
"documentType": "BASIC_TERMS",
"locales": {
"en-US": {
"document": {
"schemaVersion": 1
}
},
"zh-CN": {
"document": {
"schemaVersion": 1
}
}
}
}
}
Cache-Control
string
Allowed values: no-store

Prevent storage of the credential-bearing response.

Pragma
string
Allowed values: no-cache

Legacy cache instruction retained for credential responses.

Application anchor not found.

Media typeapplication/json

Error response body. Known failures may include a stable reason. Some failures are status-only and have an empty body. A missing, malformed, or structurally invalid JSON body returns InvalidBody.

object
reason

Stable machine-readable reason code.

string
Examplegenerated
{
"reason": "example"
}

Conflict. The response reason distinguishes:

  • ReplayProtectionAlreadySeen — the ticket was already submitted or is being processed.
  • AuthorizationArtifactStale — identity authority changed during the attempt.
  • LegalAgreementRevisionMismatch — the submitted terms revision, locale, or hash no longer matches the server’s current text.

Acquire a fresh ticket before retrying either condition.

Media typeapplication/json

Error response body. Known failures may include a stable reason. Some failures are status-only and have an empty body. A missing, malformed, or structurally invalid JSON body returns InvalidBody.

object
reason

Stable machine-readable reason code.

string
Examplegenerated
{
"reason": "example"
}

Too many Steam-ticket attempts. Back off before acquiring and submitting another ticket.

Steam ticket verification is temporarily unavailable.

Media typeapplication/json

Error response body. Known failures may include a stable reason. Some failures are status-only and have an empty body. A missing, malformed, or structurally invalid JSON body returns InvalidBody.

object
reason

Stable machine-readable reason code.

string
Examplegenerated
{
"reason": "example"
}

Error response.

Media typeapplication/json

Error response body. Known failures may include a stable reason. Some failures are status-only and have an empty body. A missing, malformed, or structurally invalid JSON body returns InvalidBody.

object
reason

Stable machine-readable reason code.

string
Examplegenerated
{
"reason": "example"
}