REST API · v1

API documentation

Sync the catalogue, generate keys and look up redemptions programmatically from your own store or bot. Create a token under Developers (you need to be logged in) and use it in the examples below.

Authentication

Every route requires the Authorization header with a token generated in the dashboard. The token starts with swr_live_ and is never shown again after it is created — keep it in an environment variable, never in your repository.

Base URL
https://steamwave.com.br/api/v1/reseller
Header
Authorization: Bearer <TOKEN>
Format
JSON (UTF-8)
curl "https://steamwave.com.br/api/v1/reseller/me" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"

Billing model (escrow)

Generating a key does not deduct your balance right away: the amount is reserved. The actual charge happens when the end customer activates the key in the launcher.

  1. POST /keys reserves the cost — walletReservedCents goes up.
  2. The key is created with status SOLD, ready for the launcher.
  3. When the customer activates it, the balance is actually consumed.
  4. Refunding a key that hasn't been used returns the reservation to your available balance.

What allows a key to be generated is your available balance (balanceCents − reservedCents). If it is lower than the cost, the API answers 402 insufficient_balance.

Limits

Per request
1 to 500 keys on POST /keys
General rate limit
120 req/min on /me, /catalog, /games, GET /keys and /batches
Generation rate limit
30 req/min on POST /keys
Monthly cap
Same plan and goal rules as the dashboard (rolling 30-day window)
Billing
Balance is charged when the customer activates the key

Past the limit the API answers 429 with a retryAfter field in seconds.

GET/me

Your account and limits

Balance, plan, cost per key and how much of the cap you've used this period.
curl "https://steamwave.com.br/api/v1/reseller/me" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"
JSON response
{
  "reseller": { "keyPrefix": "RBY", "status": "ACTIVE" },
  "plan": {
    "slug": "intermediario",
    "perKeyCostCents": 150,
    "keyLimitMonthly": 500
  },
  "wallet": {
    "balanceCents": 5000,
    "reservedCents": 450,
    "spendableCents": 4550
  },
  "usage": {
    "monthlyGenerated": 62,
    "monthlyCap": 500,
    "monthlyRemaining": 438
  }
}
GET/catalog

Sync the catalogue

Mirror the catalogue in your own store. unitCostCents is already your real generation cost (plan + goal). Query: limit (max 500), cursor, since, search, deliverable (defaults to true).
# initial load
curl "https://steamwave.com.br/api/v1/reseller/catalog?limit=200" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"

# incremental sync
curl "https://steamwave.com.br/api/v1/reseller/catalog?limit=200&since=2026-07-01T00:00:00Z" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"
Every item carries flags.deliverable, flags.denuvoKey, flags.onlineFix and flags.bypass. Only list items with deliverable: true in your store.
GET/games

Search games

Lightweight search for autocomplete. Query: search, limit (max 100), cursor. available: false means the manifest is still syncing — don't generate a key in that case.
curl "https://steamwave.com.br/api/v1/reseller/games?search=cyberpunk" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"
POST/keys

Generate keys

Body: gameId or appId, quantity (1–500) and an optional label. The Idempotency-Key header is required — use a deterministic UUID per order.
curl -X POST "https://steamwave.com.br/api/v1/reseller/keys" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"appId":"1091500","quantity":1,"label":"order #123"}'
JSON response (201)
{
  "batchId": "clx…",
  "game": { "id": "clx…", "name": "Cyberpunk 2077", "appId": "1091500" },
  "label": "order #123",
  "count": 1,
  "codes": ["XXXXX-XXXXX-XXXXX-XXXXX"],
  "cost": 150,
  "unitCost": 150,
  "walletBalanceAfter": 5000,
  "walletReservedAfter": 450,
  "walletSpendableAfter": 4550,
  "planSlug": "intermediario"
}
Repeating the request with the same Idempotency-Key returns the original response with the Idempotent-Replayed: true header, without generating a duplicate key. Never generate without that header.
GET/keys

List keys

Filters: status, gameId, batch, search, limit, cursor.
curl "https://steamwave.com.br/api/v1/reseller/keys?status=USED&limit=50" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"
GET/keys/{code}

Look up a key

The key's status and, once activated, its activation history.
curl "https://steamwave.com.br/api/v1/reseller/keys/XXXXX-XXXXX-XXXXX-XXXXX" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"
GET/batches

List batches

History of the bulk generations made through the API and the dashboard.
curl "https://steamwave.com.br/api/v1/reseller/batches" \
  -H "Authorization: Bearer $STEAMWAVE_TOKEN"

Errors

Error responses always follow the same shape, with a stable code for programmatic handling.

JSON response
{ "error": { "code": "insufficient_balance", "message": "…" } }
HTTPcodeMeaning
401missing_token / invalid_tokenToken missing, invalid or revoked
402insufficient_balanceAvailable balance lower than the cost
403api_not_availableAccount without API access (paid plan or Onda I goal required)
403subscription_inactivePlan inactive or expired
404game_not_foundGame or key not found
409game_not_readyManifest still syncing
400idempotency_key_requiredIdempotency-Key header missing
409idempotency_in_progressRetried before the first request finished
429monthly_limit_exceededPlan's monthly cap reached
429rate_limitedRate limited — see retryAfter

Monetary values are always in BRL cents — divide by 100 before displaying them.

Take the docs with you

Download the full markdown or copy a ready-made prompt to paste into ChatGPT, Claude or Cursor and have the integration written for you.