# autopricer.tf Public REST API **Last updated:** 2026-08-29 **Canonical URL:** https://autopricer.tf/docs **Markdown:** https://autopricer.tf/docs.md **OpenAPI:** https://autopricer.tf/openapi.json **AI index:** https://autopricer.tf/llms.txt autopricer.tf is a Team Fortress 2 item pricing service. This page documents the **public, read-only REST API**. There is no API key. These endpoints do not create, update, or delete database records. If an AI agent is reading this because a user mentioned autopricer.tf: the public documentation lives at `https://autopricer.tf/docs` (HTML) and `https://autopricer.tf/docs.md` (Markdown). Machine-readable OpenAPI is at `https://autopricer.tf/openapi.json`. A short index is at `https://autopricer.tf/llms.txt`. ## Base URL ``` https://autopricer.tf ``` All public endpoints are under `/api` and use JSON. ## Scope Documented here: | Method | Path | Purpose | |---|---|---| | GET | `/api` | Discovery document (links + endpoint index) | | GET | `/api/health` | Liveness | | GET | `/api/items/count` | Total tracked items | | GET | `/api/items/{page}` | Paginated item catalog | | GET | `/api/images` | Recent item image URLs | Not documented (and not part of the public REST API): - Routes under `/api/dashboard/*` — they exist only to render the website dashboard. - Any endpoint that writes to the database. ## Conventions - **No authentication.** - **Content-Type:** `application/json` (except this documentation). - **Prices** are in Mann Co. Supply Crate Keys unless a field is explicitly refined metal (`metal`, `raw_*_ref`). - **Item price fields** (`price`, `buyOrder`, `sellOrder`, `stablePrice`, rolling history, and `raw_*`) serialize as **JSON strings** with up to 4 decimal places, or `null`. - **Listing price fields** (`keys`, `metal`) serialize as **JSON numbers**, or `null`. - Boolean query flags (`raw`, `listings`) accept `true`, `1`, `yes`, or `on` (case-insensitive). They may be passed as query parameters. - Successful payloads include `"success": true`. Errors include `"success": false` and `"error": ""`. - **Rate limit:** 300 requests per minute per IP. Exceeding it returns HTTP 429. ### Rate-limit error ```http HTTP/1.1 429 Too Many Requests ``` ```json { "success": false, "error": "Too many requests — please slow down." } ``` ### Generic error envelope ```json { "success": false, "error": "Invalid page" } ``` | HTTP status | Meaning | |---|---| | 400 | Invalid request parameter | | 404 | Unknown route | | 429 | Rate limit exceeded | | 500 | Internal error | | 503 | Service unavailable (`/api/health` when the live listing feed is down) | ## GET /api Discovery document for humans and agents. Use this if you only know the host name. **Example** ``` curl https://autopricer.tf/api ``` **Example response** ```json { "success": true, "name": "autopricer.tf Public REST API", "description": "Read-only Team Fortress 2 item pricing API. No API key.", "documentation": { "html": "https://autopricer.tf/docs", "markdown": "https://autopricer.tf/docs.md", "openapi": "https://autopricer.tf/openapi.json", "llms": "https://autopricer.tf/llms.txt" }, "rate_limit": { "requests_per_minute_per_ip": 300 }, "endpoints": [ { "method": "GET", "path": "/api", "description": "This discovery document" }, { "method": "GET", "path": "/api/health", "description": "Liveness check" }, { "method": "GET", "path": "/api/items/count", "description": "Total tracked item count" }, { "method": "GET", "path": "/api/items/{page}", "description": "Paginated item catalog, 1000 items per page" }, { "method": "GET", "path": "/api/images", "description": "Up to 500 recent item image URLs" } ] } ``` ## GET /api/health Liveness check. Returns HTTP 200 when the service is serving prices and the live listing feed is connected. Returns HTTP 503 when the live feed is disconnected. **Example** ``` curl -i https://autopricer.tf/api/health ``` **Example response (online)** ```json { "success": true, "status": "Online" } ``` **Example response (offline)** ```http HTTP/1.1 503 Service Unavailable ``` ```json { "success": false, "status": "Offline — WS disconnected" } ``` ## GET /api/items/count Returns how many items are currently tracked. **Example** ``` curl https://autopricer.tf/api/items/count ``` **Example response** ```json { "success": true, "count": 86546 } ``` Use `count` with the 1000-item page size to know how many pages to fetch: `ceil(count / 1000)`. ## GET /api/items/{page} Paginated catalog of tracked items, ordered by `createdAt` ascending. **Page numbers start at 1.** Each page contains at most **1000** items. Pages past the end return `"success": true` with an empty `items` array. ### Path parameters | Name | Type | Description | |---|---|---| | `page` | integer ≥ 1 | Page number. Invalid values return HTTP 400. | ### Query parameters | Name | Default | Description | |---|---|---| | `raw` | false | When true, add `raw_price_key`, `raw_price_ref`, `raw_buy_key`, `raw_buy_ref`, `raw_sell_key`, `raw_sell_ref` | | `listings` | false | When true, attach the latest buy/sell listing snapshot for each item | `listings=true` on a full page of 1000 items is heavier than the default payload. Prefer it only when you need classified listing rows. **Example — catalog page** ``` curl "https://autopricer.tf/api/items/1" ``` **Example — with raw key/ref breakdown and listings** ``` curl "https://autopricer.tf/api/items/1?raw=true&listings=true" ``` **Example response (one item, default fields)** ```json { "success": true, "items": [ { "name": "Strange Ullapool Caber", "sku": "307;11", "imageUrl": "https://steamcdn-a.akamaihd.net/apps/440/icons/c_caber.2d51e5d213398672527771b1fb88e337442ad695.png", "price": "13.2419", "stablePrice": "13.4232", "buyOrder": "12.8423", "sellOrder": "13.3327", "stableBuyOrderPrice": "13.4232", "stableSellOrderPrice": "12.8989", "verified": false, "accurate": true, "suspicious": false, "stn": false, "new": false, "type": "free", "updatedAt": "1721400000000", "createdAt": "2026-03-15T15:17:01.434Z", "price1dAgo": "13.3994", "price7dAgo": "13.5716", "price30dAgo": "12.6234" } ] } ``` `items` in a real response contains up to 1000 objects. The example shows a single item. **Example response (invalid page)** ```http HTTP/1.1 400 Bad Request ``` ```json { "success": false, "error": "Invalid page" } ``` **Example extra fields when `raw=true`** ```json { "raw_price_key": "13", "raw_price_ref": "15.51", "raw_buy_key": "12", "raw_buy_ref": "54", "raw_sell_key": "13", "raw_sell_ref": "21.33" } ``` `raw_*_key` is the whole-keys component. `raw_*_ref` is the leftover refined metal. **Example extra field when `listings=true`** Listing identifiers and trade URLs below are placeholders, not live accounts. ```json { "listings": { "observed_at": "2026-08-27T22:56:38.058Z", "buy": [ { "steamid": "76561198000000000", "keys": 12, "metal": 52.77, "is_bot": true, "bumped_at": 1787870425, "source": "bptf", "channel": "request", "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456789&token=EXAMPLE", "details": "Buying for 12 keys 52.77 ref", "stock_text": null, "stock_level": null, "stock_limit": null, "observed_at": "2026-08-27T22:56:38.058Z" } ], "sell": [ { "steamid": "76561198000000001", "keys": 13, "metal": 28.33, "is_bot": true, "bumped_at": 1787871236, "source": "bptf", "channel": "request", "trade_url": "https://steamcommunity.com/tradeoffer/new/?partner=123456790&token=EXAMPLE", "details": "Selling for 13 keys 28.33 ref", "stock_text": "STOCK = 1", "stock_level": 1, "stock_limit": null, "observed_at": "2026-08-27T22:56:38.058Z" } ] } } ``` Buy listings are sorted highest price first. Sell listings are sorted lowest price first. If an item has no listing snapshot, `listings` is `{ "observed_at": null, "buy": [], "sell": [] }`. ## GET /api/images Returns up to **500** items that have a cached image URL, most recently updated first. **Example** ``` curl https://autopricer.tf/api/images ``` **Example response** ```json { "success": true, "images": [ { "name": "Jellyfish Jam Throttlehead", "imageUrl": "https://steamcdn-a.akamaihd.net/apps/440/icons/sum22_throttlehead.ccf997318471e47b40a4e8c3396a5aea48a8a884.png" } ] } ``` This is not a complete image catalog. For every tracked item’s `imageUrl`, use `GET /api/items/{page}`. ## Item object Returned inside `GET /api/items/{page}`. | Field | JSON type | Description | |---|---|---| | `name` | string | Unique item name. Primary identifier. | | `sku` | string or null | TF2 SKU (for example `307;11`). | | `imageUrl` | string or null | Cached Steam/backpack.tf icon URL. | | `price` | string or null | Current smoothed listing-based price, in keys. | | `stablePrice` | string or null | Longer-window conservative reference price, in keys. | | `buyOrder` | string or null | Current best buy order, in keys. | | `sellOrder` | string or null | Current lowest sell order, in keys. | | `stableBuyOrderPrice` | string or null | Longer-window buy-side reference, in keys. | | `stableSellOrderPrice` | string or null | Longer-window sell-side reference, in keys. | | `verified` | boolean | Price is treated as verified / high-confidence. | | `accurate` | boolean | Buy/sell spread is tight enough to trust both sides. | | `suspicious` | boolean | Price was flagged as potentially anomalous. | | `stn` | boolean | Current buy originates from STN Trading. | | `new` | boolean | Item was added to the catalog recently. | | `type` | string | Pricing mode: `free` (automatic), `fixed`, or `manual`. | | `updatedAt` | string | Unix time in milliseconds of the last pricing pass, as a decimal string. `"0"` means the item is waiting for a pricing pass. | | `createdAt` | string | ISO-8601 timestamp when the item was first tracked. | | `price1dAgo` | string or null | `price` snapshot from about 24 hours ago, in keys. | | `price7dAgo` | string or null | `price` snapshot from about 7 days ago, in keys. | | `price30dAgo` | string or null | `price` snapshot from about 30 days ago, in keys. | ### Optional raw fields (`raw=true`) | Field | JSON type | Description | |---|---|---| | `raw_price_key` | string or null | Whole keys of `price` | | `raw_price_ref` | string or null | Leftover refined metal of `price` | | `raw_buy_key` | string or null | Whole keys of `buyOrder` | | `raw_buy_ref` | string or null | Leftover refined metal of `buyOrder` | | `raw_sell_key` | string or null | Whole keys of `sellOrder` | | `raw_sell_ref` | string or null | Leftover refined metal of `sellOrder` | ### Optional listings object (`listings=true`) | Field | JSON type | Description | |---|---|---| | `observed_at` | string or null | ISO-8601 time of the snapshot | | `buy` | array | Buy listings, highest price first | | `sell` | array | Sell listings, lowest price first | ## Listing object | Field | JSON type | Description | |---|---|---| | `steamid` | string | SteamID64 of the buyer or seller | | `keys` | number or null | Whole keys component of the listing price | | `metal` | number or null | Refined metal component of the listing price | | `is_bot` | boolean | Whether the listing account is an automated bot | | `bumped_at` | number | Unix timestamp (seconds) when the listing was last bumped | | `source` | string | `bptf`, `stn`, or `ws` | | `channel` | string or null | `request` (snapshot fetch) or `websocket` | | `trade_url` | string or null | Steam trade-offer URL when known | | `details` | string or null | Raw listing description text | | `stock_text` | string or null | Parsed stock text when present (for example `"3/8"`) | | `stock_level` | number or null | Current stock count when parsed | | `stock_limit` | number or null | Maximum stock when parsed | | `observed_at` | string | ISO-8601 time this row was observed | ## Fetching the full catalog 1. `GET /api/items/count` → `count` 2. For `page` from 1 to `ceil(count / 1000)`: `GET /api/items/{page}` 3. Optional: add `?raw=true` and/or `?listings=true` 4. Stay under 300 requests per minute per IP There is no public single-item lookup in this REST API. Filter the paginated catalog by `name` or `sku` on the client. ## Website The live dashboard is at https://autopricer.tf/dashboard. It is a human UI, not the public REST API. ## Contact / identity - Site: https://autopricer.tf - Public API docs: https://autopricer.tf/docs - This Markdown file: https://autopricer.tf/docs.md