> ## 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.

# Error Codes

> Complete list of error codes returned by the AssetPay API.

# Error Codes

All errors follow this format:

```json theme={null}
{
  "requestId": "...",
  "success": false,
  "error": {
    "code": 1001,
    "key": "VALIDATION_FAILED",
    "message": "The request data is invalid"
  }
}
```

Codes are grouped by domain:

| Range     | Domain                   |
| --------- | ------------------------ |
| 1-99      | Trading / marketplace    |
| 1000-1099 | Generic / infrastructure |
| 1100-1199 | Authentication / tokens  |
| 1200-1299 | Two-factor / passkeys    |
| 1300-1399 | Account / access control |
| 1400-1499 | User settings            |
| 1500-1599 | Idempotency              |
| 1600-1699 | Crypto wallet & funding  |
| 1700-1799 | Callbacks / webhooks     |
| 1800-1899 | Email                    |
| 1900-1999 | API keys / secrets       |
| 2100-2199 | Risk management          |
| 2200-2299 | Booking                  |
| 2300-2399 | Identity verification    |
| 2400-2499 | Ledger integrity         |

## General Errors

| Code | Key                   | HTTP | Description                                         |
| ---- | --------------------- | ---- | --------------------------------------------------- |
| 1001 | `VALIDATION_FAILED`   | 422  | Request body or query params failed validation      |
| 1003 | `NOT_FOUND`           | 404  | Resource not found                                  |
| 1004 | `CONFLICT`            | 409  | State conflict                                      |
| 1005 | `RATE_LIMITED`        | 429  | Too many requests                                   |
| 1006 | `SERVER_ERROR`        | 500  | Internal server error                               |
| 1007 | `SYSTEM_MAINTENANCE`  | 503  | System is in maintenance mode                       |
| 1008 | `UNPROCESSABLE`       | 422  | Request cannot be processed                         |
| 1009 | `SERVICE_UNAVAILABLE` | 503  | Deposit/withdrawal services temporarily unavailable |
| 1010 | `NO_BOTS_AVAILABLE`   | 503  | No Steam bots are configured or online              |
| 1011 | `FLEET_DEGRADED`      | 503  | Steam bot fleet is degraded; retry shortly          |

## Authentication Errors

| Code | Key                        | HTTP | Description                             |
| ---- | -------------------------- | ---- | --------------------------------------- |
| 1100 | `UNAUTHORIZED`             | 401  | Authentication required                 |
| 1101 | `INVALID_CREDENTIALS`      | 401  | Invalid email/username or password      |
| 1102 | `INVALID_TOKEN`            | 401  | Token is invalid                        |
| 1108 | `MISSING_BEARER`           | 401  | Authorization header missing or invalid |
| 1110 | `TOKEN_INVALID_OR_EXPIRED` | 401  | Token is invalid or expired             |
| 1111 | `TOKEN_EXPIRED`            | 401  | Token has expired                       |

## Account / Access Errors

| Code | Key                | HTTP | Description                                       |
| ---- | ------------------ | ---- | ------------------------------------------------- |
| 1300 | `FORBIDDEN`        | 403  | You don't have permission to access this resource |
| 1301 | `ACCOUNT_DISABLED` | 403  | Account has been disabled                         |

## API Key Errors

| Code | Key                        | HTTP | Description                                                               |
| ---- | -------------------------- | ---- | ------------------------------------------------------------------------- |
| 1900 | `MISSING_API_KEY`          | 401  | No `api-key` header provided                                              |
| 1901 | `INVALID_API_KEY`          | 401  | API key not found or invalid                                              |
| 1902 | `API_KEY_REVOKED`          | 401  | API key has been revoked                                                  |
| 1903 | `API_KEY_SCOPE_DENIED`     | 403  | API key doesn't have the required scope                                   |
| 1904 | `API_KEY_IP_DENIED`        | 403  | Request IP is not in the key's whitelist                                  |
| 1908 | `INSUFFICIENT_SCOPE`       | 403  | Insufficient scope permissions for this operation                         |
| 1910 | `API_SECRET_INVALID`       | 401  | Invalid API secret                                                        |
| 1915 | `NO_API_SECRET_CONFIGURED` | 400  | Merchant has no API secret configured (required for client-token signing) |

## Trading Errors

Returned by deposit, withdrawal, inventory, and market endpoints.

| Code | Key                        | HTTP | Description                                                 |
| ---- | -------------------------- | ---- | ----------------------------------------------------------- |
| 1    | `EXTERNAL_ID_EXISTS`       | 409  | External ID already exists for this merchant                |
| 2    | `MISSING_ITEMS`            | 400  | No items were provided in the request                       |
| 3    | `INVENTORY_FETCH_FAILED`   | 424  | Couldn't load the user's Steam inventory                    |
| 4    | `NO_OFFER_FOUND`           | 400  | No valid offer exists for this item                         |
| 5    | `TRADE_OFFER_FAILED`       | 502  | Failed to send the Steam trade offer                        |
| 6    | `TOO_MANY_ACTIVE_TRADES`   | 429  | User has too many pending trades (per-client deposit guard) |
| 7    | `USER_NOT_TRADEABLE`       | 400  | User's Steam account can't trade                            |
| 8    | `TOO_MANY_ITEMS`           | 400  | Too many items in a single request                          |
| 9    | `ITEMS_UNAVAILABLE`        | 400  | Selected items not found or no longer available             |
| 10   | `ITEMS_NOT_ACCEPTED`       | 400  | Items are not accepted for deposit                          |
| 11   | `PRICE_CHANGED`            | 409  | Price has changed since you last fetched it                 |
| 12   | `MERCHANT_BALANCE_LOW`     | 400  | Merchant balance is too low for this withdrawal             |
| 13   | `INVALID_TRADEURL`         | 400  | Invalid or inaccessible trade URL                           |
| 14   | `LISTING_NOT_FOUND`        | 404  | Marketplace listing not found                               |
| 15   | `LISTING_PRICE_INVALID`    | 400  | Listing has an invalid or missing price                     |
| 16   | `INVALID_LISTING_ID`       | 400  | Invalid listing ID format                                   |
| 17   | `INSUFFICIENT_ITEM_AMOUNT` | 400  | Requested amount exceeds available quantity                 |
| 18   | `EXCEEDS_MAX_AMOUNT`       | 400  | Requested amount exceeds the maximum allowed                |
| 19   | `DEPOSIT_IN_PROGRESS`      | 409  | A deposit is already processing for this user               |
| 20   | `WITHDRAW_IN_PROGRESS`     | 409  | A withdrawal is already processing for this user            |
| 21   | `TRADE_NOT_FOUND`          | 404  | Trade not found                                             |
| 22   | `INVALID_STATE_TRANSITION` | 409  | Invalid trade state transition                              |
| 23   | `INVALID_TRADE_ID`         | 400  | Invalid trade ID                                            |
| 31   | `STEAM_UNAVAILABLE`        | 424  | Steam temporarily couldn't serve the request; retry shortly |
| 33   | `STEAM_RATE_LIMITED`       | 424  | Steam is rate-limiting inventory requests; retry shortly    |

## Asynchronous Trade Failure Codes

The errors above are returned **synchronously** when a call is rejected. A withdrawal that was accepted but later fails carries a separate, smaller, stable code instead — on `Item.error` (and on `Trade.error` when the whole trade failed for one shared cause), typed as [`TradeFailureCode`](/reference/types#tradefailurecode). These are **not** numeric API error codes; they appear on the trade object and in callbacks.

| `error`                    | Meaning                                                              |
| -------------------------- | -------------------------------------------------------------------- |
| `LISTING_UNAVAILABLE`      | Listing sold / delisted / out of stock                               |
| `PRICE_CHANGED`            | Price moved above your ceiling                                       |
| `TRADE_URL_INVALID`        | Recipient's Steam trade URL is invalid or escrow-blocked             |
| `STEAM_ACCOUNT_RESTRICTED` | Recipient's Steam account can't receive (VAC / ban / hold / private) |
| `MARKET_UNAVAILABLE`       | Temporary upstream / our-side issue — retry later                    |
| `PURCHASE_FAILED`          | Unclassified failure (catch-all)                                     |

`canceled` and `declined` items carry no code — the status is the reason. A `declined` withdrawal is buyer fault: your merchant wallet is refunded **minus a 2% penalty** (capped at \$9). See [Withdrawals → Per-Item Failure Reasons](/guides/withdrawals#per-item-failure-reasons) for handling guidance.

## Wallet / Funding Errors

Mostly returned by crypto wallet endpoints, but several apply to trading flows too.

| Code | Key                         | HTTP | Description                               |
| ---- | --------------------------- | ---- | ----------------------------------------- |
| 1600 | `INSUFFICIENT_BALANCE`      | 400  | Insufficient balance for this operation   |
| 1601 | `INVALID_AMOUNT`            | 400  | Invalid amount (e.g. zero or negative)    |
| 1622 | `INSTANT_DEPOSITS_DISABLED` | 503  | Instant deposits are temporarily disabled |

## Callback / Webhook Errors

| Code | Key                        | HTTP | Description                                                   |
| ---- | -------------------------- | ---- | ------------------------------------------------------------- |
| 1700 | `INVALID_SIGNATURE`        | 401  | Callback signature verification failed                        |
| 1701 | `MISSING_RAW_BODY`         | 400  | Raw request body is missing                                   |
| 1704 | `CALLBACK_URL_TEST_FAILED` | 400  | Configured callback URL did not respond with 2xx              |
| 1705 | `MERCHANT_NO_CALLBACK_URL` | 409  | Merchant has no active callback URL (withdrawals require one) |

## Risk Management Errors

| Code | Key                     | HTTP | Description                       |
| ---- | ----------------------- | ---- | --------------------------------- |
| 2100 | `INVALID_RISK_POLICY`   | 400  | Invalid risk policy configuration |
| 2101 | `RISK_POLICY_NOT_FOUND` | 404  | No active risk policy found       |
| 2103 | `CLIENT_USER_NOT_FOUND` | 404  | Client user not found             |

## Identity Verification Errors

| Code | Key                                      | HTTP | Description                                       |
| ---- | ---------------------------------------- | ---- | ------------------------------------------------- |
| 2300 | `VERIFICATION_NOT_AVAILABLE`             | 503  | Identity verification is not available            |
| 2301 | `VERIFICATION_ALREADY_VERIFIED`          | 409  | Account is already verified                       |
| 2302 | `VERIFICATION_IN_PROGRESS`               | 409  | A verification is already in progress             |
| 2303 | `VERIFICATION_PROCESS_NOT_FOUND`         | 404  | Verification process not found                    |
| 2304 | `VERIFICATION_BANNED_IDENTITY`           | 403  | This identity cannot be verified                  |
| 2305 | `VERIFICATION_ACCOUNT_CAP_REACHED`       | 409  | Maximum linked accounts reached for this identity |
| 2306 | `VERIFICATION_ALREADY_LINKED`            | 409  | Account is already linked to an identity          |
| 2307 | `VERIFICATION_IDENTITY_NOT_FOUND`        | 404  | Verified identity not found                       |
| 2308 | `VERIFICATION_SIGNICAT_ERROR`            | 502  | Verification provider returned an error           |
| 2309 | `VERIFICATION_WEBHOOK_SIGNATURE_INVALID` | 401  | Verification webhook signature is invalid         |
| 2310 | `VERIFICATION_EMAIL_REQUIRED`            | 400  | Email is required to link an existing identity    |
| 2311 | `VERIFICATION_NOT_LINKED`                | 400  | Account does not have a linked identity           |
| 2312 | `VERIFICATION_LINK_FAILED`               | 500  | Unable to link identity to this account           |

## Handling Errors

Check `success` first, then handle based on the error `code` or `key`:

```typescript theme={null}
const response = await fetch('https://api.assetpay.gg/client/trading/deposit', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': clientToken,
  },
  body: JSON.stringify(depositPayload),
});

const result = await response.json();

if (!result.success) {
  switch (result.error.key) {
    case 'PRICE_CHANGED':
      // Refetch inventory and show updated prices
      break;
    case 'ITEMS_UNAVAILABLE':
      // Remove unavailable items from selection
      break;
    case 'TOO_MANY_ACTIVE_TRADES':
    case 'DEPOSIT_IN_PROGRESS':
      // Tell user to wait for current deposit to finish
      break;
    case 'MERCHANT_BALANCE_LOW':
      // Withdrawal can't proceed, notify user
      break;
    default:
      console.error(`Trade error: ${result.error.key} (${result.error.code})`);
  }
}
```

When contacting support about an error, include the `requestId` from the response. It helps us trace the exact request in our logs.
