---
title: List your bot
description: Push your trading bot's status, prices and stock to the SteamSets bot directory and the level-up calculator.
sidebar:
  icon: bot
  order: 7
---

SteamSets lists Steam trading bots in its [bot directory](https://steamsets.com/bots). The [level-up calculator](https://steamsets.com/bots/calculator) uses the same data to tell users which bots to buy sets from. Your bot keeps its listing current when it sends its status, prices and stock to one endpoint.

1. **Register the bot**

    Sign in on [steamsets.com](https://steamsets.com) with the Steam account that owns the bot, and open [Your bots](https://steamsets.com/bots/mine). Register the bot with its SteamID64, a listing name and its type. Register each bot account separately.

2. **Save the bot key**

    SteamSets shows the bot key (`ssbot_…`) one time only, and stores only a hash of it. Each bot has its own key. This key is not a developer API key, and it works only for pushing that bot's data.

3. **Pay the listing fee**

    Listing costs a one-time fee of 1 TF2 key. A new bot stays pending until staff approve it. You can push data while the bot is pending, so the listing is complete when it goes live.

4. **Push updates**

    Send the bot's data to `POST /v1/bot.update`, as the next sections show.

## Push updates

```http
POST https://api.steamsets.com/v1/bot.update
Authorization: Bearer ssbot_…
Content-Type: application/json
```

A successful push gets `204 No Content`:

- A bad or missing bot key gets `401 Unauthorized`.
- An invalid body gets `400 Bad Request`, with the reason in the response.

Push when your prices or stock change, and at least every 30 minutes. A bot with no push for 1 hour shows as stale. A bot with no push for 24 hours is hidden from the directory.

### Partial updates

Every field is optional:

- **Missing field.** A field you leave out keeps its stored value. This applies down to each single price and count.
- **Zero.** `0` removes a value. For example, `"buy": 0` stops buying.
- **Set stock.** `sets.stock` replaces the full set stock when you send it. Send the complete stock each time, not the change.

So a full push and a push that changes only the TF2 sell price both work.

### Body

```json
{
  "online": true,
  "sets": {
    "stock": {
      "normal": { "440": 12, "730": 3, "570": 5 },
      "foil": { "730": 1 }
    },
    "limits": { "maxPerApp": 5 },
    "prices": {
      "tf2": { "sell": 9.5, "buy": 11 },
      "cs2": { "sell": 9, "buy": 10.5 },
      "hydra": { "sell": 8 },
      "tod": { "sell": 4 },
      "gems": { "sell": 450, "buy": 380 }
    }
  },
  "gems": {
    "stock": 250000,
    "prices": { "tf2": { "sell": 3200, "buy": 3500 } }
  },
  "keys": { "tf2": 40, "cs2": 12, "hydra": 0, "tod": 3 },
  "crypto": {
    "prices": [
      { "coin": "btc", "sell": "0.0000038" },
      { "coin": "ltc", "sell": "0.00071", "buy": "0.0005" }
    ]
  }
}
```

Send only the markets that your bot trades. A level-up bot that sells sets for TF2 keys needs only `online`, `sets.stock` and `sets.prices.tf2`.

| Field                             | Description                                                                                                            |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `online`                          | `true` when the bot accepts trades.                                                                                    |
| `sets.stock.normal`               | App ID to the number of complete normal sets that the bot holds.                                                       |
| `sets.stock.foil`                 | App ID to the number of complete foil sets that the bot holds.                                                         |
| `sets.limits.maxPerApp`           | The maximum number of sets of one app that the bot sells to one user. `0` means no limit.                              |
| `sets.prices.{tf2,cs2,hydra,tod}` | Sets per key, or per Tour of Duty ticket.                                                                              |
| `sets.prices.gems`                | Gems per set.                                                                                                          |
| `gems.stock`                      | The number of gems that the bot holds.                                                                                 |
| `gems.prices.{tf2,cs2,hydra,tod}` | Gems per key, or per ticket.                                                                                           |
| `keys.{tf2,cs2,hydra,tod}`        | The number of keys and tickets that the bot holds.                                                                     |
| `crypto.prices[]`                 | One entry for each coin. `coin` is the ticker (`btc`, `eth`, `ltc`), and `sell` and `buy` are coins per set, as decimal strings. |

The [`bot.update` reference](/reference/bots/bot-update) lists every field with its type.

### Sell and buy

Both sides are from the point of view of the user who trades with your bot:

- **`sell`** is the price at which your bot sells. `"tf2": { "sell": 9.5 }` means that the user gets 9.5 sets for 1 TF2 key.
- **`buy`** is the price at which your bot buys. `"tf2": { "buy": 11 }` means that the user gives 11 sets and gets 1 TF2 key.

A set is complete when the bot holds every card of it. Count only the sets that your bot sells. The calculator sends users to your bot for the stock you report, so stock that is too high sends users for sets that the bot does not have.

### Examples

A full push from a level-up bot:

```bash
curl -X POST https://api.steamsets.com/v1/bot.update \
  -H "Authorization: Bearer $STEAMSETS_BOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"online":true,"sets":{"stock":{"normal":{"440":12,"730":3}},"limits":{"maxPerApp":5},"prices":{"tf2":{"sell":9.5,"buy":11}}},"keys":{"tf2":40}}'
```

Stop buying sets for TF2 keys, and change nothing else:

```bash
curl -X POST https://api.steamsets.com/v1/bot.update \
  -H "Authorization: Bearer $STEAMSETS_BOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sets":{"prices":{"tf2":{"buy":0}}}}'
```

Mark the bot as offline:

```bash
curl -X POST https://api.steamsets.com/v1/bot.update \
  -H "Authorization: Bearer $STEAMSETS_BOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"online":false}'
```

## Use your steam.supply or steamtradebots.com code

If your bot already pushes to steam.supply or steamtradebots.com, you can keep that code. Change the base URL, and use your SteamSets bot key:

| Your current format                              | SteamSets URL                                                                  |
| ------------------------------------------------ | ------------------------------------------------------------------------------ |
| steam.supply `POST /API/{KEY}/updateBot`         | `POST https://api.steamsets.com/compat/steamsupply/API/{KEY}/updateBot`        |
| steam.supply `GET /API/{KEY}/update/?tf2rate=…`  | `GET https://api.steamsets.com/compat/steamsupply/API/{KEY}/update/?tf2rate=…` |
| steamtradebots.com `POST /api/v1/bot/update.php` | `POST https://api.steamsets.com/compat/steamtradebots/api/v1/bot/update.php`   |

The steamtradebots.com URL takes the key as `Authorization: Bearer`, as `X-API-Key`, or as `?api_key=`.

These formats give the same result as `bot.update`. If you write new code, use `bot.update`, because it is the only format that covers every market in one request.
