开发者
API 参考
通过 HTTPS 只读访问物品目录、价格、在售商品以及您自己的订单和钱包,并通过签名 Webhook 接收账户上的事件。
概览
所有接口都是此基础地址下的 GET 请求,返回 JSON。金额以美元计,格式为十进制字符串。OpenAPI 文档描述了每个字段。
BASEhttps://api.cs2sell.com/v1/public
GEThttps://api.cs2sell.com/v1/openapi.jsonOpenAPI 3 文档认证
以 Bearer 令牌形式发送密钥。密钥以 sk_ 开头,仅在创建时显示一次。每个密钥都带有权限范围,除 /v1/public/me 外,每个接口都需要其中之一。 在“账户 → 安全”中创建密钥。
curl https://api.cs2sell.com/v1/public/me \ -H "Authorization: Bearer sk_…"
{
"api_key_id": "6f1c2d3e-…",
"user_id": "0b7e9a41-…",
"tier": "free",
"scopes": ["catalog:read", "orders:read"],
"rate_limit_per_minute": 60
}接口
中间一列是各接口所需的权限范围。
| 接口 | 权限范围 | 返回内容 |
|---|---|---|
| GET /v1/public/me | 任意密钥 | 当前调用所用的密钥:版本、权限范围和速率限制。 |
| GET /v1/public/catalog | catalog:read | 搜索物品目录。分页 |
| GET /v1/public/items/{id} | catalog:read | 单个物品及其各款式。 |
| GET /v1/public/prices/{variant_id} | catalog:read | 某款式在各市场的价格。 |
| GET /v1/public/marketplaces | catalog:read | 我们追踪价格的市场。 |
| GET /v1/public/listings | listings:read | CS2Sell 上的在售商品,支持筛选。分页 |
| GET /v1/public/orders | orders:read | 您的订单。分页 |
| GET /v1/public/wallet/balance | wallet:read | 您的可用余额和待结算余额。 |
分页
列表接口接受 ?page=(从 1 开始)和 ?page_size=(默认 50,最多 100),并返回如下结构:
{
"items": [ … ],
"page": 1,
"page_size": 50,
"total": 1284
}速率限制
每个密钥的每个权限范围都有独立的每分钟额度,因此频繁查询目录不会占用订单查询的额度。每个响应都会告知当前用量。
| 版本 | 每分钟请求数(每个权限范围) | |
|---|---|---|
| 免费 | 60 | 可用 |
| 专业 | 600 | 即将推出 |
| 商业 | 3000 | 即将推出 |
- X-RateLimit-Limit
- 该权限范围每分钟允许的请求数。
- X-RateLimit-Remaining
- 当前分钟内剩余的请求数。
- X-RateLimit-Reset
- 距本分钟重置的秒数。
- Retry-After
- 随 429 返回:重试前需等待的秒数。
错误
错误使用 HTTP 状态码和一个可供匹配的稳定错误码。params 用于填充错误消息的占位符,校验错误还会附带 fields 列表。
HTTP/1.1 403 Forbidden
{
"error": {
"code": "api_keys.scope_missing",
"params": { "scope": "orders:read" }
}
}Webhook
添加端点并选择需要的事件。每个事件以 JSON 形式 POST 推送,并使用端点密钥(whsec_…)签名。 在“账户 → 安全”中添加。
事件
- listing.created
- 您的商品已上架
- listing.sold
- 您的商品已售出
- listing.cancelled
- 您的商品已被您或平台下架
- order.completed
- 您的订单已交付
- order.refunded
- 您的订单已退款
- trade.completed
- 机器人或 P2P 交易已完成
- trade.reversed
- Steam 上的交易被撤回
- wallet.deposit
- 充值已到账
- wallet.withdrawal
- 提现已发出或失败
请求头
- X-CS2Sell-Signature
- sha256= 加上以您的密钥对原始请求体计算的 HMAC-SHA256 十六进制值。
- X-CS2Sell-Event
- 事件名称,请求体中也有。
- X-CS2Sell-Delivery-Id
- 每次推送唯一,重试时保持不变;可用于去重。
- X-CS2Sell-Timestamp
- 本次尝试发送时的 Unix 时间。
验证推送
请在解析之前对原始请求体计算 HMAC,并使用恒定时间比较。使用密钥 whsec_example 时,以下请求体的签名为:
X-CS2Sell-Signature: sha256=ca488ead1f388f2edbd01f592eeb29b9c27225c76da89e2e78a4abb6ca451c6e {"id":"0b9c6f2e-4f7a-4c55-9a43-2d6f1f0e8a11","event":"listing.sold","created_at":"2026-10-08T12:00:00Z","data":{"listing_id":"5d1b2a90-7c3e-4b8e-9f0a-6a2c4e8d1f37","order_id":"c2e4f6a8-1b3d-4f5a-8c7e-9d0b2a4c6e81","price_usd":"42.50","kind":"p2p"}}
请在 10 秒内返回任意 2xx。否则将在 30 秒、5 分钟、30 分钟、2 小时、6 小时和 24 小时后重试;第六次失败后端点将被停用,并通知您。端点必须是公网 http 或 https 地址,且不会跟随重定向。
Node.js 快速上手
无需安装 SDK:API 就是普通的 HTTPS 和 JSON。每个快速上手示例都会读取 /v1/public/me 并验证 Webhook 签名。
// Node.js 18+: fetch and crypto are built in.
import { createHmac, timingSafeEqual } from 'node:crypto';
const res = await fetch('https://api.cs2sell.com/v1/public/me', {
headers: { Authorization: `Bearer ${process.env.CS2SELL_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.code);
console.log(body.tier, res.headers.get('x-ratelimit-remaining'));
// Verify a webhook against the raw body, before parsing it.
export function verify(rawBody, signature, secret) {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(signature ?? '');
return a.length === b.length && timingSafeEqual(a, b);
}Python 快速上手
# pip install requests
import hashlib, hmac, os
import requests
r = requests.get(
"https://api.cs2sell.com/v1/public/me",
headers={"Authorization": f"Bearer {os.environ['CS2SELL_API_KEY']}"},
timeout=10,
)
r.raise_for_status()
print(r.json()["tier"], r.headers["X-RateLimit-Remaining"])
def verify(raw_body: bytes, signature: str, secret: str) -> bool:
"""Check X-CS2Sell-Signature against the raw request body."""
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature or "")Go 快速上手
package cs2sell
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"os"
)
type Me struct {
Tier string `json:"tier"`
Scopes []string `json:"scopes"`
RateLimitPerMinute int `json:"rate_limit_per_minute"`
}
func FetchMe() (*Me, error) {
req, err := http.NewRequest("GET", "https://api.cs2sell.com/v1/public/me", nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("CS2SELL_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("cs2sell: %s", res.Status)
}
var me Me
return &me, json.NewDecoder(res.Body).Decode(&me)
}
// Verify checks X-CS2Sell-Signature against the raw request body.
func Verify(body []byte, signature, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signature))
}