AppRoute Public API
Auth
Send API key via X-API-Key header.
Content-Type (JSON requests)
For requests with a JSON body (POST, PUT, PATCH), clients must send Content-Type: application/json.
Requests that omit the Content-Type header or do not include application/json are rejected with HTTP 415
(Unsupported Media Type).
Response envelope (all endpoints)
Every response uses a shared JSON envelope:
status— high-level outcome enum (SUCCESS,IN_PROGRESS,PARTIALLY_COMPLETED,CANCELLED).- Errors always return
CANCELLED. POST /ordersmay returnIN_PROGRESS(HTTP 202) and should be polled.
- Errors always return
statusCode— internal application code (NOT an HTTP status), sequential range0..14:OK=0,ACCEPTED=1,IDEMPOTENCY_REPLAY=2VALIDATION_ERROR=3,UNAUTHORIZED=4,FORBIDDEN=5,NOT_FOUND=6,CONFLICT=7,LIMIT_REACHED=8,OUT_OF_STOCK=9,INSUFFICIENT_FUNDS=10UPSTREAM_ERROR=11,INTERNAL_ERROR=12API_KEY_LIMIT_EXCEEDED=13(HTTP 409,errorCode="api_key_transaction_limit_exceeded"): the API key's statictransactionLimitcannot accommodate this order. NOT a rate limit — retrying without raising the cap will keep failing.PROVIDER_UNAVAILABLE=14(HTTP 504,Retry-After: 2): the upstream provider (currently only DTU validation onPOST /orders?checkOnly=true) failed to answer twice in a row within the tightened read budget. Public API has already retried once internally; the failure is transient. Safe to retry after theRetry-Afterdelay. The request did NOT debit funds and did NOT create an order.
statusMessage— human-readable messagetraceId— request correlation iddata— success payload (ornullfor errors)errors— optional field-level errors for validation cases
Steam Gifts (feature-gated, default off)
Catalog / quote:
GET /steam-gifts/games,GET /steam-gifts/games/{productId}POST /steam-gifts/quotesbody{editionId, recipientRegion}→ sealedquoteToken
Create / status reuse the shared order lifecycle:
POST /orderswithordersType="steam-gift", requiredreferenceId+quoteToken, exactly one gift (orders[0].denominationId= editionId), fieldsrecipient_region+invite_url/profile_url. Sender region is server-selected.GET /orders?orderId=.../referenceId=...returns optionalresult.steamGift(delivery/gift state, no bot credentials / Steam transids / raw errors).
Idempotency for steam-gift is stricter than shop/dtu/esim: same referenceId +
different canonical payload → HTTP 409. Terminal outcomes are immutable (no
delete-and-recreate). New quote/intent requires a new referenceId.
Enablement is fail-closed canary: STEAM_GIFTS_ENDPOINT_ENABLED + non-empty
STEAM_GIFTS_ENABLED_API_KEY_IDS (or explicit STEAM_GIFTS_ALLOW_ALL_API_KEYS=true).
Otherwise routes and steam-gift create return HTTP 404 with zero work.
Webhook delivery is not implemented in this facade — poll orders for status.
Upstream dependency: steam-gifts-service POST /api/v1/steam-gifts/quotes and
create with optional giftId (edition→product resolution).
Idempotency
referenceId in POST /orders is required for purchases (checkOnly=false) and acts as an
idempotency key (unique within your account). If the same referenceId is replayed, the API returns
the original result with statusCode=IDEMPOTENCY_REPLAY (no duplicate purchase), even if the request
body is different. Exception: ordersType="steam-gift" requires the same canonical payload;
a different payload with the same referenceId returns HTTP 409 Conflict.
For DTU validation (ordersType="dtu" + checkOnly=true), referenceId is optional and no order is created.
Orders: statuses and polling
POST /orders can return:
SUCCESS— terminal success, voucher codes (shop) may be present immediately.IN_PROGRESS— accepted for processing (HTTP 202). This is expected for supplier-backed shop purchases (including Giftery). PollGET /orderswithorderIdorreferenceIduntil a terminal status.PARTIALLY_COMPLETED— terminal partial success: some vouchers were delivered; remaining items will not be delivered and were refunded.CANCELLED— terminal failure.
Cart (checkout)
POST /carts lets one referenceId hold multiple shop positions (a cart), purchased
atomically. It is a separate endpoint — POST /orders keeps 1 referenceId = 1 order.
- v1 is shop-only (
ordersType="shop");dtu/esimare rejected with HTTP 422. - All-or-nothing: a single out-of-stock / invalid line fails the whole cart (HTTP 4xx), nothing is charged.
referenceIdis the cart id + idempotency key; replays return the aggregate withstatusCode=IDEMPOTENCY_REPLAY.- The API key's
transactionLimitis checked against the cart total (HTTP 409API_KEY_LIMIT_EXCEEDEDnames the cart total when it does not fit). - A long-order position makes the aggregate
IN_PROGRESS(HTTP 202 +Retry-After: 15). - Retrieve / poll the created orders via
GET /orders?referenceId=...; reveal voucher codes per order withunhide=true.
Voucher codes: masking and unhide
GET /orders always returns voucher codes masked by default:
- Mask format is strict:
****+ last 4 characters of the code.
To retrieve full voucher codes, use unhide=true only with a filter:
GET /orders?orderId=...&unhide=trueorGET /orders?referenceId=...&unhide=true- Returns full codes and performs an intentional side-effect:
- marks codes as received in the underlying shop service;
- stores the timestamp of the first code retrieval.
Security rule:
unhide=truewithoutorderId/referenceIdis rejected with HTTP 422.
You can poll with unhide=true from the first filtered read. By default, each
account/order has separate budgets: 60 requests / 60 seconds for IN_PROGRESS
or PARTIALLY_COMPLETED, and 1 request / 60 seconds for SUCCESS or CANCELLED.
Pending polls do not consume the completed budget; repeated completed responses,
including cached codes, do. Read data.page.items[].status, save the returned result,
and stop polling on terminal status. PARTIALLY_COMPLETED is terminal partial
delivery and can contain codes despite using the pending budget.
On HTTP 429, wait for Retry-After before retrying the same order. See the
GET /orders description for admission and checkout rules, and GET /rate-limits
for effective limits.
Authentication
- API Key: ApiKey
Security Scheme Type: | apiKey |
|---|---|
Header parameter name: | X-API-Key |