Skip to main content
GET
Stream listings as they appear and disappear
A Server-Sent Events feed of the catalogue changing. One connection replaces any polling loop. Polling cannot answer “what is new?” cheaply — every client that tries ends up re-reading the same first page on a timer, and the answer is almost always “nothing”. It also cannot answer “what is gone?” at all: a poller only discovers an item sold by trying to buy it and failing. This endpoint pushes both. Authentication required. Send your key as Authorization: Bearer csb_pub_....

Query parameters

Filters are applied on our side, before anything is sent to you. They exist to save your bandwidth — one stream already carries the whole catalogue, so you never need several connections to cover different segments.
number
Only stream listings at or above this USD price.
number
Only stream listings at or below this USD price.
string
Only stream this category, e.g. Rifle, Knife, Gloves.
string
Only stream this rarity tier, e.g. Classified, Covert.
string
Only stream this wear bucket: Factory New, Minimal Wear, Field-Tested, Well-Worn, Battle-Scarred.
string
Exact market_hash_name (case-insensitive) — stream one specific item.
string
StatTrak™ filter. only or exclude.
string
Souvenir filter. only or exclude.
string
instant or hold. Narrows new events to one delivery bucket — a withdrawal bot subscribing with delivery=instant never sees an item it cannot ship today.gone events are never filtered: you may be holding the item from before your filter existed, and a missed removal is the ghost listing this feed exists to prevent.
string
Resume after this event id. Use only if your client cannot send the Last-Event-ID header — the header is the standard mechanism and is preferred.
string
Event types to receive, comma-separated: new, update, gone. Default: all three.update is about 80% of the feed, almost all of it price changes. If you only buy new listings and drop sold ones, events=new,gone gives you the same picture of what is for sale at about a fifth of the bytes. Leave out gone and you keep listings that have already sold.

Events

Listing
A listing entered the catalogue. The payload is exactly the Listing object GET /v1/listings returns, including listed_at.This fires for genuinely new inventory and for re-listings — items returning from cancelled orders, expired trade offers, or released holds. A re-listed item is new to you even though it existed before.One listing per physical skin, the same rule as GET /v1/listings and the snapshot. When the same skin is on sale through more than one supplier, only the cheapest copy is announced; the others are not. If a cheaper copy appears later, the copy you hold is retired with gone and the cheaper one arrives as new. If the copy you hold sells and another remains, that one arrives as new. Your view therefore never carries two prices for one skin, and it matches the snapshot at any moment.
Listing
A listing you already received changed: its price_usd moved, or float_value / paint_seed arrived after its new event. The payload is the full Listing object, same shape as new, with the current values. Replace your copy by id; if you have no listing with that id yet, add it.With new, update and gone you can keep the whole catalogue yourself — load it once from the snapshot, then apply the stream — instead of polling GET /v1/listings. Filters apply to update like to new, except min_price / max_price: a listing you hold that reprices out of your range still reaches you, so you never keep it at an old price. Some markets send float and pattern a few minutes after the lot goes on sale, which is why they can come in an update. Sticker wear comes as the market reports it: when the market does not know it, it is null both here and in /v1/listings.Lots from $100 are priced against the next listing of the same item, so an update also comes when that other listing changes. Still send max_price_usd with your order: the price is checked again at purchase, and a higher one is refused with price_moved, never charged.
object
A listing left the catalogue — sold, reserved, or withdrawn — or stopped standing for its skin because a cheaper copy of the same skin appeared (see new). The payload is { "id": "..." }. A gone for an id you never received is normal: ignore it.Act on this one. Dropping items as they sell is the difference between your buy calls succeeding and your buy calls discovering the item was already gone. This is the half of the picture polling cannot give you at any frequency.
object
Your Last-Event-ID is older than the retained history, so a replay would be incomplete. Payload is { "reason": "last_event_id_expired", "detail": "..." }. The same event with "reason": "stream_rebased" arrives on an open connection, once, when the rules the feed follows change (as on October 28, 2026) and a view built before cannot be patched forward; the connection is then closed.Re-read GET /v1/listings?sort=newest (or reload the snapshot) to rebuild your view, then reconnect without Last-Event-ID. We send this rather than silently handing you a partial replay you would mistake for a complete one.

Reconnecting without gaps

Every event carries an id. Send the last id you processed back as the Last-Event-ID header on reconnect and you receive exactly what you missed — including across our deploys, which drop open connections by design. A : heartbeat comment arrives every 25 seconds. Treat a longer silence as a dead connection and reconnect; browsers’ EventSource does this and resends Last-Event-ID for you.

Limits

Three concurrent streams per API key. The connection itself is not rate-limited — once open, events flow as fast as the catalogue changes. A new event goes out about 0.3 seconds after a listing enters the catalogue, to every key at the same moment, so polling /v1/listings cannot see a listing sooner. See polling versus the stream. A fourth connection answers 429 too_many_streams with Retry-After: 90. A connection that dropped without closing keeps its slot for up to 90 seconds, so a reconnect right after a network blip may have to wait that long. A connection that falls more than 8 MB behind (about 40 seconds of the full feed) is closed. Reconnect with Last-Event-ID and you continue from the last event you processed. If it keeps happening, your client reads slower than the feed arrives: narrow it with events and the filters above.

Example request

Example stream

Example client

EventSource cannot set an Authorization header — in a server-side runtime use an SSE client that can (or pass the key however your HTTP client allows). The snippet above shows the event handling, not the auth.

Error codes

If you are streaming, you do not need to poll /v1/listings on a timer at all — keep it for your initial catalogue load and for recovering after a resync. If you cannot hold a long-lived connection, the next best thing is GET /v1/listings with available_after, which turns each poll into a delta read.

Authorizations

Authorization
string
header
required

Send your key as a Bearer token on every request: Authorization: Bearer csb_pub_.... Generate keys in your CSBoard profile. Calls made with a key are metered only by that key's own limits — there is no per-IP limit on top — and every answer carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Bucket for the bucket the call spent. See Rate limits.

Query Parameters

min_price
number

Only stream listings at or above this USD price.

max_price
number

Only stream listings at or below this USD price.

category
string

e.g. Rifle, Knife, Gloves.

rarity
string

e.g. Classified, Covert.

wear
enum<string>

Exact wear name.

Available options:
Factory New,
Minimal Wear,
Field-Tested,
Well-Worn,
Battle-Scarred
name
string

Exact market_hash_name (case-insensitive).

stat_trak
enum<string>

Filter StatTrak™ items.

Available options:
only,
exclude
souvenir
enum<string>

Filter Souvenir items.

Available options:
only,
exclude
delivery
enum<string>

Narrow new events to one delivery bucket (instant or hold). gone events are never filtered — a missed removal is the ghost listing this feed exists to prevent.

Available options:
instant,
up_to_12h,
hold
last_event_id
string

Resume after this event id. Use only if your client cannot send the Last-Event-ID header.

min_refund_percent
number

Narrow new events to listings whose refund_percent is at least this (0-100). gone events are never filtered.

Required range: 0 <= x <= 100
events
string

Event types to receive, comma-separated: new, update, gone. Default: all three. update is about 80% of the feed, almost all price changes; events=new,gone keeps what is for sale at about a fifth of the bytes.

Example:

"new,gone"

Response

An open SSE stream. Stays open until you disconnect.

The response is of type string.