Skip to content

Catalogue Events ​

GET /api/v1/merchant/purchase/events

Keep a downloaded catalogue current instead of re-downloading it: ask only for what changed since a point in time.

Download Available Items once and keep its last_update_at. Ask this endpoint for changes after it, apply them, and remember next for the next call.

Request ​

Headers ​

HeaderRequiredDescription
X-Api-Key✅Your merchant API key

Query Parameters ​

ParameterTypeRequiredDescription
sincestring✅RFC 3339 time to read after. First call: your catalogue's last_update_at. Then: the next from your previous response
gamestring—Comma-separated game codes (csgo, rust, dota2, tf2) to receive. Omit for all
extendedboolean—Include class_id, instance_id, asset_id, bot_steam_id, float, paint_seed, inspect_url, phase on upsert cards
limitinteger—Events per page, 1–50000 (default 10000)
bash
curl "https://api.skinslink.com/api/v1/merchant/purchase/events?since=2026-08-21T14:00:00Z&game=csgo&extended=true" \
  -H "X-Api-Key: your-api-key" \
  --compressed

Response ​

json
{
  "success": true,
  "message": "Successfully retrieved catalogue events",
  "data": {
    "since": "2026-08-21T14:00:00Z",
    "next": "2026-08-21T14:00:12.512434831Z",
    "count": 2,
    "more": false,
    "reset": false,
    "events": [
      {
        "type": "upsert",
        "at": "2026-08-21T14:00:11.004Z",
        "game": "csgo",
        "id": "38029384123",
        "item": {
          "id": "38029384123",
          "name": "AK-47 | Redline (Field-Tested)",
          "price": 12.45,
          "image_url": "https://steamcommunity-a.akamaihd.net/economy/image/class/730/..."
        }
      },
      { "type": "remove", "at": "2026-08-21T14:00:12.512434831Z", "game": "csgo", "id": "38029111999" }
    ]
  }
}
FieldTypeDescription
nextstringPass as since next time. Nanosecond precision — send it back exactly
countintegerEvents in this page
morebooleantrue: the page filled up; ask again at once with the new next
resetbooleantrue: download the catalogue again (see below); events is empty
events[].typestringupsert or remove
events[].atstringWhen it happened (RFC 3339, nanoseconds)
events[].gamestringGame code
events[].idstringCatalogue item id — the one you pass to Create Purchase
events[].itemobjectOn upsert only: the full card, same shape as an Available Items full item

Applying changes ​

  • upsert — insert the id, or replace it if you already have it. The card is the complete current state.
  • remove — take the id out.

Re-applying an event is safe.

Reset ​

The journal keeps about one hour. You get reset: true with an empty events when since is older than that, or the catalogue changed too much to stream event by event. Either way: download Available Items again and resume from the new last_update_at. A reset always arrives on its own — never mixed with changes.

Stream instead of poll

Open a Catalogue WebSocket and we stream the same events to you live. Keep this endpoint too — it is how you catch up on connect and after a gap.

Errors ​

StatusMessageCause
400since must be an RFC 3339 time…since missing or malformed
400limit must be between 1 and 50000limit out of range
400unknown game "…"game carries a code other than csgo, rust, dota2, tf2
401invalid API keyMissing or invalid X-Api-Key
503catalogue events are temporarily unavailable, retryJournal read failed — wait for Retry-After and repeat