Skip to main content
Version: 1.0.0

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 /orders may return IN_PROGRESS (HTTP 202) and should be polled.
  • statusCode — internal application code (NOT an HTTP status), sequential range 0..14:
    • OK=0, ACCEPTED=1, IDEMPOTENCY_REPLAY=2
    • VALIDATION_ERROR=3, UNAUTHORIZED=4, FORBIDDEN=5, NOT_FOUND=6, CONFLICT=7, LIMIT_REACHED=8, OUT_OF_STOCK=9, INSUFFICIENT_FUNDS=10
    • UPSTREAM_ERROR=11, INTERNAL_ERROR=12
    • API_KEY_LIMIT_EXCEEDED=13 (HTTP 409, errorCode="api_key_transaction_limit_exceeded"): the API key's static transactionLimit cannot 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 on POST /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 the Retry-After delay. The request did NOT debit funds and did NOT create an order.
  • statusMessage — human-readable message
  • traceId — request correlation id
  • data — success payload (or null for 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/quotes body {editionId, recipientRegion} → sealed quoteToken

Create / status reuse the shared order lifecycle:

  • POST /orders with ordersType="steam-gift", required referenceId + quoteToken, exactly one gift (orders[0].denominationId = editionId), fields recipient_region + invite_url/profile_url. Sender region is server-selected.
  • GET /orders?orderId=... / referenceId=... returns optional result.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). Poll GET /orders with orderId or referenceId until 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 / esim are rejected with HTTP 422.
  • All-or-nothing: a single out-of-stock / invalid line fails the whole cart (HTTP 4xx), nothing is charged.
  • referenceId is the cart id + idempotency key; replays return the aggregate with statusCode=IDEMPOTENCY_REPLAY.
  • The API key's transactionLimit is checked against the cart total (HTTP 409 API_KEY_LIMIT_EXCEEDED names 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 with unhide=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=true or GET /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=true without orderId / referenceId is 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

Security Scheme Type:

apiKey

Header parameter name:

X-API-Key