RMT.GG/卖家开发者文档
v1

卖家 API

自动化产品列表、完成销售并流式传输订单事件。包括出站 Webhook 和按需库存补充的保留端点。

REST 开放 API

Bearer 认证的 /api/v1 用于产品和订单,带有发现和速率限制头部。

出站 Webhook

用于订单和产品生命周期事件的签名 HTTPS(或 Discord)传递。

保留 / 补充

在本地库存不足时,付款后从您的服务器铸造 COMPLEX 库存。

您可以构建的内容

卖家开放 API 适用于希望获得 Discord 警报、库存同步、Zapier 风格自动化或在 RMT.GG 上构建自定义后台的卖家。

  • 管理产品
    通过 /api/v1/offers 创建草稿、更新安全字段、发布和归档。
  • 完成销售
    列出并检查卖家订单,然后使用可选证据 URL 标记为已交付。
  • 保持在限制内
    每个密钥每分钟限制为 300 次请求。响应包括 X-RateLimit-* 头部。
  • 实时反应
    订阅订单和产品事件,或使用保留 Webhook 补充 COMPLEX 库存。
  • 从您的商店收款
    已批准的合作伙伴可以将买家从外部商店发送到托管结账页面,然后完成订单支付。

快速入门

在开发者设置中创建一个API密钥,然后调用发现以打印实时目录。

  1. 1打开设置 → 开发者(无需单独启用步骤)。
  2. 2创建一个 API 密钥并复制一次密钥(rmt_sk_live_…)。将其存储在您的秘密管理器中。
  3. 3调用 GET /api/v1 并使用 Authorization: Bearer 确认作用域、配额和操作。
GET/api/v1

发现文档

返回作用域、配额、Webhook 事件和完整的操作目录。任何有效的 API 密钥均可使用。

认证

在每个 /api/v1 请求中发送您的实时秘密密钥。优先使用 HTTPS。绝不要在公共客户端或浏览器包中嵌入密钥。

首选头部

http
Authorization: Bearer rmt_sk_live_<prefix>_<secret>

备用头部

http
X-Api-Key: rmt_sk_live_<prefix>_<secret>

可重用的 TypeScript 客户端(Bearer 认证,类型错误,429 重试)

typescript
const API_BASE = "https://rmt.gg/api/v1";
const API_KEY = process.env.RMT_API_KEY!; // rmt_sk_live_…

export class RmtApiError extends Error {
  constructor(
    readonly status: number,
    readonly code: string | undefined,
    message: string,
    readonly retryAfterSec?: number,
  ) {
    super(message);
    this.name = "RmtApiError";
  }
}

type RmtFetchInit = RequestInit & { idempotencyKey?: string };

export async function rmtFetch<T>(path: string, init: RmtFetchInit = {}): Promise<T> {
  const headers = new Headers(init.headers);
  headers.set("Authorization", `Bearer ${API_KEY}`);
  // Alternate: headers.set("X-Api-Key", API_KEY);
  headers.set("Accept", "application/json");
  if (init.body && !headers.has("Content-Type")) {
    headers.set("Content-Type", "application/json");
  }
  if (init.idempotencyKey) headers.set("Idempotency-Key", init.idempotencyKey);

  const res = await fetch(`${API_BASE}${path}`, { ...init, headers });
  const retryAfter = Number(res.headers.get("Retry-After") ?? "");
  const body = (await res.json().catch(() => ({}))) as {
    error?: string;
    code?: string;
    retryAfter?: number;
  };

  if (res.status === 429) {
    throw new RmtApiError(
      429,
      body.code ?? "RATE_LIMITED",
      body.error ?? "Rate limited",
      Number.isFinite(retryAfter) ? retryAfter : body.retryAfter,
    );
  }
  if (!res.ok) {
    throw new RmtApiError(res.status, body.code, body.error ?? res.statusText);
  }
  return body as T;
}

export async function withRetry<T>(fn: () => Promise<T>, maxAttempts = 4): Promise<T> {
  let attempt = 0;
  for (;;) {
    try {
      return await fn();
    } catch (err) {
      attempt += 1;
      if (!(err instanceof RmtApiError) || err.status !== 429 || attempt >= maxAttempts) {
        throw err;
      }
      const waitSec = Math.max(1, err.retryAfterSec ?? 1);
      await new Promise((r) => setTimeout(r, waitSec * 1000));
    }
  }
}

泄露时更换

如果密钥泄露,请在开发者设置中撤销它并创建一个新的。如果您正在使用,请在撤销之前更新您的自动化。

作用域

每个 API 密钥携带作用域以限制端点。缺少作用域将返回 403 SCOPE_MISSING。

offers:read
offers:write
orders:read
orders:write
webhooks:manage
checkout:write
  • offers:read: 列出并获取您的产品。
  • offers:write: 创建、更新、发布和删除产品。
  • orders:read: 列出并获取卖家订单。
  • orders:write: 标记订单为已交付。
  • webhooks:manage: 保留用于未来的开放API webhook管理。今天在通知中配置Discord/Telegram,并在开发者设置中配置JSON webhook。
  • checkout:write: 创建和读取托管结账会话。需要管理员批准的合作伙伴结账。

默认密钥作用域

新密钥接收 offers:read、offers:write、orders:read 和 orders:write。出站 Webhook CRUD 保留在设置 UI(会话认证)中。

产品 API

产品标识符接受公共 URL 段或数字 ID。响应省略内部 ID 和 sellerId。

PATCH 目前无法更改的内容

库存行、选项价格、媒体和属性在卖家编辑器中管理(或未来的端点),而不是通过 PATCH。

GET/api/v1/offers
offers:read

列出您的产品

使用 archive=active(默认)、archived 或 all 进行过滤。

请求

  • archive
    query
    类型
    string
    必填
    选填
    描述
    One of "active" (default), "archived", or "all".
  • Response: { offers: Offer[], total: number }. Numeric id and sellerId are omitted.
POST/api/v1/offers
offers:write

创建草稿产品

创建一个由经过身份验证的卖家拥有的空草稿。无需请求体。

  • No request body required.
  • Response 201: { offer: Offer }.
GET/api/v1/offers/:urlOrId
offers:read

获取一个产品

通过公共 URL 段或数字 ID 加载。关系(选项)可能会被包含;库存项目不会。

请求

  • urlOrId
    path
    类型
    string
    必填
    必填
    描述
    Offer.url slug or Offer.id.
  • Returns relations (options, etc.) when available; items are not included.
PATCH/api/v1/offers/:urlOrId
offers:write

更新产品字段

对产品字段的安全子集进行补丁。当配置出站 Webhook 时,发出 offer.updated。

请求

  • urlOrId
    path
    类型
    string
    必填
    必填
    描述
    Offer.url slug or Offer.id.
  • title
    body
    类型
    string
    必填
    选填
    描述
    Listing title.
  • description
    body
    类型
    string
    必填
    选填
    描述
    Listing description.
  • visibility
    body
    类型
    string
    必填
    选填
    描述
    PUBLIC | PRIVATE | UNPUBLISHED.
  • categoryId
    body
    类型
    number
    必填
    选填
    描述
    Catalog category id.
  • offeringId
    body
    类型
    number
    必填
    选填
    描述
    Catalog offering id.
  • thumbnail
    body
    类型
    string
    必填
    选填
    描述
    Thumbnail URL or asset reference.
  • offerType
    body
    类型
    string
    必填
    选填
    描述
    Offer type string used by the listing.
  • listingMode
    body
    类型
    string
    必填
    选填
    描述
    Listing mode (for example STANDARD, RANK_BOOST, SESSION).
  • At least one allowed field is required.
  • Emits offer.updated webhook when configured.
  • Stock is managed via GET/POST /api/v1/offers/:urlOrId/stock. Option prices, media, and attributes are not editable via this endpoint yet.
DELETE/api/v1/offers/:urlOrId
offers:write

删除或归档

与卖家 UI 相同的删除/归档规则。

请求

  • urlOrId
    path
    类型
    string
    必填
    必填
    描述
    Offer.url slug or Offer.id.
  • Response: { ok: true }.
POST/api/v1/offers/:urlOrId/publish
offers:write

发布一个产品

发布草稿(或更改可见性)。如果必填产品字段不完整,则会失败并返回 400。

请求

  • urlOrId
    path
    类型
    string
    必填
    必填
    描述
    Offer.url slug or Offer.id.
  • visibility
    body
    类型
    string
    必填
    选填
    描述
    Optional. PUBLIC (default), PRIVATE, or UNPUBLISHED.
  • Response: { offer: Offer }.
  • Fails if the listing is incomplete for publish.

库存 API

查看每个层级可购买的数量,将交付字段名称与正确的列表匹配,然后补充数量或保存的密钥和账户。

匹配工作原理

GET /api/v1/stock?fields=username,password 查找具有这些字段的列表。使用选项名称(或 optionId)和字段名称进行补货。您不需要内部字段 ID。响应中永远不包含凭证值。

GET/api/v1/stock
offers:read

列出您所有列表的库存

返回每个层级的数量和交付字段名称,以便您可以将密钥和账户匹配到正确的提供。使用 q、fields、stockMode 和 lowStock 进行过滤。永远不返回凭证值。

请求

  • q
    query
    类型
    string
    必填
    选填
    限制
    Max 80
    描述
    Filter by listing title or url slug.
  • fields
    query
    类型
    string
    必填
    选填
    描述
    Comma-separated delivery field names. The listing must have all of them (Username,Password). Names match case-insensitively.
  • stockMode
    query
    类型
    string
    必填
    选填
    描述
    QUANTITY or COMPLEX. Listing must have at least one option in that mode.
  • lowStock
    query
    类型
    number
    必填
    选填
    描述
    Keep listings that have a finite tier with available less than or equal to this number.
  • archive
    query
    类型
    string
    必填
    选填
    描述
    One of "active" (default), "archived", or "all".
  • Response: { offers: StockOffer[], total: number }. Numeric offer id is omitted. Option id is included so you can restock a specific tier.
  • available is the buyable count. null with unlimited true means unlimited quantity or on-demand COMPLEX inventory.
  • fields[] is the listing delivery schema (empty for quantity-only listings). Use it to map keys and accounts without field ids.
  • This endpoint never returns credential values.
GET/api/v1/offers/:urlOrId/stock
offers:read

获取一个列表的库存

与索引相同的 StockOffer 形状,适用于一个 URL 或数字 ID。仅计数。

请求

  • urlOrId
    path
    类型
    string
    必填
    必填
    描述
    Offer.url slug or Offer.id.
  • Response: { offer } with the same StockOffer shape as GET /api/v1/stock.
  • Counts only. Use the seller editor to inspect saved key values.
POST/api/v1/offers/:urlOrId/stock
offers:write

补货一个列表

数量层级:添加、移除或设置。保存物品层级:按字段名称的物品对象,当有一个字段时使用 keys[],或使用分隔文本。通过 options[] 在一次调用中处理多个层级。dryRun 预览匹配。onDuplicate 默认跳过。

json
{
  "option": "1 Month",
  "add": 50
}

请求

  • urlOrId
    path
    类型
    string
    必填
    必填
    描述
    Offer.url slug or Offer.id.
  • option
    body
    类型
    string
    必填
    条件
    描述
    Pricing option name (case-insensitive). Omit when the listing has a single tier.
  • optionId
    body
    类型
    number
    必填
    条件
    描述
    Pricing option id from GET stock. Wins over option when both are sent. Ambiguous names return 409 OPTION_AMBIGUOUS.
  • add
    body
    类型
    number
    必填
    条件
    限制
    1-1,000,000
    描述
    QUANTITY: add this many units. Fails with 400 UNLIMITED_STOCK if the tier is unlimited.
  • remove
    body
    类型
    number
    必填
    条件
    限制
    1-1,000,000
    描述
    QUANTITY: withdraw this many units. Fails with 400 INSUFFICIENT_STOCK when there is not enough.
  • set
    body
    类型
    number | null
    必填
    条件
    描述
    QUANTITY: set an absolute count. null means unlimited. Cannot go below units held in checkout.
  • items
    body
    类型
    object[]
    必填
    条件
    限制
    Max 1,000
    描述
    COMPLEX: objects keyed by delivery field name, for example { "Username": "a", "Password": "b" }. Names match case-insensitively.
  • keys
    body
    类型
    string[]
    必填
    条件
    限制
    Max 1,000
    描述
    COMPLEX: license keys when the listing has exactly one delivery field. Otherwise 400 FIELD_MAPPING_AMBIGUOUS.
  • text
    body
    类型
    string
    必填
    条件
    限制
    Max 1,000 rows
    描述
    COMPLEX: delimited paste. A header row that matches field names is detected automatically. Otherwise columns map in field sort order when the column count matches.
  • delimiter
    body
    类型
    string
    必填
    选填
    限制
    Default :
    描述
    Delimiter for text. Ignored unless text is sent.
  • headers
    body
    类型
    string[]
    必填
    选填
    描述
    Optional column headers for text when the first line is data, not names.
  • options
    body
    类型
    object[]
    必填
    条件
    描述
    Restock several tiers in one call. Each element is the same shape as a single-option body (option, add, items, …).
  • dryRun
    body
    类型
    boolean
    必填
    选填
    描述
    Preview matching and counts without writing. Default false.
  • onDuplicate
    body
    类型
    string
    必填
    选填
    限制
    skip (default) or error
    描述
    COMPLEX: skip existing unsold fingerprints, or fail the request with 409 DUPLICATE_ITEMS.
  • Send exactly one action per option: add, remove, set, items, keys, or text.
  • Sending items to a QUANTITY tier (or add to a COMPLEX tier) returns 400 STOCK_MODE_MISMATCH.
  • Responses never echo credential values. COMPLEX results include imported, skippedDuplicates, errors, and matchedFields.
  • Saved items are capped at 5,000 unsold rows per option. A single request may import at most 1,000 rows.

导入多个账户或密钥

指南

使用 POST /api/v1/offers/:url/stock,items[] 用于账户,keys[] 用于单字段许可证代码。每个请求分块为 1,000 行。

  1. 1获取列表。使用 fields[] 和 stockMode 选择物品、钥匙或添加。
  2. 2将账户保存为 JSON 或 CSV,按字段名称键入。将许可证密钥逐行保存。
  3. 3先进行干运行。检查 wouldImport、skippedDuplicates 和 matchedFields。
  4. 4再次发送相同的请求体,不带 dryRun,以写入库存。

选择与列表匹配的有效载荷

首先调用 GET stock。如果 fields[] 有多个名称,发送以这些名称为键的 items 对象(用户名、密码、电子邮件)。如果只有一个字段,keys[] 就足够了。数量列表使用 add,而不是 items。

每个请求最多 1,000 行。每个等级最多 5,000 个未售出物品。每分钟 300 个请求。默认跳过重复项。

accounts.json(每个账户一个对象)

json
[
  { "Username": "player1", "Password": "secret1", "E-Mail": "[email protected]" },
  { "Username": "player2", "Password": "secret2", "E-Mail": "[email protected]" }
]

accounts.csv

csv
Username,Password,E-Mail
player1,secret1,p1@example.com
player2,secret2,p2@example.com

keys.txt(每行一个许可证密钥)

text
AAAA-BBBB-CCCC
DDDD-EEEE-FFFF
GGGG-HHHH-IIII

cURL

bash
# Inspect field names and stockMode
curl -s -H "Authorization: Bearer rmt_sk_live_…" \
  -H "Accept: application/json" \
  https://rmt.gg/api/v1/offers/YOUR_OFFER_URL/stock

# Preview (no write)
curl -s -X POST \
  -H "Authorization: Bearer rmt_sk_live_…" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  https://rmt.gg/api/v1/offers/YOUR_OFFER_URL/stock \
  -d '{"dryRun":true,"onDuplicate":"skip","option":"Premium","items":[{"Username":"player1","Password":"secret1","E-Mail":"[email protected]"}]}'

# Apply accounts
curl -s -X POST \
  -H "Authorization: Bearer rmt_sk_live_…" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  https://rmt.gg/api/v1/offers/YOUR_OFFER_URL/stock \
  -d '{"onDuplicate":"skip","option":"Premium","items":[{"Username":"player1","Password":"secret1","E-Mail":"[email protected]"}]}'

# Apply license keys (listing must have exactly one delivery field)
curl -s -X POST \
  -H "Authorization: Bearer rmt_sk_live_…" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  https://rmt.gg/api/v1/offers/YOUR_OFFER_URL/stock \
  -d '{"option":"Steam","keys":["AAAA-BBBB-CCCC","DDDD-EEEE-FFFF"]}'

# Or paste CSV / colon-separated rows in text
curl -s -X POST \
  -H "Authorization: Bearer rmt_sk_live_…" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  https://rmt.gg/api/v1/offers/YOUR_OFFER_URL/stock \
  -d '{"option":"Premium","delimiter":",","text":"Username,Password,E-Mail\nplayer1,secret1,[email protected]"}'

TypeScript 批量导入(每个请求 1,000 行)

typescript
// Paste rmtFetch and withRetry from the Auth section first.
const CHUNK = 1000;

async function importRows(offerUrl: string, option: string, rows: Array<Record<string, string>>) {
  for (let i = 0; i < rows.length; i += CHUNK) {
    const items = rows.slice(i, i + CHUNK);
    const preview = await rmtFetch<{
      results: Array<{ wouldImport: number; skippedDuplicates: number; errors: string[] }>;
    }>(`/offers/${offerUrl}/stock`, {
      method: "POST",
      body: JSON.stringify({ dryRun: true, onDuplicate: "skip", option, items }),
    });
    const row = preview.results[0];
    if ((row?.errors?.length ?? 0) > 0) {
      throw new Error(row.errors.join("; "));
    }
    await withRetry(() =>
      rmtFetch(`/offers/${offerUrl}/stock`, {
        method: "POST",
        body: JSON.stringify({ onDuplicate: "skip", option, items }),
      }),
    );
  }
}

// License keys: only when GET stock.fields has exactly one name
async function importKeys(offerUrl: string, option: string, keys: string[]) {
  for (let i = 0; i < keys.length; i += CHUNK) {
    await withRetry(() =>
      rmtFetch(`/offers/${offerUrl}/stock`, {
        method: "POST",
        body: JSON.stringify({ option, keys: keys.slice(i, i + CHUNK) }),
      }),
    );
  }
}

此 API 保护的内容

密钥需要 offers:write,受速率限制,并且只能补充您自己的列表。GET 永远不会返回保存的凭据。POST 响应不会回显用户名、密码或密钥值。在生产环境中通过 HTTPS 发送请求,并将 API 密钥保存在环境变量中。

在 Windows 上,使用 curl.exe(而不是 curl 别名)。将 -d JSON 用引号括起来,以防 PowerShell 拆分它。

订单 API

订单与您的卖家账户相关联。根据市场记录隐私规则,买方账单详细信息可能会被隐藏。

GET/api/v1/orders
orders:read

列出卖家订单

支持 limit、offset、status、q 和 sort(最新、最旧、总高、总低)。

请求

  • limit
    query
    类型
    number
    必填
    选填
    限制
    1-100, default 20
    描述
    Page size.
  • offset
    query
    类型
    number
    必填
    选填
    限制
    >= 0, default 0
    描述
    Skip this many rows.
  • status
    query
    类型
    string
    必填
    选填
    限制
    Max 32
    描述
    Filter by order status (for example PAID, DELIVERED, COMPLETED).
  • q
    query
    类型
    string
    必填
    选填
    限制
    Max 80
    描述
    Search reference or related text.
  • sort
    query
    类型
    string
    必填
    选填
    限制
    newest (default)
    描述
    newest | oldest | total_high | total_low.
  • Response: { orders: Order[], total: number }.
GET/api/v1/orders/:uid
orders:read

获取一个订单

返回带有行项目的订单。使用公共订单 uid。

请求

  • uid
    path
    类型
    string
    必填
    必填
    描述
    Order.uid.
  • Response: { order } with line items.
  • Buyer billing fields may be redacted under marketplace-of-record privacy rules.
POST/api/v1/orders/:uid/deliver
orders:write

标记为已交付

手动履行。COMPLEX 行在需要时必须完全附加。发出 order.delivered。

请求

  • uid
    path
    类型
    string
    必填
    必填
    描述
    Order.uid.
  • evidence
    body
    类型
    string[]
    必填
    选填
    限制
    HTTPS, max 10
    描述
    Optional screenshot or transfer-proof URLs.
  • Response: { success: true, order }.
  • COMPLEX inventory lines must be fully attached before deliver when the product requires it.
  • Emits order.delivered webhook when configured.

托管结账

任何经过批准的合作伙伴商店或后端都可以将买家发送到RMT.GG支付页面。我们保持商户记录,并收取锁定金额的4%。

白名单和履行

在设置中申请,选择托管结账,然后在此创建API密钥和JSON webhook。付款后,我们会发出checkout.completed。交付值保留在RMT.GG确认中;它们不在卖家GET或webhook中。

POST/api/v1/checkout/sessions
checkout:write

创建托管结账会话

将买家引导至锁定的 RMT.GG 支付页面。一个物品:数量和物品名称。购物车:每行包含名称和数量的 items[]。货币默认为美元(USD)。支付后,如果有交付字段需要复制,买家将留在 RMT.GG;如果没有交付,我们将在短暂倒计时后将他们送回商店。数量、长度和其他限制在限制列中。

javascript
{
  amount:   10,           // what the buyer pays
  itemName: "Gold pack",  // pay page heading
}

请求

  • amount
    body
    类型
    number
    必填
    条件
    限制
    > 0, max 1,000,000
    描述
    What the buyer pays. Required for a single item. With items[], omit it or send the line sum. Mismatch: 400 AMOUNT_MISMATCH.
  • currency
    body
    类型
    string
    必填
    选填
    限制
    Default USD
    描述
    ISO 4217 code such as USD or EUR.
  • itemName
    body
    类型
    string
    必填
    条件
    限制
    Max 120
    描述
    Pay page heading. Required for a single item. Alias: title. With items[], defaults to the first line name. Missing: 400 ITEM_NAME_REQUIRED.
  • title
    body
    类型
    string
    必填
    选填
    描述
    Alias of itemName. If both are sent, itemName wins.
  • description
    body
    类型
    string
    必填
    选填
    限制
    Max 200
    描述
    Copy under the heading. If omitted, the heading is reused.
  • imageUrl
    body
    类型
    string
    必填
    选填
    限制
    HTTPS, max 2048
    描述
    Product image, or fallback for lines without imageUrl. Invalid: 400 INVALID_IMAGE_URL.
  • items
    body
    类型
    object[]
    必填
    条件
    限制
    1-20 lines, JSON max 48,000
    描述
    Locked cart. Required when amount is omitted. Buyers cannot change lines. Empty: 400 INVALID_ITEMS.
  • items[].name
    body
    类型
    string
    必填
    必填
    限制
    Max 120
    描述
    Line title. Alias: title.
  • items[].title
    body
    类型
    string
    必填
    选填
    描述
    Alias of items[].name. If both are sent, name wins.
  • items[].description
    body
    类型
    string
    必填
    选填
    限制
    Max 200
    描述
    Line copy under the name.
  • items[].amount
    body
    类型
    number
    必填
    必填
    限制
    > 0, max 1,000,000
    描述
    Unit price. Session total is sum(amount * quantity).
  • items[].quantity
    body
    类型
    number
    必填
    选填
    限制
    1-99, default 1
    描述
    Locked on the pay page.
  • items[].imageUrl
    body
    类型
    string
    必填
    选填
    限制
    HTTPS, max 2048
    描述
    Line image. Falls back to top-level imageUrl.
  • items[].delivery
    body
    类型
    object[]
    必填
    选填
    限制
    Max 16 fields
    描述
    Shown after payment on RMT.GG. Seller GET and webhooks omit values.
  • items[].delivery[].name
    body
    类型
    string
    必填
    必填
    限制
    Max 80
    描述
    Field label, for example Code or Password.
  • items[].delivery[].type
    body
    类型
    string
    必填
    选填
    限制
    text, password, textarea
    描述
    password is blurred until the buyer reveals it. Default text.
  • items[].delivery[].value
    body
    类型
    string
    必填
    必填
    限制
    Max 2048
    描述
    Field value. Numbers are stored as strings. Empty: 400 INVALID_DELIVERY.
  • email
    body
    类型
    string
    必填
    选填
    限制
    Invalid values ignored
    描述
    Prefills the pay page. The buyer still confirms email before paying.
  • returnUrl
    body
    类型
    string
    必填
    选填
    限制
    HTTPS, max 2048
    描述
    Continue-to-shop after payment. Delivery fields keep the buyer on RMT.GG with a button. No delivery: we send them back after a short countdown. If omitted, there is no shop button. http://localhost is allowed for local shops.
  • cancelUrl
    body
    类型
    string
    必填
    选填
    限制
    HTTPS, max 2048
    描述
    Redirect if the buyer cancels or the session expires. If omitted, they stay on the pay page.
  • invoiceId
    body
    类型
    string
    必填
    选填
    限制
    Max 128
    描述
    Your shop id. Same payload returns the existing session. A different payload: 409 INVOICE_CONFLICT.
  • categorySlug
    body
    类型
    string
    必填
    条件
    限制
    With offering, or omit both
    描述
    Public root slug such as games. Used for card, PayPal, and crypto labels, not the pay page title. Wrong pair: 400 INVALID_PSP_CATEGORY.
  • offering
    body
    类型
    string
    必填
    条件
    限制
    With categorySlug, or omit both
    描述
    Catalog offering such as Mods. Mapped to labels like Games · Add-ons.
  • metadata
    body
    类型
    object
    必填
    选填
    限制
    Object, max 4096 chars
    描述
    Stored on the session. Not returned on seller GET.
  • Idempotency-Key
    header
    类型
    string
    必填
    选填
    限制
    Max 128
    描述
    Replay header. Same key and payload returns the existing session. A different payload: 409 IDEMPOTENCY_CONFLICT.

响应

  • uid
    response
    类型
    string
    描述
    Session id. Same value as in hostedUrl / hosted_url.
  • status
    response
    类型
    string
    描述
    created | pending_payment | paid | canceled | expired | refunded | error. Unpaid sessions expire after 24 hours.
  • paid
    response
    类型
    boolean
    描述
    true only when status is paid. false for refunded, expired, canceled, and unpaid states.
  • amount
    response
    类型
    number
    描述
    Locked buyer total in major units.
  • currency
    response
    类型
    string
    描述
    ISO currency code stored on the session (for example USD).
  • itemName
    response
    类型
    string | null
    描述
    Pay page heading.
  • description
    response
    类型
    string
    描述
    Longer copy under the heading.
  • email
    response
    类型
    string | null
    描述
    Prefill or confirmed buyer email. Guest checkout placeholders are returned as null.
  • lang
    response
    类型
    string | null
    描述
    Buyer locale when known. Not a create-session field.
  • returnUrl
    response
    类型
    string | null
    描述
    Continue-to-shop URL stored on the session, or null.
  • cancelUrl
    response
    类型
    string | null
    描述
    Cancel/expiry redirect, or null.
  • invoiceId
    response
    类型
    string | null
    描述
    Your invoice id. Same value as externalInvoiceId.
  • externalInvoiceId
    response
    类型
    string | null
    描述
    Same as invoiceId (legacy alias).
  • source
    response
    类型
    string
    描述
    How the session was created. API sessions are "api".
  • expiresAt
    response
    类型
    string
    描述
    ISO timestamp. Unpaid checkouts cannot be completed after this time.
  • hostedUrl
    response
    类型
    string
    描述
    Pay page URL (same target as top-level hosted_url on create).
  • orderUid
    response
    类型
    string | null
    描述
    Marketplace order uid after payment. null until the session is paid.
  • items
    response
    类型
    object[]
    描述
    Locked lines: name, description, amount, quantity, imageUrl. Seller GET never includes delivery values.
  • hosted_url
    response
    类型
    string
    描述
    Pay page URL. Send the buyer here. Same target as hostedUrl.
  • expires_at
    response
    类型
    string
    描述
    ISO timestamp. Same value as expiresAt.
  • Approved partners only. Platform fee is 4% of the locked amount. Payment-method costs are absorbed by the platform.
  • After payment the buyer stays on RMT.GG so they can copy delivery fields. returnUrl is a continue button when delivery is present. With no delivery fields we send them back after a short countdown. If you omit them, they stay on the pay page after payment, cancel, or expiry.
  • Fulfill on checkout.completed. Sessions expire after 24 hours. Buyers cannot change line items. imageUrl must be HTTPS. categorySlug and offering must be sent together (or omit both); a wrong pair returns 400 INVALID_PSP_CATEGORY.
GET/api/v1/checkout/sessions/:uid
checkout:write

获取托管结账会话

返回您创建的会话。如果checkout.completed延迟,请使用此项。paid仅在状态为已付款时为true。items永远不包括交付值。

请求

  • uid
    path
    类型
    string
    必填
    必填
    描述
    Session uid returned at create time.

响应

  • uid
    response
    类型
    string
    描述
    Session id. Same value as in hostedUrl / hosted_url.
  • status
    response
    类型
    string
    描述
    created | pending_payment | paid | canceled | expired | refunded | error. Unpaid sessions expire after 24 hours.
  • paid
    response
    类型
    boolean
    描述
    true only when status is paid. false for refunded, expired, canceled, and unpaid states.
  • amount
    response
    类型
    number
    描述
    Locked buyer total in major units.
  • currency
    response
    类型
    string
    描述
    ISO currency code stored on the session (for example USD).
  • itemName
    response
    类型
    string | null
    描述
    Pay page heading.
  • description
    response
    类型
    string
    描述
    Longer copy under the heading.
  • email
    response
    类型
    string | null
    描述
    Prefill or confirmed buyer email. Guest checkout placeholders are returned as null.
  • lang
    response
    类型
    string | null
    描述
    Buyer locale when known. Not a create-session field.
  • returnUrl
    response
    类型
    string | null
    描述
    Continue-to-shop URL stored on the session, or null.
  • cancelUrl
    response
    类型
    string | null
    描述
    Cancel/expiry redirect, or null.
  • invoiceId
    response
    类型
    string | null
    描述
    Your invoice id. Same value as externalInvoiceId.
  • externalInvoiceId
    response
    类型
    string | null
    描述
    Same as invoiceId (legacy alias).
  • source
    response
    类型
    string
    描述
    How the session was created. API sessions are "api".
  • expiresAt
    response
    类型
    string
    描述
    ISO timestamp. Unpaid checkouts cannot be completed after this time.
  • hostedUrl
    response
    类型
    string
    描述
    Pay page URL (same target as top-level hosted_url on create).
  • orderUid
    response
    类型
    string | null
    描述
    Marketplace order uid after payment. null until the session is paid.
  • items
    response
    类型
    object[]
    描述
    Locked lines: name, description, amount, quantity, imageUrl. Seller GET never includes delivery values.
  • Response: { session }. Stale unpaid sessions are marked expired before they are returned.
  • Use this as a backup to checkout.completed. paid is true only when status is paid.
  • 404 NOT_FOUND if the uid is unknown or belongs to another seller.
GET/api/v1/checkout/sessions
checkout:write

通过发票ID查找托管的结账会话

与通过uid的GET相同的会话对象。传递您在创建时发送的invoiceId。缺失:400 INVOICE_ID_REQUIRED。未知:404 NOT_FOUND。

请求

  • invoiceId
    query
    类型
    string
    必填
    必填
    限制
    Max 128
    描述
    invoiceId from create. Missing: 400 INVOICE_ID_REQUIRED. Too long: 400 INVALID_INVOICE_ID.

响应

  • uid
    response
    类型
    string
    描述
    Session id. Same value as in hostedUrl / hosted_url.
  • status
    response
    类型
    string
    描述
    created | pending_payment | paid | canceled | expired | refunded | error. Unpaid sessions expire after 24 hours.
  • paid
    response
    类型
    boolean
    描述
    true only when status is paid. false for refunded, expired, canceled, and unpaid states.
  • amount
    response
    类型
    number
    描述
    Locked buyer total in major units.
  • currency
    response
    类型
    string
    描述
    ISO currency code stored on the session (for example USD).
  • itemName
    response
    类型
    string | null
    描述
    Pay page heading.
  • description
    response
    类型
    string
    描述
    Longer copy under the heading.
  • email
    response
    类型
    string | null
    描述
    Prefill or confirmed buyer email. Guest checkout placeholders are returned as null.
  • lang
    response
    类型
    string | null
    描述
    Buyer locale when known. Not a create-session field.
  • returnUrl
    response
    类型
    string | null
    描述
    Continue-to-shop URL stored on the session, or null.
  • cancelUrl
    response
    类型
    string | null
    描述
    Cancel/expiry redirect, or null.
  • invoiceId
    response
    类型
    string | null
    描述
    Your invoice id. Same value as externalInvoiceId.
  • externalInvoiceId
    response
    类型
    string | null
    描述
    Same as invoiceId (legacy alias).
  • source
    response
    类型
    string
    描述
    How the session was created. API sessions are "api".
  • expiresAt
    response
    类型
    string
    描述
    ISO timestamp. Unpaid checkouts cannot be completed after this time.
  • hostedUrl
    response
    类型
    string
    描述
    Pay page URL (same target as top-level hosted_url on create).
  • orderUid
    response
    类型
    string | null
    描述
    Marketplace order uid after payment. null until the session is paid.
  • items
    response
    类型
    object[]
    描述
    Locked lines: name, description, amount, quantity, imageUrl. Seller GET never includes delivery values.
  • Same { session } body as GET /api/v1/checkout/sessions/:uid, including the fields above.
  • Prefer this when you stored your own invoice id and not the session uid.
  • 404 NOT_FOUND if no session exists for that invoice id.

出站 Webhook

在设置 → 开发者中配置 HTTPS 端点(或 Discord Webhook)。当订阅事件触发时,RMT 会发送 POST。

order.paid
order.delivered
order.completed
order.refunded
order.disputed
offer.published
offer.updated
checkout.completed
checkout.canceled
checkout.refunded
  • JSON 格式发布一个结构化的信封,包含 id、类型、创建时间和数据。
  • Discord 格式发布丰富的嵌入内容,包含订单或产品链接。
  • 可选签名使用 X-RMT-Timestamp 和 X-RMT-Signature(与保留相同的方案)。
  • 每个端点下的交付历史记录显示,以便您可以重试失败。端点在重复失败后会自动暂停。
  • 托管结账发送checkout.completed、checkout.canceled和checkout.refunded,附带数据.checkout。交付值被省略。市场销售保留order.paid和其他order.*事件。

JSON 交付信封

json
{
  "id": "whd_…",
  "type": "order.paid",
  "created": "2026-07-23T12:00:00.000Z",
  "data": {
    "order": {
      "uid": "ord_…",
      "reference": "RMT-…",
      "status": "PAID",
      "url": "https://rmt.gg/orders/ord_…",
      "items": [ /* line items with offer names */ ]
    }
  }
}

签名交付头部

json
{
  "X-RMT-Event": "order.paid",
  "X-RMT-Delivery": "whd_…",
  "X-RMT-Timestamp": "1710000000",
  "X-RMT-Signature": "v1=abc123…"
}

结账完成的有效负载

json
{
  "id": "whd_…",
  "type": "checkout.completed",
  "created": "2026-08-14T12:00:00.000Z",
  "data": {
    "checkout": {
      "uid": "pcs_…",
      "status": "paid",
      "amount": 10,
      "currency": "USD",
      "itemName": "Gold pack",
      "description": "1000 gold for account example",
      "invoiceId": "inv-12345",
      "source": "api",
      "orderUid": "ord_…",
      "hostedUrl": "https://rmt.gg/pay/pcs_…",
      "email": "[email protected]",
      "paidAt": "2026-08-14T12:01:00.000Z",
      "expiresAt": "2026-08-15T12:00:00.000Z",
      "createdAt": "2026-08-14T12:00:00.000Z",
      "reason": null,
      "items": [
        {
          "name": "Gold pack",
          "description": "1000 gold for account example",
          "amount": 10,
          "quantity": 1,
          "imageUrl": "https://cdn.shop.example/gold.png"
        }
      ]
    }
  }
}

checkout.canceled有效负载

json
{
  "id": "whd_…",
  "type": "checkout.canceled",
  "created": "2026-08-14T12:20:00.000Z",
  "data": {
    "checkout": {
      "uid": "pcs_…",
      "status": "canceled",
      "amount": 10,
      "currency": "USD",
      "itemName": "Gold pack",
      "description": "1000 gold for account example",
      "invoiceId": "inv-12345",
      "source": "api",
      "orderUid": null,
      "hostedUrl": "https://rmt.gg/pay/pcs_…",
      "email": "[email protected]",
      "paidAt": null,
      "expiresAt": "2026-08-15T12:00:00.000Z",
      "createdAt": "2026-08-14T12:00:00.000Z",
      "reason": "buyer_canceled",
      "items": [
        {
          "name": "Gold pack",
          "description": "1000 gold for account example",
          "amount": 10,
          "quantity": 1,
          "imageUrl": "https://cdn.shop.example/gold.png"
        }
      ]
    }
  }
}

验证 Webhook 签名

当设置签名密钥时,计算 HMAC-SHA256 以 timestamp + '.' + rawBody,并与 v1= 后的十六进制值进行比较。

密钥保留在 RMT。每个签名的 POST 包含 X-RMT-Timestamp(Unix 秒)和 X-RMT-Signature(v1=加上十六进制)。使用你的密钥对字符串 timestamp + '.' + rawBody 计算 HMAC-SHA256,然后与 v1= 后的十六进制进行比较。拒绝超过 5 分钟的时间戳。

  • 准确读取接收到的原始字节。不要解析 JSON 并在哈希之前重新序列化。
  • 将 X-RMT-Timestamp 头部值用作时间戳前缀(相同字符串,不进行格式化)。
  • 使用安全的时间比较检查进行比较。当配置了密钥时,拒绝缺失或不匹配的签名请求。
  • 拒绝超过 5 分钟的时间戳以限制重放。相同的方案适用于 reserve.item 和出站订单或结账事件。

TypeScript 验证(时间安全比较和 5 分钟重放窗口)

typescript
import { createHmac, timingSafeEqual } from "node:crypto";

const MAX_AGE_SEC = 5 * 60; // reject replays older than 5 minutes

export function verifyRmtSignature(opts: {
  secret: string;
  timestamp: string | null | undefined;
  signatureHeader: string | null | undefined;
  rawBody: string; // exact POST bytes. Do not JSON.parse then re-stringify.
  nowSec?: number;
}): boolean {
  const secret = opts.secret.trim();
  const timestamp = String(opts.timestamp ?? "").trim();
  const provided = String(opts.signatureHeader ?? "").trim().replace(/^v1=/i, "");
  if (!secret || !timestamp || !provided) return false;

  const ts = Number(timestamp);
  if (!Number.isInteger(ts) || ts <= 0) return false;
  const nowSec = opts.nowSec ?? Math.floor(Date.now() / 1000);
  if (Math.abs(nowSec - ts) > MAX_AGE_SEC) return false;

  const expected = createHmac("sha256", secret)
    .update(`${timestamp}.${opts.rawBody}`)
    .digest("hex");

  const a = Buffer.from(expected, "utf8");
  const b = Buffer.from(provided.toLowerCase(), "utf8");
  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}

// Express / Node HTTP example:
// const rawBody = (req as { rawBody?: string }).rawBody
//   ?? JSON.stringify(req.body); // only if you captured the raw string first
// const ok = verifyRmtSignature({
//   secret: process.env.RMT_WEBHOOK_SECRET!,
//   timestamp: req.headers["x-rmt-timestamp"] as string,
//   signatureHeader: req.headers["x-rmt-signature"] as string,
//   rawBody,
// });
// if (!ok) return res.status(401).end();

TypeScript webhook 处理程序

typescript
type CheckoutCompleted = {
  id: string;
  type: "checkout.completed";
  created: string;
  data: {
    checkout: {
      uid: string;
      status: "paid";
      amount: number;
      currency: string;
      itemName: string | null;
      description: string;
      invoiceId: string | null;
      source: string | null;
      orderUid: string | null;
      hostedUrl: string;
      email: string | null;
      paidAt: string | null;
      expiresAt: string | null;
      createdAt: string | null;
      reason: null;
      items: Array<{
        name: string;
        description: string | null;
        amount: number;
        quantity: number;
        imageUrl: string | null;
      }>;
    };
  };
};

type CheckoutCanceled = {
  type: "checkout.canceled";
  data: {
    checkout: {
      uid: string;
      status: "canceled" | "expired";
      invoiceId: string | null;
      reason: "buyer_canceled" | "expired";
    };
  };
};

export async function handleRmtWebhook(rawBody: string, headers: Headers) {
  const ok = verifyRmtSignature({
    secret: process.env.RMT_WEBHOOK_SECRET!,
    timestamp: headers.get("x-rmt-timestamp"),
    signatureHeader: headers.get("x-rmt-signature"),
    rawBody,
  });
  if (!ok) throw new Response("Unauthorized", { status: 401 });

  const event = JSON.parse(rawBody) as { type: string; data: Record<string, unknown> };
  switch (event.type) {
    case "checkout.completed": {
      const checkout = (event as CheckoutCompleted).data.checkout;
      if (!checkout.invoiceId || !checkout.paidAt) break;
      await fulfillShopOrder(checkout.invoiceId, checkout.orderUid);
      break;
    }
    case "checkout.canceled": {
      const checkout = (event as CheckoutCanceled).data.checkout;
      await markShopOrderCanceled(checkout.invoiceId, checkout.reason);
      break;
    }
    case "checkout.refunded":
    case "order.paid":
    case "order.delivered":
      break;
    default:
      break;
  }
}

保留 Webhook(库存补充)

对于 COMPLEX(唯一单位)产品,RMT 可以在付款后向您的 HTTPS 端点发送 POST,以在本地库存不足时铸造下一个许可证、账户或密钥。

付款安全失败

如果您的端点超时或返回无效数据,订单将保持为已付款。买方将被收费;您将在订单上看到错误,并可以重试保留或手动附加密钥。

如何设置

  1. 创建一个复杂的产品列表,包含物品字段(例如许可证)。
  2. 在物品步骤中,启用按需库存端点并粘贴您的公共 HTTPS URL。
  3. 可选择设置签名密钥,以便 RMT 在每次调用时发送 X-RMT-Timestamp 和 X-RMT-Signature。
  4. 运行测试(或粘贴示例 JSON),将响应路径映射到物品字段,然后保存。
  5. 发布列表。买家可以在本地库存为空的情况下购买;密钥在付款后创建。
  • 始终优先使用本地库存;Webhook 仅填补短缺部分。
  • 在产品编辑器的项目步骤中配置产品级默认值,或按定价选项覆盖。
  • 仅限 HTTPS。可选 HMAC 签名与出站 Webhook 匹配(X-RMT-Event: reserve.item)。
  • 在编辑器中测试发送 dryRun: true。在订单页面上,修复端点后使用重试保留。

规范 POST 体(截断)

json
{
  "id": "rsv_…",
  "type": "reserve.item",
  "order": { "uid": "ord_…", "reference": "RMT-…", "url": "https://rmt.gg/orders/ord_…" },
  "offer": { "url": "my-offer", "title": "Game key", "pageUrl": "https://rmt.gg/offers/my-offer" },
  "option": { "id": 1, "name": "Standard" },
  "fields": [{ "id": 10, "name": "License", "type": "text", "required": true }],
  "quantity": 1
}

请求头部(当设置了签名密钥时)

json
{
  "Content-Type": "application/json",
  "X-RMT-Event": "reserve.item",
  "X-RMT-Delivery": "rsv_…",
  "X-RMT-Timestamp": "1710000000",
  "X-RMT-Signature": "v1=abc123…"
}

便捷响应

json
{
  "entries": [
    { "name": "License", "value": "AAAA-BBBB-CCCC" }
  ]
}

映射的 JSON 字段(响应映射路径如 $.license)

json
{
  "license": "AAAA-BBBB-CCCC",
  "email": "[email protected]",
  "password": "temporary-pass"
}

如何验证签名密钥

如果您在产品列表上设置了密钥,则每个 reserve POST 都会被签名。重新计算 HMAC-SHA256(secret, timestamp + '.' + rawBody),并在去掉 v1= 前缀后与 X-RMT-Signature 进行比较。密钥本身从不包含在请求中。

查看完整的验证示例

TypeScript 预留处理程序(验证,然后返回条目)

typescript
type ReserveRequest = {
  id: string;
  type: "reserve.item";
  dryRun?: boolean;
  quantity: number;
  fields: Array<{ name: string; required?: boolean }>;
};

export async function handleReserve(rawBody: string, headers: Headers) {
  const ok = verifyRmtSignature({
    secret: process.env.RMT_RESERVE_SECRET!,
    timestamp: headers.get("x-rmt-timestamp"),
    signatureHeader: headers.get("x-rmt-signature"),
    rawBody,
  });
  if (!ok) return new Response("Unauthorized", { status: 401 });

  const body = JSON.parse(rawBody) as ReserveRequest;
  if (body.type !== "reserve.item") {
    return Response.json({ error: "Unexpected event" }, { status: 400 });
  }

  const qty = Number(body.quantity);
  if (!Number.isInteger(qty) || qty < 1) {
    return Response.json({ error: "Invalid quantity" }, { status: 400 });
  }

  if (body.dryRun) {
    return Response.json({
      entries: [{ name: "License", value: "TEST-AAAA-BBBB" }],
    });
  }

  const license = await mintLicense(); // your inventory
  return Response.json({
    entries: [{ name: "License", value: license }],
  });
}

付款前请勿调用保留

RMT 仅在付款成功后调用您的端点,因此放弃的结账不会消耗许可证。

错误和速率限制

错误返回 JSON { error, code? }。开放 API 流量限制为每个 API 密钥每分钟 300 次请求。

  • API_KEY_REQUIRED
    401

    缺少 Authorization 或 X-Api-Key 头部。

  • API_KEY_INVALID
    401

    密钥未知、已撤销、已过期或开发者访问已暂停。

  • SCOPE_MISSING
    403

    密钥缺少端点所需的作用域。

  • RATE_LIMITED
    429

    请求过多。请遵循 Retry-After 和 X-RateLimit-Reset。

  • CHECKOUT_PARTNER_NOT_APPROVED
    403

    此卖家未获得托管结账的批准。

  • INVALID_JSON
    400

    请求体必须是JSON。

  • INVALID_AMOUNT
    400

    金额必须大于 0 且最多为 1,000,000。

  • UNSUPPORTED_CURRENCY
    400

    货币不是支持的 ISO 代码。

  • INVALID_RETURN_URL
    400

    returnUrl 和 cancelUrl 必须是 https(http://localhost 允许用于本地商店)。

  • INVALID_PSP_CATEGORY
    400

    categorySlug 和 offering 必须一起发送并匹配目录对。

  • INVALID_INVOICE_ID
    400

    invoiceId超过128个字符。

  • INVOICE_ID_REQUIRED
    400

    GET /checkout/sessions需要invoiceId作为查询参数。

  • INVALID_IDEMPOTENCY_KEY
    400

    Idempotency-Key超过128个字符。

  • INVALID_METADATA
    400

    metadata必须是JSON对象,而不是数组或原始类型。

  • METADATA_TOO_LARGE
    400

    序列化的metadata超过4096个字符。

  • IDEMPOTENCY_CONFLICT
    409

    Idempotency-Key 与不同的金额、货币或物品重复使用。

  • INVOICE_CONFLICT
    409

    invoiceId 与不同的金额、货币或物品重复使用。

  • INVALID_IMAGE_URL
    400

    imageUrl 必须是一个 https URL。

  • ITEM_NAME_REQUIRED
    400

    当未提供物品时,itemName(或标题)是必需的。

  • INVALID_ITEMS
    400

    items必须是一个非空的锁定行项目数组(最多20个)。每一行需要name和amount。

  • TOO_MANY_ITEMS
    400

    items 不能包含超过 20 行。

  • AMOUNT_MISMATCH
    400

    amount 必须等于每行金额乘以数量的总和。

  • INVALID_DELIVERY
    400

    交付字段无效。每个字段需要一个名称(最多80个字符)和一个值(最多2048个字符)。类型必须是text,password或textarea(默认为text)。每行最多16个字段。

  • ITEMS_TOO_LARGE
    400

    序列化的items JSON大于48,000个字符。

  • NOT_FOUND
    404

    没有托管结账会话与该uid或invoiceId匹配此卖家。

  • RESERVE_FAILED
    400

    保留 Webhook 超时、返回无效数据或缺少必填字段。

  • OPTION_AMBIGUOUS
    409

    多个定价选项与该名称匹配。请从 GET stock 中传递 optionId。

  • OPTION_NOT_FOUND
    404

    没有定价选项与此列表上的 ID 或名称匹配。

  • OPTION_REQUIRED
    400

    此列表有多个定价选项。请传递 option 或 optionId。

  • UNKNOWN_FIELD
    400

    字段名称与此列表的交付架构不匹配。

  • FIELD_MAPPING_AMBIGUOUS
    400

    无法将列或键映射到交付字段。发送头,或使用按字段名称键入的项目对象。

  • STOCK_MODE_MISMATCH
    400

    该有效负载与选项的库存模式(数量与保存的物品)不匹配。

  • IMPORT_TOO_LARGE
    400

    补货请求每个选项最多可导入 1,000 个保存的物品。

  • OPTION_ITEM_CAPACITY
    400

    此定价选项已经达到最大 5,000 个未售出的保存物品。

  • DUPLICATE_ITEMS
    409

    onDuplicate=error,且至少有一个物品已存在于此选项中。

  • UNLIMITED_STOCK
    400

    此选项具有无限数量。请先使用 set 切换到有限数量。

  • INSUFFICIENT_STOCK
    400

    没有足够的库存数量可供移除。

  • STOCK_HELD_IN_CHECKOUT
    400

    无法将数量降低到当前在结账中保留的单位以下。

  • INVALID_RESTOCK
    400

    补货主体缺少必需的操作,或在一个选项中组合了 add/items。

处理 429

使用 Retry-After 秒数进行退避。不要旋转密钥以绕过限制;限制是针对每个密钥的,并且对所有卖家是统一的。

成功响应包括 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset。

准备好自动化了吗?

在开发者设置中创建一个密钥,并在通知下连接Discord或Telegram。