Skip to content

Create Deposit

POST /api/v1/merchant/create-deposit

Creates a deposit with specific Steam items. Used in the API-only integration flow after fetching inventory.

Request

Headers

HeaderRequiredDescription
X-Api-KeyYour merchant API key
Content-Typeapplication/json

Body

ParameterTypeRequiredDescription
merchant_tx_idstringYour unique transaction/order ID
gamestringGame code: csgo, rust, dota2, tf2
partnerintegerSteam trade partner ID
tokenstringSteam trade token
asset_idsstring[]Item IDs from the inventory response
result_urlstringWebhook URL — overrides your merchant-level webhook URL for this deposit (must be valid URL)
success_urlstringSuccess redirect URL (must be valid URL)
fail_urlstringFailure redirect URL (must be valid URL)
custom_currencystringCustom currency code (1–4 chars, e.g. BTC, EUR). Requires all 3 currency fields
custom_currency_multipliernumberCurrency multiplier (0.5–2.0)
custom_currency_ratenumberCurrency exchange rate (≥ 0.1)
min_pricesobjectPer-item price floor in USD, keyed by asset_id (e.g. {"38029384123": 19.50}). If an item's price at deposit time is below its floor, the deposit is rejected with item_specified_price_not_found and no trade is created. Entries ≤ 0 are ignored

Pricing & Price Lock

The deposit amount is derived from the inventory snapshot of your most recent Get Inventory call for the same Steam account (partner + token). That snapshot is cached for 5 minutes.

  • If you call create-deposit more than 5 minutes after fetching the inventory, the request fails with inventory_reload — re-fetch the inventory and retry.
  • Without min_prices, the credited amount is the price cached at deposit time, not the moment you displayed it to the user.

Protect against price drift with min_prices

Pass the optional min_prices map (keyed by asset_id, in USD) to set a per-item floor. If any item's price at deposit time is below its floor, the deposit is rejected with item_specified_price_not_found and no trade is created — so you are never credited less than you displayed. Set each floor slightly below the price you showed the user (e.g. quoted minus 1–2%). Prices are USD regardless of any custom_currency fields.

Alternative: hash-name flow

Get PricesCreate Deposit by Hash Name offers the same per-item min_price protection plus a per-transaction quote snapshot (by id), so the quote cannot be overwritten by a concurrent inventory fetch.

Response

json
{
  "success": true,
  "message": "Deposit processing with selected items",
  "data": {
    "id": 42,
    "merchant_tx_id": "order-12345",
    "status": "active",
    "amount": 36.25,
    "bot_name": "Skinslink Bot #3",
    "bot_steam_id": 76561199012345678,
    "trade_offer_id": "6912345678",
    "trade_offer_expiry_at": "2026-02-16T12:30:00Z",
    "success_url": "https://yoursite.com/deposit/success",
    "fail_url": "https://yoursite.com/deposit/failed"
  }
}

Response Fields

FieldTypeDescription
idintegerInternal trade ID
merchant_tx_idstringYour transaction ID (echoed back)
statusstringTrade status (active on success, failed on error)
amountnumberTotal deposit amount (USD)
bot_namestring | nullName of the Steam bot sending the offer
bot_steam_idinteger | nullSteam ID of the bot
trade_offer_idstring | nullSteam trade offer ID
trade_offer_expiry_atstring | nullISO 8601 timestamp when the offer expires
success_urlstringSuccess redirect URL (only present if provided in request)
fail_urlstringFailure redirect URL (only present if provided in request)

INFO

Custom currency fields (custom_currency, custom_currency_multiplier, custom_currency_rate, custom_currency_sum) are not included in the create-deposit response. Use Deposit Status to retrieve them once the trade reaches hold or completed status.

Example

bash
curl -X POST https://api.skinslink.com/api/v1/merchant/create-deposit \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "merchant_tx_id": "order-12345",
    "game": "csgo",
    "partner": 123456789,
    "token": "AbCdEfGh",
    "asset_ids": ["38029384123", "38029384124"]
  }'

To add a per-item price floor, include min_prices in the request body:

json
{
  "merchant_tx_id": "order-12346",
  "game": "csgo",
  "partner": 123456789,
  "token": "AbCdEfGh",
  "asset_ids": ["38029384123", "38029384124"],
  "min_prices": {
    "38029384123": 19.50,
    "38029384124": 4.20
  }
}

After Creating a Deposit

  1. Show the trade offer info to the user (bot name, offer ID)
  2. User accepts the trade offer in Steam
  3. Listen for webhooks or poll /merchant/deposit/status for updates

TIP

Store the trade_offer_expiry_at and remind users to accept before expiry. Expired offers are automatically canceled.

Errors

StatusMessageCause
400invalid request bodyMalformed JSON
400validation errorMissing or invalid fields (see data array for details). Includes inventory_reload — the inventory price snapshot expired (> 5 min since Get Inventory); re-fetch and retry
400item_specified_price_not_foundAn item's price at deposit time dropped below its min_prices floor. No trade is created; re-fetch the inventory for current prices
401missing authorization headerX-Api-Key header not provided
401invalid API keyAPI key not found or inactive
403merchant account is disabledMerchant account deactivated
403invalid IP: <ip>Request IP not in whitelist
404not found errorTrade or items not found
409already exist errorDuplicate merchant_tx_id
500internal errorSomething went wrong on our side

→ For domain-specific validation codes (Steam account issues, trade eligibility), see Errors.