Purchasing keys through the API

This guide walks through buying wholesale keys end-to-end via the Eneba API: finding an auction, paying with your EUR wallet, waiting for the checkout to complete, exporting the purchased keys and downloading the resulting archive.

The API checkout flow currently supports wholesale auctions only — non-wholesale listings cannot be purchased through the API at this time.

This flow requires the wholesale buyer role on your account — purchasing and key export will reject calls made without it. Contact Eneba support if you receive a 403 or an access-denied error.

Requirements

  • You have generated API credentials and obtained an access_token — see the Getting Started guide for the OAuth flow, environment URLs and authentication header.
  • Your EUR wallet has enough balance to cover the purchase. Payment is always deducted from the EUR wallet regardless of the auction currency.

Sequence diagram

The following sequence shows the successful end-to-end flow between your client, the Eneba API and the S3 download endpoint that serves the keys archive.

S3EnebaClientS3EnebaClientloop[poll until COMPLETED]loop[poll until COMPLETED]P_wholesaleAuctions (search)auctionId, wholesaleStock, wholesalePriceS_purchaseWholesaleAuctionsorderId, actionIdA_action(actionId)O_ordersentryTokenO_exportOrderKeys(entryToken)O_orderExport(entryToken)downloadUrlGET downloadUrlexport.zip

1. Find the auction

Search for the product you want to buy and pick the auction whose id you will purchase. Filter by merchant when several merchants list the same product.

Use the P_wholesaleAuctions query.

query getWholesaleAuctions($search: String, $merchantSearch: String) {
  P_wholesaleAuctions(search: $search, merchantSearch: $merchantSearch) {
    edges {
      node {
        id
        product { name }
        wholesalePrice { amount currency }
        wholesaleStock
        merchant { displayName slug }
      }
    }
  }
}

Variables:

{ "search": "call of duty modern warfare" }

Note the id of the desired auction — that is the auctionId you will pass to the next step. The wholesaleStock field tells you how many keys are currently available.

Price amounts are returned in cents — divide by 100 to display the value (e.g. 1500€15.00).

2. Submit the purchase

Submit the purchase using the S_purchaseWholesaleAuctions mutation. Each call initiates an asynchronous checkout and returns an actionId you can poll, plus the orderId of the created order.

mutation PurchaseWholesaleAuctions($input: S_API_PurchaseWholesaleAuctionsInput!) {
  S_purchaseWholesaleAuctions(input: $input) {
    success
    orderId
    actionId
  }
}

Variables:

{
  "input": {
    "items": [
      {
        "auctionId": "<id from step 1>",
        "quantity": 1
      }
    ]
  }
}

A single request supports up to 10 auction items, with quantity between 1 and 2000 per item. All auctionId values within one request must be unique.

A success: true response only confirms the checkout was queued — it does not mean the purchase has completed. Poll A_action with the returned actionId (step 3) to track the actual outcome.

If the auction does not have enough stock when the checkout is processed, the action will end in FAILED state at step 3. Note that the wholesaleStock value reported by P_wholesaleAuctions reflects stock at query time and can change before your purchase runs.

3. Poll the checkout status

The checkout runs in the background. Poll the A_action query with the actionId returned in step 2 until state reaches a terminal value.

query getAction($actionId: A_Uuid!) {
  A_action(actionId: $actionId) {
    id
    state
  }
}

Variables:

{ "actionId": "<actionId from step 2>" }
StateMeaning
NEWCheckout is still being processed
COMPLETEDPurchase succeeded
FAILEDPurchase failed

Poll every 2–3 seconds. The query returns null if the action has not started yet, or if 24 hours have passed since it was initiated.

4. Get the order's entryToken

Once the action is COMPLETED, fetch the order to obtain the entryToken required to export the keys, and to confirm the orderState is FULFILLED.

Use the O_orders query.

query getOrders($first: Int) {
  O_orders(first: $first) {
    totalCount
    edges {
      node {
        number
        entryToken
        orderState
        paymentState
        totalPrice { amount currency }
        createdAt
        items {
          sellableName
          quantity
          totalPrice { amount currency }
        }
      }
    }
  }
}

Only orders placed via the API checkout flow are returned here — orders the same account placed through the Eneba storefront will not appear.

Store the entryToken of the order you just placed — you'll use it in the next two steps.

5. Trigger the key export

Start the asynchronous key export with the O_exportOrderKeys mutation. A success: true response means the export has been queued; the file itself is produced in the background.

mutation exportOrderKeys($input: O_API_ExportOrderKeysInput!) {
  O_exportOrderKeys(input: $input) {
    success
  }
}

Variables:

{
  "input": {
    "entryToken": "<entryToken from step 4>"
  }
}

6. Poll the export status

Poll the O_orderExport query with the same entryToken until status reaches COMPLETED and downloadUrl is populated.

query getOrderExport($entryToken: String!) {
  O_orderExport(entryToken: $entryToken) {
    id
    status
    downloadUrl
    expired
  }
}

Variables:

{ "entryToken": "<entryToken from step 4>" }
StatusMeaning
PENDINGExport is still being generated
COMPLETEDArchive is ready and downloadUrl is populated
FAILEDExport failed — call O_exportOrderKeys again

Poll every 2–3 seconds.

The downloadUrl is a presigned S3 URL valid for 30 minutes. If the URL expires, or if expired: true is returned, call O_exportOrderKeys again with the same entryToken to produce a fresh export.

7. Download and extract the keys

Download the archive from the presigned URL and unzip it. The archive is password-protected with the email address of the Eneba account that placed the order.

curl -o export.zip "<downloadUrl>"
unzip -P "<your-account-email>" export.zip

Inside the archive, each item from the order lives in its own sub-folder containing a keys.txt file with one key per line. The folder names are generated by the server and are not exposed in the API response — list the archive contents (unzip -l export.zip) to discover them.

Copyright 2026 Eneba. All Rights Reserved. JSC “Helis play”, Gyneju St. 4-333, Vilnius, the Republic of Lithuania