> ## Documentation Index
> Fetch the complete documentation index at: https://assetpay.gg/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deposits

> Process skin deposits end to end: the deposit flow, single- and multi-item requests, request fields, rate limits, and the exact response you get back.

A deposit is when a user sells their skin to your platform. The user sends their item via a Steam trade offer, and you receive the value as balance.

## The Deposit Flow

<Steps>
  <Step title="Fetch inventory">
    Call `GET /client/inventory` to get the user's tradeable items with current offer prices.
  </Step>

  <Step title="User selects items">
    Display the inventory in your UI. The user picks one or more items to sell.
  </Step>

  <Step title="Initiate deposit">
    Call `POST /client/trading/deposit` with the selected items and their offer prices.
  </Step>

  <Step title="Trade offer sent">
    AssetPay sends a Steam trade offer to the user. The trade moves to `active` — sitting in the user's Steam inbox awaiting acceptance.
  </Step>

  <Step title="User accepts">
    The user accepts the trade offer in Steam. The trade moves to `hold`.
  </Step>

  <Step title="Hold period (CS2 only)">
    For CS2, Steam enforces a 7-day trade protection period. The trade stays in `hold` until it ends. Rust trades skip this step entirely and transition `active → completed` directly.
  </Step>

  <Step title="Completed">
    After the hold period (CS2) or immediately after acceptance (Rust), the trade reaches `completed`. You receive a callback and credit the user's balance.
  </Step>
</Steps>

## Single-Item Deposit

```http theme={null}
POST https://api.assetpay.gg/client/trading/deposit
Content-Type: application/json
Authorization: CLIENT_TOKEN

{
  "items": [
    { "itemId": "a1b2c3d4-...", "price": 10.75 }
  ],
  "game": "730",
  "externalId": "dep_unique_123"
}
```

## Multi-Item Deposit

You can deposit multiple items in a single trade. Pass them all in the `items` array:

```http theme={null}
POST https://api.assetpay.gg/client/trading/deposit
Content-Type: application/json
Authorization: CLIENT_TOKEN

{
  "items": [
    { "itemId": "a1b2c3d4-...", "price": 10.75 },
    { "itemId": "b2c3d4e5-...", "price": 5.20 }
  ],
  "game": "730",
  "externalId": "dep_multi_456"
}
```

For Rust items that are stackable, you can specify an `amount`:

```json theme={null}
{ "itemId": "...", "price": 0.15, "amount": 3 }
```

## Request Fields

| Field            | Type    | Required | Description                                                                             |
| ---------------- | ------- | -------- | --------------------------------------------------------------------------------------- |
| `items`          | array   | Yes      | Array of items to deposit (min 1, max 250)                                              |
| `items[].itemId` | string  | Yes      | Item ID from the inventory response                                                     |
| `items[].price`  | number  | Yes      | Offer price in USD. Must match the current offer price returned by `/client/inventory`. |
| `items[].amount` | number  | No       | Quantity for stackable items (default: 1, max: 10000)                                   |
| `game`           | string  | No       | `"730"` (CS2) or `"252490"` (Rust). Defaults to `"730"`.                                |
| `externalId`     | string  | No       | Your unique tracking ID (max 128 chars). Stored as `externalId` on the trade.           |
| `isInstant`      | boolean | No       | Whether to request instant credit (default `false`).                                    |

## Rate Limits

Two layers apply to `/client/trading/deposit`:

* **Per-merchant tier throttle** (shared across all clients): 500 req/min verified, 5 req/min unverified.
* **Per-client guard** (scoped per merchant + client Steam ID):
  * Max **5 concurrent active deposits** (not-yet-accepted: `initiated | active`) — `TOO_MANY_ACTIVE_TRADES` (HTTP 429).
  * Max **10 deposits per 5-minute rolling window** — `RATE_LIMITED` (HTTP 429).

These guard against runaway behavior on a single user. They run before pricing/inventory fetches, so a rate-limited request fails fast and cheap.

## Response

The response contains the full trade object:

```json theme={null}
{
  "requestId": "...",
  "success": true,
  "data": {
    "id": "trade-uuid",
    "type": "deposit",
    "source": "client",
    "status": "initiated",
    "game": "730",
    "externalId": "dep_unique_123",
    "merchantId": "merchant-uuid",
    "clientUserId": "client-uuid",
    "clientSteamID": "76561198012345678",
    "clientTradeUrl": "https://steamcommunity.com/tradeoffer/new/?partner=...",
    "items": [...],
    "totalPrice": 10.75,
    "isInstant": true,
    "createdAt": "2026-03-04T10:00:00.000Z",
    "updatedAt": "2026-03-04T10:00:00.000Z"
  }
}
```

## Instant Deposits

`isInstant` defaults to `false`, so a deposit is fully held unless you ask for instant credit. Sending `isInstant: true` fails with `INSTANT_DEPOSITS_DISABLED` if instant deposits are off for your account. When instant credit applies, AssetPay calculates how much of the deposit value can be credited instantly based on collateral, rather than waiting for the full 7-day hold period.

When a deposit enters `hold` status, the trade object includes:

* `preCredit` - the amount credited instantly (USD)
* `pendingCredit` - the remaining amount held until the hold period ends
* `collateral` - breakdown of collateral sources

If `isInstant` is `false` or omitted, the entire amount waits until `completed`.

The `collateral` field in the inventory response tells you the total instant credit available for that user before they start depositing.

## External ID

The `externalId` field is your own tracking identifier. Use it to link AssetPay trades back to records in your system.

<Warning>
  External IDs must be unique per trade. Reusing an ID will result in an `EXTERNAL_ID_EXISTS` error.
</Warning>

## Balance Handling for Deposits

**When to credit:**

| Event       | Action                                                |
| ----------- | ----------------------------------------------------- |
| `hold`      | Credit `preCredit` amount (if using instant deposits) |
| `completed` | Credit `pendingCredit` (the remaining held amount)    |
| `reverted`  | Reverse any instant credit that was applied           |

**When NOT to credit:**

| Event       | Action                                                        |
| ----------- | ------------------------------------------------------------- |
| `initiated` | Just acknowledge                                              |
| `active`    | Just acknowledge — Steam offer sent, awaiting user acceptance |
| `failed`    | No credit needed                                              |
| `canceled`  | No credit needed                                              |
| `declined`  | No credit needed (user declined the offer)                    |

See the [Callbacks](/docs/guides/callbacks) guide for full details on processing each event.
