The authoritative OpenAPI 3.0 contract is embedded below. Download the raw YAML.
openapi: 3.0.3
info:
title: ItemData Steam Inventory API
version: 6.0.0
description: Cursor-paginated Steam inventory API with a server-controlled Steam page size of 2000, rotating-proxy retries, durable public page snapshots, bounded account-wide private-inventory caching, caller-authorized Steam-session access, and an optional internal Steam-session pool for recently trade-blocked CS2 assets.
servers:
- url: /
tags:
- name: Inventory
description: Fetch normalized Steam inventory pages with cache and billing metadata.
- name: Plans
description: Discover the currently published ItemData plans and request limits.
- name: Operations
description: Read-only service liveness and dependency health endpoints.
- name: Reference
description: Human-readable and machine-readable API contracts.
paths:
/v1/inventory:
get:
tags: [Inventory]
summary: Fetch one Steam inventory page
x-itemdata-catalog: true
x-itemdata-try-it: inventory
x-itemdata-order: 10
x-itemdata-credit-cost:
unit: credit
base: 1
maximum: 2
fresh_surcharge: 1
stacks: false
label: 1–2 credits
description: Successful normal pages cost 1 credit. Any fresh-fetch mode adds +1, and fresh options never stack above 2 credits.
x-itemdata-rate-limit:
label: Plan limits
description: The active plan's minute, day, and month request limits apply before Steam work begins.
x-itemdata-example:
query:
steam_id: '76561198000000000'
game: cs2
description: >-
Returns exactly one Steam page. A successful normal public request
consumes one base credit and may use a fresh or stale-if-error public
snapshot. no_cache=true, caller-supplied steam_login_secure or
trade_url credentials, and
try_first_seven_days_blocked_items=true each add +1 credit when the
result is billable because they force a fresh fetch. Fresh-fetch
additions never stack, so the maximum billable inventory-request price
is 2 credits.
Steam's undocumented Community inventory endpoint currently returns
HTTP 401 with JSON null for structurally valid but unallocated
SteamID64 values. Because 401 may also represent a public-empty state,
ItemData treats it as a successful empty public page and follows normal
public-page caching and billing. An upstream Steam HTTP 403 is treated
as a confirmed private inventory and finalizes the full
quote: 1 credit for a normal MISS or private-marker HIT, or 2 credits
for a fresh-fetch mode. It is cached for 72 hours once per SteamID64;
during that TTL it applies to every game and normal requests return HIT
without contacting Steam. no_cache=true ignores both public snapshots
and the private marker, charges 2 credits for a confirmed fresh 403,
and refreshes the marker. A non-authoritative success=false result still
removes an older public snapshot but is not charged.
Caller-supplied and internal Steam-session requests always perform a
fresh fetch and bypass all shared cache state. For an authorized
account, provide a structurally valid steamLoginSecure cookie in
X-Steam-Login-Secure to fetch the cookie owner's inventory for any
supported game; for CS2, this avoids the normal 10-day visibility
delay. steam_id is ignored and the owner SteamID64 is read from the
cookie. Alternatively, provide a canonical Steam trade URL in
X-Steam-Trade-URL to fetch that CS2 partner inventory, including 7-10
day trade-locked items; steam_id is then ignored and the target is read
from the URL. If both credentials are present, X-Steam-Login-Secure
takes precedence and the trade URL is ignored. Never put either secret
in a URL unless legacy compatibility is unavoidable: query strings can
enter browser history, access logs, and intermediary logs. Set
try_first_seven_days_blocked_items=true for CS2 to try the internal
partner-inventory session pool first; this forces non-tradable items to
be included and falls back to a fresh public inventory request on the
first page only when Steam rejects the partner request or the pool is
temporarily unavailable. trade_url cannot be combined with
try_first_seven_days_blocked_items. Broker authentication/configuration
and invalid broker responses fail instead of being hidden by public
fallback. Other failed requests and non-authoritative success=false
responses consume zero credits. The upstream public Steam page size is
fixed server-side at 2000; count and limit are not accepted. When
more_items is true, pass last_assetid as start_assetid on the next
request. Preserve cursor provenance using
X-ItemData-Inventory-Source: keep the option enabled after partner, but
omit it after public-fallback. The actual encoded JSON body is limited
to 12 MiB for both compact and pretty output.
operationId: getInventory
security:
- BearerAuth: []
- ApiKeyQuery: []
parameters:
- $ref: '#/components/parameters/Key'
- name: steam_id
in: query
required: false
schema:
type: string
minLength: 17
maxLength: 17
pattern: '^[0-9]{17}$'
example: '76561198000000000'
description: Public individual SteamID64 only, in the inclusive range 76561197960265729 through 76561202255233023. SteamID2, SteamID3, vanity names, profile URLs, whitespace, and other Steam account types are rejected before inventory capacity or credits are reserved. Required unless steam_login_secure or trade_url supplies the target. When either credential supplies the target, steam_id may be omitted; if supplied, it must still satisfy this schema but its value is not used. steam_login_secure takes precedence when both credentials are present.
x-itemdata-requirement:
kind: conditional
unless: [X-Steam-Login-Secure, X-Steam-Trade-URL]
- $ref: '#/components/parameters/Game'
- $ref: '#/components/parameters/Language'
- name: start_assetid
in: query
schema: { type: string, maxLength: 32, pattern: '^[0-9]+$' }
description: Opaque Steam cursor from the previous response's last_assetid. Omit for the first page.
- $ref: '#/components/parameters/IncludeNonTradable'
- $ref: '#/components/parameters/WithNoTradable'
- $ref: '#/components/parameters/NoCache'
- $ref: '#/components/parameters/TryFirstSevenDaysBlockedItems'
- name: steam_login_secure
in: query
deprecated: true
schema: { type: string, maxLength: 4096 }
description: Legacy query form of X-Steam-Login-Secure. Prefer the header because query strings can be retained in browser history and access or intermediary logs.
x-itemdata-sensitive: true
x-itemdata-persist: never
- $ref: '#/components/parameters/SteamLoginSecureHeader'
- name: trade_url
in: query
deprecated: true
schema: { type: string, maxLength: 2048 }
description: Legacy query form of X-Steam-Trade-URL. Prefer the header because the trade token is a secret and query strings can be retained in browser history and access or intermediary logs.
x-itemdata-sensitive: true
x-itemdata-persist: never
- $ref: '#/components/parameters/SteamTradeURLHeader'
- $ref: '#/components/parameters/Format'
- $ref: '#/components/parameters/Pretty'
responses:
'200':
description: One inventory page, including a cacheable success=false response for a confirmed private inventory. Upstream Steam 401/403 statuses are domain inputs and do not become this API's HTTP 401/403 responses. A Steam 401, including the response observed for an unallocated but structurally valid SteamID64, becomes a billable successful empty page.
headers:
X-ItemData-More-Items:
description: Mirrors more_items from the response body.
schema: { type: boolean }
X-ItemData-Next-Cursor:
description: Present only when another page exists; pass this value as start_assetid. In blocked-item mode, keep the mode enabled only when X-ItemData-Inventory-Source is partner; omit it after public-fallback.
schema: { type: string, maxLength: 32, pattern: '^[0-9]+$' }
X-ItemData-Cache:
description: HIT for a fresh public snapshot or account-wide private marker, MISS after a new normal fetch, STALE for public stale-if-error fallback, and BYPASS for forced, session-authenticated, or successful cache-storage fallback fetches.
schema: { type: string, enum: [HIT, MISS, STALE, BYPASS] }
X-ItemData-Inventory-Source:
description: public for the normal endpoint, partner when the internal session pool succeeded, and public-fallback when partner mode fell back on its first page.
schema: { type: string, enum: [public, partner, public-fallback] }
Age:
description: Whole seconds since the served public page or confirmed private state was observed at Steam.
schema: { type: integer, format: int64, minimum: 0 }
X-ItemData-Billing-Status:
description: confirmed when the debit and usage event are durable. pending is a rare at-most-once safety outcome where COMMIT may have succeeded but reconciliation remained unavailable; retrying the same inventory call is a new billable request.
schema: { type: string, enum: [confirmed, pending] }
X-ItemData-Credits-Charged:
description: Credits finalized for this billable result, including a confirmed Steam HTTP 403. Present only when X-ItemData-Billing-Status is confirmed.
schema: { type: integer, minimum: 1, maximum: 2 }
X-ItemData-Credit-Pricing-Version:
description: Immutable server pricing rule recorded with the usage event. Present only when X-ItemData-Billing-Status is confirmed.
schema: { type: string, example: inventory.v2 }
content:
application/json:
schema: { $ref: '#/components/schemas/Inventory' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'402': { $ref: '#/components/responses/PaymentRequired' }
'403': { $ref: '#/components/responses/Forbidden' }
'429': { $ref: '#/components/responses/RateLimited' }
'499': { $ref: '#/components/responses/ClientClosedRequest' }
'502': { $ref: '#/components/responses/BadGateway' }
'503': { $ref: '#/components/responses/Unavailable' }
'504': { $ref: '#/components/responses/GatewayTimeout' }
/v1/plans:
get:
tags: [Plans]
summary: List published plans
description: Returns the currently published ItemData plans, credit balances, and minute, day, and month request limits without requiring an API key.
operationId: listPublishedPlans
x-itemdata-catalog: true
x-itemdata-try-it: simple-get
x-itemdata-order: 20
x-itemdata-credit-cost:
unit: credit
base: 0
maximum: 0
fresh_surcharge: 0
stacks: false
label: Free
description: This endpoint does not consume inventory credits.
x-itemdata-rate-limit:
label: Public read
description: Protected by bounded service capacity; no API key is required.
responses:
'200':
description: Published plans ordered by sort_order and code.
content:
application/json:
schema: { $ref: '#/components/schemas/PlanList' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/v1/live:
get:
tags: [Operations]
summary: Process liveness
description: Confirms that the ItemData HTTP process is running. This lightweight probe does not verify downstream dependencies.
operationId: getLiveness
x-itemdata-catalog: true
x-itemdata-try-it: simple-get
x-itemdata-order: 40
x-itemdata-credit-cost:
unit: credit
base: 0
maximum: 0
fresh_surcharge: 0
stacks: false
label: Free
description: This endpoint does not consume inventory credits.
x-itemdata-rate-limit:
label: Health probe
description: Intended for lightweight process-liveness checks.
responses:
'200':
description: The process is running and can serve HTTP.
content:
application/json:
schema: { $ref: '#/components/schemas/Liveness' }
/v1/health:
get:
tags: [Operations]
summary: Service, dependency, proxy, and runtime health
description: Reports dependency-aware service readiness, including the runtime components required to serve inventory traffic.
operationId: getHealth
x-itemdata-catalog: true
x-itemdata-try-it: simple-get
x-itemdata-order: 30
x-itemdata-credit-cost:
unit: credit
base: 0
maximum: 0
fresh_surcharge: 0
stacks: false
label: Free
description: This endpoint does not consume inventory credits.
x-itemdata-rate-limit:
label: Health probe
description: Intended for dependency-aware health and status checks.
responses:
'200':
description: Healthy
content:
application/json:
schema: { $ref: '#/components/schemas/Health' }
'503':
description: One or more required dependencies are unavailable
content:
application/json:
schema: { $ref: '#/components/schemas/Health' }
/v1/docs:
get:
tags: [Reference]
summary: Self-contained OpenAPI documentation
description: Returns the backend's embedded, English-language OpenAPI documentation for human inspection.
operationId: getEmbeddedDocumentation
x-itemdata-catalog: true
x-itemdata-try-it: none
x-itemdata-order: 50
x-itemdata-credit-cost:
unit: credit
base: 0
maximum: 0
fresh_surcharge: 0
stacks: false
label: Free
description: This endpoint does not consume inventory credits.
x-itemdata-rate-limit:
label: Public reference
description: Served as a short-lived cacheable documentation response.
responses:
'200': { description: Human-readable embedded OpenAPI documentation }
/v1/openapi.yaml:
get:
tags: [Reference]
summary: Raw OpenAPI contract
description: Returns the authoritative English-language OpenAPI 3.0 YAML contract used to generate the public endpoint catalog.
operationId: getOpenAPIContract
x-itemdata-catalog: true
x-itemdata-try-it: none
x-itemdata-order: 60
x-itemdata-credit-cost:
unit: credit
base: 0
maximum: 0
fresh_surcharge: 0
stacks: false
label: Free
description: This endpoint does not consume inventory credits.
x-itemdata-rate-limit:
label: Public reference
description: Served as a short-lived cacheable machine-readable contract.
responses:
'200':
description: OpenAPI 3.0 YAML
content:
application/yaml:
schema: { type: string }
/auth/steam:
get:
summary: Start Steam OpenID sign-in
operationId: startSteamSignIn
parameters:
- name: return_to
in: query
required: false
schema: { type: string, default: /dashboard, maxLength: 2048 }
description: Same-site relative path used after authentication.
responses:
'302':
description: Redirect to the fixed Steam OpenID provider.
'400': { $ref: '#/components/responses/ConsoleBadRequest' }
'429': { $ref: '#/components/responses/ConsoleRateLimited' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/auth/steam/callback:
get:
summary: Verify a Steam OpenID assertion
operationId: finishSteamSignIn
description: Browser callback used by Steam. A short-lived HttpOnly browser-binding cookie plus state, return_to, provider, signature, nonce, identity, and claimed SteamID64 are verified server-side. Capacity and rate-limit failures redirect with a safe auth_error code.
responses:
'302':
description: Redirect to the configured frontend with a new secure web session, or a safe auth_error code.
/auth/logout:
post:
summary: Revoke the current web session
operationId: logoutWebSession
security:
- WebSession: []
parameters:
- $ref: '#/components/parameters/CSRFToken'
responses:
'204': { description: Session revoked and cookies cleared }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/console/v1/me:
get:
summary: Load the authenticated dashboard snapshot
operationId: getConsoleDashboard
security:
- WebSession: []
responses:
'200':
description: Account, active-key metadata, current-month usage, credits, and a CSRF token. API-key plaintext is never returned here.
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleDashboard' }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/console/v1/api-key/rotate:
post:
summary: Create or atomically rotate the account API key
operationId: rotateConsoleAPIKey
description: The plaintext credential is returned exactly once. An active key is not replaced while it has unexpired credit reservations.
security:
- WebSession: []
parameters:
- $ref: '#/components/parameters/CSRFToken'
responses:
'201':
description: New API key. Do not persist this response.
content:
application/json:
schema: { $ref: '#/components/schemas/CreatedAPIKey' }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'409': { $ref: '#/components/responses/APIKeyBusy' }
'429': { $ref: '#/components/responses/ConsoleRateLimited' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/console/v1/api-key/revoke:
post:
summary: Revoke the account API key
operationId: revokeConsoleAPIKey
security:
- WebSession: []
parameters:
- $ref: '#/components/parameters/CSRFToken'
responses:
'200':
description: API key revoked
content:
application/json:
schema:
type: object
additionalProperties: false
required: [revoked]
properties:
revoked: { type: boolean, enum: [true] }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'404': { $ref: '#/components/responses/APIKeyNotFound' }
'409': { $ref: '#/components/responses/APIKeyBusy' }
'429': { $ref: '#/components/responses/ConsoleRateLimited' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/console/v1/admin/plans:
get:
summary: List every plan for administration
operationId: listAdminPlans
security:
- WebSession: []
responses:
'200':
description: Draft, published, and archived plans ordered by sort_order and code.
content:
application/json:
schema: { $ref: '#/components/schemas/PlanList' }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
post:
summary: Create a plan
operationId: createAdminPlan
security:
- WebSession: []
parameters:
- $ref: '#/components/parameters/CSRFToken'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CreatePlanRequest' }
responses:
'201':
description: Plan created and audit event recorded atomically.
content:
application/json:
schema: { $ref: '#/components/schemas/PlanResponse' }
'400': { $ref: '#/components/responses/ConsoleBadRequest' }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'409':
description: A plan with this code already exists.
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
'429': { $ref: '#/components/responses/ConsoleRateLimited' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/console/v1/admin/plans/{code}:
post:
summary: Update a plan with optimistic concurrency
operationId: updateAdminPlan
security:
- WebSession: []
parameters:
- name: code
in: path
required: true
schema:
type: string
minLength: 1
maxLength: 64
pattern: '^[a-z][a-z0-9_-]{0,63}$'
- $ref: '#/components/parameters/CSRFToken'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UpdatePlanRequest' }
responses:
'200':
description: Updated plan and atomic audit event.
content:
application/json:
schema: { $ref: '#/components/schemas/PlanResponse' }
'400': { $ref: '#/components/responses/ConsoleBadRequest' }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'404':
description: Plan not found.
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
'409':
description: Supplied version is stale.
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
'429': { $ref: '#/components/responses/ConsoleRateLimited' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
/console/v1/admin/users/{steam_id64}/plan:
post:
summary: Assign or replace an account plan for a fixed duration
operationId: assignAdminAccountPlan
description: >-
Appends an immutable assignment snapshot and atomically resets an
active API key to the selected plan's published credits and rate
limit. Idempotency keys are scoped to the authenticated administrator
and retained durably: retrying the same key and payload returns the
original assignment without another grant or credit reset. Existing
in-flight credit reservations cause a conflict.
security:
- WebSession: []
parameters:
- name: steam_id64
in: path
required: true
schema:
type: string
pattern: '^[0-9]{17}$'
- $ref: '#/components/parameters/CSRFToken'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AssignPlanRequest' }
responses:
'201':
description: Immutable assignment snapshot. The administrator identity and internal duration audit field are not exposed.
headers:
Idempotency-Replayed:
description: True when this response replays the durable result of an earlier request with the same administrator, key, and payload.
schema: { type: boolean }
content:
application/json:
schema: { $ref: '#/components/schemas/PlanAssignmentResponse' }
'400':
description: Missing or invalid Idempotency-Key, SteamID64, plan code, duration, content type, or JSON shape.
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
'401': { $ref: '#/components/responses/ConsoleUnauthorized' }
'403': { $ref: '#/components/responses/ConsoleForbidden' }
'404':
description: The registered account or selected plan does not exist.
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
'409':
description: The plan is not published with fixed credits, the active API key has an in-flight reservation, or the Idempotency-Key was already used by this administrator with another payload (`idempotency_key_conflict`).
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
'429': { $ref: '#/components/responses/ConsoleRateLimited' }
'503': { $ref: '#/components/responses/ConsoleUnavailable' }
components:
securitySchemes:
ApiKeyQuery:
type: apiKey
in: query
name: key
BearerAuth:
type: http
scheme: bearer
WebSession:
type: apiKey
in: cookie
name: itemshard_session
description: Local HTTP cookie name. HTTPS deployments use the hardened __Host-itemshard_session name.
parameters:
Key:
name: key
in: query
required: false
schema: { type: string, maxLength: 512 }
description: API key. Authorization Bearer is preferred outside compatibility integrations.
x-itemdata-sensitive: true
x-itemdata-persist: never
Game:
name: game
in: query
schema:
type: string
enum: [cs2, rust, dota, dota2, tf2, pubg]
default: cs2
description: Supported canonical values are cs2, rust, dota2, tf2, and pubg. dota is accepted as a compatibility alias and is returned canonically as dota2.
Language:
name: language
in: query
schema:
type: string
minLength: 2
maxLength: 32
pattern: '^[A-Za-z][A-Za-z_-]{1,31}$'
default: english
description: Steam inventory localization language. Defaults to english and accepts Steam-compatible language identifiers.
IncludeNonTradable:
name: include_non_tradable
in: query
schema: { type: boolean, default: false }
description: Include non-tradable assets. Filtering never changes total_inventory_count or cursor progression.
WithNoTradable:
name: with_no_tradable
in: query
schema: { type: boolean, default: false }
description: SteamWebAPI-compatible alias for include_non_tradable. If both are provided, their values must match.
NoCache:
name: no_cache
in: query
schema: { type: boolean, default: false }
description: Force a new public Steam fetch instead of serving a public snapshot or confirmed-private marker. Additional cost is +1 credit for a billable result; a confirmed Steam HTTP 403 therefore costs 2 credits and refreshes the account-wide private marker. The response is not published as another shared immutable object. A non-authoritative success=false response still durably removes any older public snapshot and is refunded. A concurrent no_cache call for the same SteamID64 returns refresh_in_progress and is not charged. Requests authorized by steam_login_secure or trade_url and internal Steam-session requests already bypass the shared cache and do not need this flag. Fresh-fetch additions never stack, so the maximum billable inventory-request price is 2 credits.
TryFirstSevenDaysBlockedItems:
name: try_first_seven_days_blocked_items
in: query
schema: { type: boolean, default: false }
description: For CS2 only, try Steam's partner-inventory path through an internal service-account session before the normal public endpoint. It cannot be combined with steam_login_secure or trade_url, always bypasses the shared cache, and forces include_non_tradable=true. Additional cost is +1 credit for a billable result, including a confirmed Steam HTTP 403 from the public fallback. If Steam rejects the first partner request or the pool is temporarily unavailable, ItemData performs one fresh public fallback and reports public-fallback in X-ItemData-Inventory-Source; broker configuration/authentication and protocol failures do not silently fall back. For the next page, keep this flag after a partner response but omit it after public-fallback. A later partner cursor never falls back to the semantically different public cursor.
Format:
name: format
in: query
schema: { type: string, enum: [json, prettyjson, pretty], default: json }
description: Use prettyjson for indented JSON; pretty remains a compatibility alias.
Pretty:
name: pretty
in: query
schema: { type: boolean, default: false }
description: Set to 1 or true for indented JSON. Pretty output is subject to the same 12 MiB encoded-body limit as compact JSON. ItemData intentionally supports JSON only.
SteamLoginSecureHeader:
name: X-Steam-Login-Secure
in: header
required: false
schema: { type: string, maxLength: 4096 }
description: Preferred transport for a structurally valid steamLoginSecure cookie that contains its owner SteamID64. Supported for every game; for CS2, it fetches the authorized owner's inventory without the normal 10-day visibility delay. steam_id is ignored and derived from the cookie. The value is forwarded only for this request, bypasses all shared cache reads and writes, adds +1 credit for a billable result including a confirmed Steam HTTP 403, and is never persisted. If X-Steam-Trade-URL is also present, this header takes precedence and the trade URL is ignored.
x-itemdata-sensitive: true
x-itemdata-persist: never
SteamTradeURLHeader:
name: X-Steam-Trade-URL
in: header
required: false
schema:
type: string
maxLength: 2048
example: https://steamcommunity.com/tradeoffer/new/?partner=123456&token=AbCdEf
description: Preferred transport for a canonical HTTPS Steam trade URL with exactly partner=<AccountID32> and token=<6-128 characters from A-Z, a-z, 0-9, underscore, or hyphen>. CS2 only. Fetches the partner inventory including 7-10 day trade-locked items; steam_id is ignored and derived from partner. It always bypasses shared cache reads and writes, adds +1 credit after success, is never persisted, and cannot be combined with try_first_seven_days_blocked_items. It is ignored when X-Steam-Login-Secure is present.
x-itemdata-sensitive: true
x-itemdata-persist: never
CSRFToken:
name: X-CSRF-Token
in: header
required: true
schema: { type: string, minLength: 32, maxLength: 512 }
description: Token returned by GET /console/v1/me. Mutations also require an exact configured browser Origin.
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
schema:
type: string
minLength: 16
maxLength: 128
pattern: '^[A-Za-z0-9._:-]+$'
description: Opaque per-operation key. Keep it unchanged when retrying an ambiguous response. A key is scoped to the authenticated administrator and may never be reused with another target or request body.
responses:
BadRequest:
description: Invalid request
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
Unauthorized:
description: Missing or invalid API key
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
PaymentRequired:
description: Insufficient credits
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
Forbidden:
description: API key is inactive, its assigned plan has expired (`plan_expired`), or access is forbidden
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
RateLimited:
description: Account-wide fixed-window request rate exceeded. All API keys for the same Steam account and every application replica share the minute, UTC-day, and UTC-month counters.
headers:
Retry-After:
schema: { type: integer }
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
Unavailable:
description: Required dependency or proxy gateway unavailable (`cache_unavailable` or `upstream_unavailable`), or an identical refresh is still in progress (`refresh_in_progress`)
headers:
Retry-After:
description: Present for retryable cache coordination failure or refresh contention.
schema: { type: integer, minimum: 1 }
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
BadGateway:
description: Steam returned invalid data, or the decoded or final encoded inventory exceeded a safety limit (`pagination_limit`)
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
GatewayTimeout:
description: Steam request timed out
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
ClientClosedRequest:
description: Request context was canceled by the client
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
ConsoleBadRequest:
description: Invalid browser authentication request
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
ConsoleUnauthorized:
description: Missing, expired, or revoked web session
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
ConsoleForbidden:
description: Origin/CSRF validation failed or the session lacks the required permission
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
ConsoleUnavailable:
description: Web account service unavailable
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
ConsoleRateLimited:
description: Browser authentication or console mutation rate exceeded
headers:
Retry-After:
schema: { type: integer }
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
APIKeyBusy:
description: An in-flight credit reservation prevents key rotation or revocation
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
APIKeyNotFound:
description: No active API key exists
content:
application/json:
schema: { $ref: '#/components/schemas/ConsoleError' }
schemas:
Error:
type: object
additionalProperties: false
required: [success, error]
properties:
success: { type: boolean, enum: [false] }
error:
type: object
additionalProperties: false
required: [code, message]
properties:
code: { type: string }
message: { type: string }
ConsoleError:
type: object
additionalProperties: false
required: [error]
properties:
error:
type: object
additionalProperties: false
required: [code, message]
properties:
code: { type: string }
message: { type: string }
Inventory:
type: object
additionalProperties: false
required: [success, steam_id, game, appid, total_inventory_count, items, more_items]
properties:
success: { type: boolean }
steam_id: { type: string }
game: { type: string }
appid: { type: integer }
total_inventory_count: { type: integer }
items:
type: array
items: { $ref: '#/components/schemas/Item' }
last_assetid: { type: string, maxLength: 32, pattern: '^[0-9]+$' }
more_items: { type: boolean }
error:
type: object
additionalProperties: false
properties:
code: { type: string }
message: { type: string }
Item:
type: object
additionalProperties: false
required:
- assetid
- classid
- instanceid
- amount
- market_hash_name
- market_name
- name
- name_color
- type
- rarity
- rarity_color
- exterior
- icon_url
- icon_url_large
- tradable
- marketable
- commodity
- market_tradable_restriction
- market_marketable_restriction
- tags
- descriptions
- actions
- fraudwarnings
- inspect_link
properties:
assetid: { type: string }
classid: { type: string }
instanceid: { type: string }
amount: { type: string }
market_hash_name: { type: string }
market_name: { type: string }
name: { type: string }
name_color: { type: string }
type: { type: string }
rarity: { type: string }
rarity_color: { type: string }
exterior: { type: string }
icon_url: { type: string }
icon_url_large: { type: string }
tradable: { type: boolean }
marketable: { type: boolean }
commodity: { type: boolean }
market_tradable_restriction: { type: integer }
market_marketable_restriction: { type: integer }
tags:
type: array
items: { $ref: '#/components/schemas/Tag' }
descriptions:
type: array
items: { $ref: '#/components/schemas/DescriptionLine' }
actions:
type: array
items: { $ref: '#/components/schemas/Action' }
fraudwarnings:
type: array
nullable: true
items: { type: string }
inspect_link: { type: string }
Tag:
type: object
additionalProperties: false
required: [category, internal_name, localized_category_name, localized_tag_name]
properties:
category: { type: string }
internal_name: { type: string }
localized_category_name: { type: string }
localized_tag_name: { type: string }
color: { type: string }
DescriptionLine:
type: object
additionalProperties: false
required: [type, value]
properties:
type: { type: string }
value: { type: string }
color: { type: string }
Action:
type: object
additionalProperties: false
required: [link, name]
properties:
link: { type: string }
name: { type: string }
Liveness:
type: object
additionalProperties: false
required: [status]
properties:
status: { type: string, enum: [ok] }
Health:
type: object
additionalProperties: false
required: [status, version, uptime_seconds, dependencies, proxy, system]
properties:
status: { type: string, enum: [ok, degraded] }
version: { type: string }
uptime_seconds: { type: integer, format: int64, minimum: 0 }
dependencies:
type: object
additionalProperties: { $ref: '#/components/schemas/HealthCheck' }
proxy:
type: object
additionalProperties: true
system:
type: object
additionalProperties: true
HealthCheck:
type: object
additionalProperties: false
required: [status]
properties:
status: { type: string, enum: [ok, unavailable] }
latency: { type: string }
error: { type: string }
ConsoleDashboard:
type: object
additionalProperties: false
required: [account, api_key, plan_assignment, usage, credits, permissions, csrf_token]
properties:
account:
type: object
additionalProperties: false
required: [steam_id64, display_name, plan]
properties:
steam_id64: { type: string, pattern: '^[0-9]{17}$' }
display_name: { type: string }
avatar_url: { type: string }
plan: { type: string }
api_key:
nullable: true
allOf:
- $ref: '#/components/schemas/APIKeySummary'
plan_assignment:
nullable: true
allOf:
- $ref: '#/components/schemas/PlanAssignmentSnapshot'
usage:
type: object
additionalProperties: false
required: [requests, credits_used, used, remaining, limit, period_start, period_end]
properties:
requests: { type: integer, format: int64, minimum: 0 }
credits_used: { type: integer, format: int64, minimum: 0 }
used: { type: integer, format: int64, minimum: 0 }
remaining: { type: integer, format: int64, minimum: 0 }
limit: { type: integer, format: int64, minimum: 0 }
period_start: { type: string, format: date-time }
period_end: { type: string, format: date-time }
credits:
type: object
additionalProperties: false
required: [remaining]
properties:
remaining: { type: integer, format: int64, minimum: 0 }
permissions:
type: array
items:
type: string
enum: ['plans:manage', 'plan_assignments:manage']
uniqueItems: true
csrf_token: { type: string, minLength: 32, maxLength: 512 }
APIKeySummary:
type: object
additionalProperties: false
required:
- prefix
- created_at
- rate_limit_per_minute
- rate_limit_per_day
- rate_limit_per_month
properties:
prefix: { type: string }
created_at: { type: string, format: date-time }
last_used_at: { type: string, format: date-time }
rate_limit_per_minute: { type: integer, minimum: 1, maximum: 200 }
rate_limit_per_day:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
rate_limit_per_month:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
plan_expires_at: { type: string, format: date-time }
PlanAssignmentSnapshot:
type: object
additionalProperties: false
required:
- plan_code
- plan_version
- credits
- rate_limit_per_minute
- rate_limit_per_day
- rate_limit_per_month
- duration_days
- starts_at
- expires_at
properties:
plan_code:
type: string
minLength: 1
maxLength: 64
pattern: '^[a-z][a-z0-9_-]{0,63}$'
plan_version: { type: integer, format: int64, minimum: 1 }
credits:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
rate_limit_per_minute:
type: integer
minimum: 1
maximum: 200
rate_limit_per_day:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
rate_limit_per_month:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
duration_days: { type: integer, minimum: 1, maximum: 3650 }
starts_at: { type: string, format: date-time }
expires_at: { type: string, format: date-time }
AssignPlanRequest:
type: object
additionalProperties: false
required: [plan_code, duration_days]
properties:
plan_code:
type: string
minLength: 1
maxLength: 64
pattern: '^[a-z][a-z0-9_-]{0,63}$'
duration_days: { type: integer, minimum: 1, maximum: 3650 }
PlanAssignmentResponse:
type: object
additionalProperties: false
required: [assignment]
properties:
assignment:
type: object
additionalProperties: false
required:
- id
- steam_id64
- plan_code
- plan_version
- credits
- rate_limit_per_minute
- rate_limit_per_day
- rate_limit_per_month
- starts_at
- expires_at
- active_api_key_updated
properties:
id: { type: integer, format: int64, minimum: 1 }
steam_id64: { type: string, pattern: '^[0-9]{17}$' }
plan_code:
type: string
minLength: 1
maxLength: 64
pattern: '^[a-z][a-z0-9_-]{0,63}$'
plan_version: { type: integer, format: int64, minimum: 1 }
credits:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
rate_limit_per_minute:
type: integer
minimum: 1
maximum: 200
rate_limit_per_day:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
rate_limit_per_month:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
starts_at: { type: string, format: date-time }
expires_at: { type: string, format: date-time }
active_api_key_updated: { type: boolean }
CreatedAPIKey:
type: object
additionalProperties: false
required: [api_key, prefix, created_at]
properties:
api_key:
type: string
description: Plaintext secret returned exactly once.
prefix: { type: string }
created_at: { type: string, format: date-time }
Plan:
type: object
additionalProperties: false
required:
- code
- name
- eyebrow
- description
- price_minor
- currency
- billing_interval
- credits
- rate_limit_per_minute
- rate_limit_per_day
- rate_limit_per_month
- features
- cta_kind
- cta_label
- featured
- sort_order
- status
- version
- created_at
- updated_at
- discount_percent
- discount_expires_at
properties:
code:
type: string
minLength: 1
maxLength: 64
pattern: '^[a-z][a-z0-9_-]{0,63}$'
name: { type: string, minLength: 1, maxLength: 128 }
eyebrow: { type: string, minLength: 1, maxLength: 128 }
description: { type: string, minLength: 1, maxLength: 1024 }
price_minor:
type: integer
format: int64
minimum: 0
maximum: 1000000000000
nullable: true
currency:
type: string
maxLength: 3
pattern: '^$|^[A-Z]{3}$'
billing_interval:
type: string
enum: [month, year]
nullable: true
credits:
type: integer
format: int64
minimum: 1
maximum: 1000000000000
nullable: true
rate_limit_per_minute: { type: integer, minimum: 1, maximum: 200 }
rate_limit_per_day:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
rate_limit_per_month:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
features:
type: array
minItems: 1
maxItems: 32
uniqueItems: true
items: { type: string, minLength: 1, maxLength: 256 }
cta_kind: { type: string, enum: [steam_signup, support] }
cta_label: { type: string, minLength: 1, maxLength: 128 }
featured: { type: boolean }
sort_order: { type: integer, minimum: 0, maximum: 1000000 }
status: { type: string, enum: [draft, published, archived] }
version: { type: integer, format: int64, minimum: 1 }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
discount_percent:
type: integer
minimum: 1
maximum: 100
nullable: true
description: Percentage removed from price_minor while the paired expiration is still in the future. Null when no discount is configured.
discount_expires_at:
type: string
format: date-time
nullable: true
description: Finite RFC3339 instant at which the configured discount stops applying. Null when no discount is configured.
allOf:
- $ref: '#/components/schemas/PlanPricingInvariant'
- $ref: '#/components/schemas/PlanDiscountInvariant'
PlanList:
type: object
additionalProperties: false
required: [plans]
properties:
plans:
type: array
items: { $ref: '#/components/schemas/Plan' }
PlanResponse:
type: object
additionalProperties: false
required: [plan]
properties:
plan: { $ref: '#/components/schemas/Plan' }
CreatePlanRequest:
type: object
additionalProperties: false
required:
- code
- name
- eyebrow
- description
- price_minor
- currency
- billing_interval
- credits
- rate_limit_per_minute
- rate_limit_per_day
- rate_limit_per_month
- features
- cta_kind
- cta_label
- featured
- sort_order
- status
properties:
code:
type: string
minLength: 1
maxLength: 64
pattern: '^[a-z][a-z0-9_-]{0,63}$'
name: { type: string, minLength: 1, maxLength: 128 }
eyebrow: { type: string, minLength: 1, maxLength: 128 }
description: { type: string, minLength: 1, maxLength: 1024 }
price_minor: { type: integer, format: int64, minimum: 0, maximum: 1000000000000, nullable: true }
currency: { type: string, maxLength: 3, pattern: '^$|^[A-Z]{3}$' }
billing_interval: { type: string, enum: [month, year], nullable: true }
credits: { type: integer, format: int64, minimum: 1, maximum: 1000000000000, nullable: true }
rate_limit_per_minute: { type: integer, minimum: 1, maximum: 200 }
rate_limit_per_day:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
rate_limit_per_month:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
features:
type: array
minItems: 1
maxItems: 32
uniqueItems: true
items: { type: string, minLength: 1, maxLength: 256 }
cta_kind: { type: string, enum: [steam_signup, support] }
cta_label: { type: string, minLength: 1, maxLength: 128 }
featured: { type: boolean }
sort_order: { type: integer, minimum: 0, maximum: 1000000 }
status: { type: string, enum: [draft, published, archived] }
discount_percent:
type: integer
minimum: 1
maximum: 100
nullable: true
description: Optional percentage discount. Omit both discount fields for the legacy no-discount create contract; send both null to explicitly configure no discount.
discount_expires_at:
type: string
format: date-time
nullable: true
description: Optional finite RFC3339 expiration instant paired with discount_percent.
allOf:
- $ref: '#/components/schemas/PlanPricingInvariant'
- $ref: '#/components/schemas/PlanDiscountRequestInvariant'
UpdatePlanRequest:
type: object
additionalProperties: false
required:
- version
- name
- eyebrow
- description
- price_minor
- currency
- billing_interval
- credits
- rate_limit_per_minute
- rate_limit_per_day
- rate_limit_per_month
- features
- cta_kind
- cta_label
- featured
- sort_order
- status
properties:
version: { type: integer, format: int64, minimum: 1 }
name: { type: string, minLength: 1, maxLength: 128 }
eyebrow: { type: string, minLength: 1, maxLength: 128 }
description: { type: string, minLength: 1, maxLength: 1024 }
price_minor: { type: integer, format: int64, minimum: 0, maximum: 1000000000000, nullable: true }
currency: { type: string, maxLength: 3, pattern: '^$|^[A-Z]{3}$' }
billing_interval: { type: string, enum: [month, year], nullable: true }
credits: { type: integer, format: int64, minimum: 1, maximum: 1000000000000, nullable: true }
rate_limit_per_minute: { type: integer, minimum: 1, maximum: 200 }
rate_limit_per_day:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
rate_limit_per_month:
{ type: integer, format: int64, minimum: 1, maximum: 1000000000000 }
features:
type: array
minItems: 1
maxItems: 32
uniqueItems: true
items: { type: string, minLength: 1, maxLength: 256 }
cta_kind: { type: string, enum: [steam_signup, support] }
cta_label: { type: string, minLength: 1, maxLength: 128 }
featured: { type: boolean }
sort_order: { type: integer, minimum: 0, maximum: 1000000 }
status: { type: string, enum: [draft, published, archived] }
discount_percent:
type: integer
minimum: 1
maximum: 100
nullable: true
description: Optional percentage discount. Omitting both discount fields preserves the stored schedule; sending both null clears it.
discount_expires_at:
type: string
format: date-time
nullable: true
description: Optional finite RFC3339 expiration instant paired with discount_percent.
allOf:
- $ref: '#/components/schemas/PlanPricingInvariant'
- $ref: '#/components/schemas/PlanDiscountRequestInvariant'
PlanPricingInvariant:
type: object
required: [price_minor, currency, billing_interval]
description: |
Custom pricing uses a null price, an empty currency, and a null billing
interval. A zero price requires a three-letter currency and a null
interval. A positive price requires a three-letter currency and a
month or year interval.
oneOf:
- title: Custom pricing
properties:
price_minor: { type: integer, nullable: true, enum: [null] }
currency: { type: string, enum: [''] }
billing_interval: { type: string, nullable: true, enum: [null] }
- title: Free plan
properties:
price_minor: { type: integer, enum: [0] }
currency: { type: string, minLength: 3, maxLength: 3, pattern: '^[A-Z]{3}$' }
billing_interval: { type: string, nullable: true, enum: [null] }
- title: Recurring paid plan
properties:
price_minor: { type: integer, minimum: 1, maximum: 1000000000000 }
currency: { type: string, minLength: 3, maxLength: 3, pattern: '^[A-Z]{3}$' }
billing_interval: { type: string, enum: [month, year] }
PlanDiscountInvariant:
type: object
required: [discount_percent, discount_expires_at]
description: |
Discount metadata is always returned as a pair. Null values mean no
discount is configured. A configured percentage is valid only for a
positive fixed price and applies while the current instant is strictly
earlier than discount_expires_at; the stored metadata may remain after
expiry until an administrator changes or clears it. While active,
clients derive the effective minor-unit price by rounding
price_minor * (100 - discount_percent) / 100 to the nearest integer,
with exact halves rounded up; a 100% discount therefore displays zero
without changing the plan into a free-plan pricing contract.
oneOf:
- title: No configured discount
properties:
discount_percent: { type: integer, nullable: true, enum: [null] }
discount_expires_at: { type: string, format: date-time, nullable: true, enum: [null] }
- title: Configured percentage discount
properties:
price_minor: { type: integer, minimum: 1, maximum: 1000000000000 }
discount_percent: { type: integer, minimum: 1, maximum: 100 }
discount_expires_at: { type: string, format: date-time }
PlanDiscountRequestInvariant:
type: object
description: |
The two discount fields form one optional legacy-compatible pair. A
create request that omits both fields creates no discount. An update
request that omits both preserves the stored schedule. Sending both as
null clears the schedule. Unknown fields and a half-present pair are
invalid.
oneOf:
- title: Legacy request without discount fields
not:
anyOf:
- required: [discount_percent]
- required: [discount_expires_at]
- title: Explicitly clear discount
required: [discount_percent, discount_expires_at]
properties:
discount_percent: { type: integer, nullable: true, enum: [null] }
discount_expires_at: { type: string, format: date-time, nullable: true, enum: [null] }
- title: Configure percentage discount
required: [price_minor, discount_percent, discount_expires_at]
properties:
price_minor: { type: integer, minimum: 1, maximum: 1000000000000 }
discount_percent: { type: integer, minimum: 1, maximum: 100 }
discount_expires_at: { type: string, format: date-time }