Full market snapshots
Development preview: this method is implemented locally, not yet a verified public service.
POST /v1/markets/snapshot streams the current cached market matrix as application/x-ndjson: one JSON record per line. It requires market:read. Send only the Authorization header, with no body or query parameters.
curl --no-buffer --fail-with-body -X POST \ -H "Authorization: Bearer $CSFOLDER_API_KEY" \ https://api.csfolder.com/v1/markets/snapshotThis reads our database and cache. It does not fetch upstream data for each customer. It covers the catalog stored in CSFolder, not a promise that every item in the game has a quote on every marketplace. History is a separate dataset.
Completion protocol
Section titled “Completion protocol”| Record | Meaning |
|---|---|
start |
Request ID, price-cache generation, ingest time and upper catalog item ID. |
item |
data.item_id, market_hash_name, exact phase, availability, asks and bids. |
end |
Matching request ID and generation, plus the number of item records sent. |
error |
The export failed. Discard the partial dataset. No successful end follows. |
Each quote has integer USD-cent amount, currency: USD, minor_units: 2, provider, quantity and URL. Quantity and URL can be null. Missing cache entries use availability: missing and empty quote arrays, not a zero price. Bid prices never substitute for asks; phases never fall back to an unphased item.
HTTP 200 alone is not success. Require exactly one start, ordered item records and one matching end; verify the item count and reject unknown, extra, malformed or truncated records. A network interruption may have no error line. Read line by line rather than calling response.json() or accumulating the whole body. The maximum encoded record is 256 KiB.
Write into a temporary file or staging table. Only promote it after the complete protocol has been validated. On snapshot_changed or snapshot_interrupted, discard the staging data and retry the entire request with bounded backoff. There is no resume cursor in this version. Interrupted starts can still spend quota, so do not retry forever.
Consistency and timestamps
Section titled “Consistency and timestamps”A successful export contains prices from one cache generation. An update during streaming invalidates the export. Catalog identities are scanned in increasing item ID up to the captured maximum; this is not a point-in-time database snapshot.
ingested_at is when CSFolder published that cache generation. generated_at is when the export started. Neither is the marketplace observation time: the current feed does not supply it, so price_as_of and quote as_of remain null. A recent export can contain older source prices. Do not turn an export timestamp into an observed hourly history point without preserving this distinction.
Export limits
Section titled “Export limits”One active export per account, shared across keys. There are eight active export slots across the service and a two-minute export deadline. Slow clients are backpressured; disconnected clients stop further reads. Schedule with jitter and honor Retry-After rather than starting every customer at the same second.
Development defaults for starts in a rolling 24-hour window:
| Plan | Starts |
|---|---|
| Free | Not available (403 before quota or lease) |
| Builder | 48 |
| Trader | 144 |
| Quant | 288 |
These are draft access settings, not published subscriptions. Each admitted export also costs one monthly request. Slot/daily-limit rejections occur before monthly charging. Failure before streaming releases the daily reservation, but an already admitted monthly request is not refunded. Once streaming starts, client cancellation or a later failure still counts as a start. A crashed process may retain its reservation until expiry.
HTTP 429 uses snapshot_busy, snapshot_capacity or snapshot_daily_limit and a Retry-After header. Before response headers, missing data can return HTTP 503. After streaming starts, follow the completion protocol above. See limits and errors.