Skip to main content

Overview

The AssetPay price feed is a low-latency stream of item and price changes, delivered over Redis Streams at feed.assetpay.gg. Instead of polling the REST API, you tail a stream and react to each change as it happens - items entering the pool, items leaving, and price updates. Each consumer reads a snapshot of current state once, then tails the stream for incremental changes. If you fall behind or reconnect, you re-read the snapshot and resume - no events are lost.
The feed requires separately provisioned credentials. If you only need your own priced view of the market (the CS2 pool items /secure/market?source=internal returns, priced for your account), the WebSocket Market Updates event covers that with just your API key.

Connection

rediss://feed.assetpay.gg:6382 - TLS only; plaintext connections are rejected.
The feed is TLS-encrypted with a private CA. To connect you need:
  • The CA certificate (ca.crt) - AssetPay provides this; your client must trust it.
  • An ACL username + password - AssetPay issues these per integration.
  • SNI / servername set to feed.assetpay.gg when validating the certificate.
The feed is a raw Redis (TCP) endpoint, so feed.assetpay.gg resolves directly to the origin - it is not proxied like the HTTP API.
Your ACL user is scoped to your own stream and snapshot. Reading anything else returns NOPERM.

Streams & keys

AssetPay issues two key names alongside your credentials:

Event format

Each stream entry has two fields: type and data (a JSON string).
string
item.add, item.remove, or price.update.
JSON string
The event payload - see below.

item.add

A new item entered the pool (or its block was refreshed):
id, appid, assetId, status, tradable, delivery and prices are always present. prices is keyed by marketplace, each entry { price, updatedAt }, and holds every marketplace the item is priced on in your stream. Every other field, including rarity, color, phase, amount, stickers and charm, is omitted when it has no value. The snapshot hash stores the same block.

price.update

An existing item’s price changed:

item.remove

An item left the pool (sold or pulled), or is no longer priced on your stream:
Removals can be repeated for a while after an item leaves. Treat a remove for an id you don’t hold as a no-op. Read the fields you need and ignore any you don’t recognise.

Consuming the feed

1

Capture the stream position

Record the latest stream id (XREVRANGE <stream> + - COUNT 1) before seeding, so anything added during seeding replays from the stream - no gap.
2

Seed from the snapshot

HGETALL the snapshot hash to load current state in one round trip. Each field is an item id; each value is the JSON block.
3

Tail the stream

XREAD BLOCK 0 STREAMS <stream> <lastId> in a loop, applying each event and advancing lastId to each entry’s id.
4

Resync on disconnect

On reconnect, re-run from step 1. The snapshot is always current, so re-seeding reconciles any missed events.

Example (Node.js / ioredis)

Use a dedicated client for the blocking XREAD ... BLOCK loop - it ties up the connection. Don’t reuse it for other commands.

Notes

  • Prices are decimal-dollar strings (e.g. "12.43"), not cents - parse carefully to avoid float rounding.
  • Streams are length-capped (~100k entries, trimmed automatically) - always seed from the snapshot rather than reading the stream from 0.
  • The snapshot is the source of truth. Membership is reconciled against it continuously, so an item present there is live even if you missed its item.add.
  • Credentials and the CA are issued per integration - contact AssetPay to provision feed access.