Create keys and channels
Open Settings → Developer for marketplace API keys and JSON webhooks. For hosted checkout, create the key and checkout.completed webhook on Settings → Hosted checkout. Open Settings → Notifications to connect Discord or Telegram order alerts.
- Keys are scoped to your seller account and can be revoked anytime.
- Open API traffic is rate-limited to 300 requests per minute for every seller.
- GET /api/v1 returns discovery metadata for available resources.
Authenticate and call the API
Send Authorization: Bearer with your live secret key (or X-Api-Key). Prefer HTTPS only. Never embed keys in public clients. Each key carries scopes that gate endpoints.
- offers:read: list and get offers.
- offers:write: create, update, publish, and delete offers.
- orders:read: list and get seller orders.
- orders:write: mark orders delivered.
- checkout:write: create and read hosted checkout sessions (approved partners).
Authenticated discovery
curl -H "Authorization: Bearer rmt_sk_live_…" https://rmt.gg/api/v1Rotate keys
If a key leaks, revoke it in Developer settings and create a new one. Update your automation before revoking if you are live.
Open API endpoint map
Base path is /api/v1. Successful responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. GET /api/v1 returns a machine-readable operations catalog that matches this article.
- GET /api/v1: discovery (any valid key).
- GET /api/v1/offers: list offers (offers:read).
- POST /api/v1/offers: create draft (offers:write).
- GET /api/v1/offers/:urlOrId: get offer (offers:read).
- PATCH /api/v1/offers/:urlOrId: update offer fields (offers:write).
- DELETE /api/v1/offers/:urlOrId: delete or archive (offers:write).
- POST /api/v1/offers/:urlOrId/publish: publish (offers:write).
- GET /api/v1/orders: list sales (orders:read).
- GET /api/v1/orders/:uid: get order (orders:read).
- POST /api/v1/orders/:uid/deliver: mark delivered (orders:write).
- POST /api/v1/checkout/sessions: create a hosted checkout session (checkout:write).
- GET /api/v1/checkout/sessions/:uid: get a hosted checkout session (checkout:write).
Print the live operations catalog
curl -s -H "Authorization: Bearer rmt_sk_live_…" https://rmt.gg/api/v1 | jq ".operations"Offers API
Offer identifiers accept the public url slug or numeric id. Responses omit internal id and sellerId. Stock rows, option prices, media, and attributes are managed in the seller editor (or future endpoints), not via PATCH yet.
List active offers
curl -H "Authorization: Bearer rmt_sk_live_…" "https://rmt.gg/api/v1/offers?archive=active"Create a draft offer
curl -X POST -H "Authorization: Bearer rmt_sk_live_…" https://rmt.gg/api/v1/offersGet one offer with relations
curl -H "Authorization: Bearer rmt_sk_live_…" https://rmt.gg/api/v1/offers/YOUR_OFFER_URLUpdate allowed fields
curl -X PATCH -H "Authorization: Bearer rmt_sk_live_…" -H "Content-Type: application/json" https://rmt.gg/api/v1/offers/YOUR_OFFER_URL -d @body.jsonAllowed PATCH body fields
{
"title": "Updated title",
"description": "Buyer-facing description",
"visibility": "PUBLIC",
"categoryId": 12,
"offeringId": 34,
"thumbnail": "https://…",
"offerType": "ACCOUNT",
"listingMode": "STANDARD"
}Publish (default PUBLIC)
curl -X POST -H "Authorization: Bearer rmt_sk_live_…" -H "Content-Type: application/json" https://rmt.gg/api/v1/offers/YOUR_OFFER_URL/publish -d '{"visibility":"PUBLIC"}'Delete or archive
curl -X DELETE -H "Authorization: Bearer rmt_sk_live_…" https://rmt.gg/api/v1/offers/YOUR_OFFER_URLPublish requirements
Publish fails with 400 if required listing fields are incomplete (same validation as the offer editor). Successful updates can emit an offer.updated webhook.
Orders API
Orders are scoped to your seller account. Buyer billing details may be redacted. Use the public order uid (not the opaque reference alone) for get and deliver.
List recent paid sales
curl -H "Authorization: Bearer rmt_sk_live_…" "https://rmt.gg/api/v1/orders?status=PAID&limit=20&sort=newest"Get one order with line items
curl -H "Authorization: Bearer rmt_sk_live_…" https://rmt.gg/api/v1/orders/ORDER_UIDMark delivered
curl -X POST -H "Authorization: Bearer rmt_sk_live_…" -H "Content-Type: application/json" https://rmt.gg/api/v1/orders/ORDER_UID/deliver -d @evidence.jsonOptional evidence body
{
"evidence": [
"https://cdn.example.com/proof-1.png"
]
}Errors and rate limits
Errors return JSON { error, code? }. Rate limit is 300 requests per minute per API key.
- 401 API_KEY_REQUIRED or API_KEY_INVALID.
- 403 SCOPE_MISSING when the key lacks the endpoint scope.
- 404 Not found for offers or orders you do not own (same message either way).
- 429 RATE_LIMITED with Retry-After and X-RateLimit-* headers.
- 400 for validation failures (publish incomplete, deliver not allowed, empty PATCH).
Handle 429
Back off using Retry-After seconds. Do not rotate keys to bypass limits; the limit is per key and flat for all sellers.
Outbound order webhooks
Discord and Telegram alerts are configured in Settings → Notifications. Custom JSON HTTPS webhooks stay in Developer settings (not via /api/v1). Subscribe to order.paid, order.delivered, order.completed, order.refunded, order.disputed, offer.published, and offer.updated. Optional JSON signing uses X-RMT-Timestamp and X-RMT-Signature.
- Discord format posts rich embeds with an order link and offer name.
- JSON format posts a structured body including offer names and line items.
- If you set a secret, verify HMAC-SHA256 of timestamp.body equals the v1= signature hex.
- Delivery history appears under each endpoint so you can retry failures.
- Hosted checkout uses checkout.completed, checkout.canceled, and checkout.refunded. Marketplace sales keep order.paid and the other order.* events.
Example signed headers
{
"X-RMT-Event": "order.paid",
"X-RMT-Timestamp": "1710000000",
"X-RMT-Signature": "v1=abc123…"
}Verify signatures
Compute HMAC-SHA256 over the string timestamp + "." + rawBody using your endpoint secret. Compare to the hex after v1=.
Node.js sketch
import crypto from "crypto";
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const ok = expected === signature.replace(/^v1=/, "");